blob: 087b192cfc27dc3b1af4930e3fcdfa56a23e000d [file] [log] [blame]
/******************************************************************************
*
* Copyright 2016 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#pragma once
#include <memory>
#include <mutex>
#include <queue>
namespace bluetooth {
namespace common {
/*
* LeakyBondedQueue<T>
*
* - LeakyLondedQueue<T> is a fixed size queue that leaks oldest item when
* reaching its capacity. This is useful in creating memory bonded data
* structure where freshness is more important than full coverage.
* - The queue is protected by a simple mutex and is thread-safe, although
* improvements could be made to lock enqueue and dequeue separately, it
* is not implemented at this moment due to lack of demand
* - The queue uses unique_ptr to automatically free its content when it is
* destructed. It is the user's responsibility to implement T's destructor
* correctly.
*
*/
template <class T>
class LeakyBondedQueue {
public:
LeakyBondedQueue(size_t capacity);
/* Default destructor
*
* Call Clear() and free the queue structure itself
*/
~LeakyBondedQueue();
/*
* Add item NEW_ITEM to the underlining queue. If the queue is full, pop
* the oldest item
*/
void Enqueue(T* new_item);
/*
* Add item NEW_ITEM to the underlining queue. If the queue is full, dequeue
* the oldest item and returns it to the caller. Return nullptr otherwise.
*/
T* EnqueueWithPop(T* new_item);
/*
* Dequeues the oldest item from the queue. Return nullptr if queue is empty
*/
T* Dequeue();
/*
* Returns the length of queue
*/
size_t Length();
/*
* Returns the defined capacity of the queue
*/
size_t Capacity();
/*
* Returns whether the queue is empty
*/
bool Empty();
/*
* Pops all items from the queue
*/
void Clear();
private:
// Put item in unique_ptr so that they get freed automatically when poped or
// when queue_ is freed
std::queue<std::unique_ptr<T>> queue_;
std::mutex lock_;
size_t capacity_;
};
/*
* Definitions must be in the header for template classes
*/
template <class T>
LeakyBondedQueue<T>::LeakyBondedQueue(size_t capacity) {
capacity_ = capacity;
}
template <class T>
LeakyBondedQueue<T>::~LeakyBondedQueue() {}
template <class T>
void LeakyBondedQueue<T>::Enqueue(T* new_item) {
std::lock_guard<std::mutex> lock(lock_);
if ((queue_.size() + 1) > capacity_) {
queue_.pop();
}
std::unique_ptr<T> item_ptr(new_item);
queue_.push(std::move(item_ptr));
}
template <class T>
T* LeakyBondedQueue<T>::EnqueueWithPop(T* new_item) {
std::lock_guard<std::mutex> lock(lock_);
T* old_item = nullptr;
if ((queue_.size() + 1) > capacity_) {
std::unique_ptr<T> item = std::move(queue_.front());
queue_.pop();
old_item = item.release();
}
std::unique_ptr<T> item_ptr(new_item);
queue_.push(std::move(item_ptr));
return old_item;
}
template <class T>
T* LeakyBondedQueue<T>::Dequeue() {
std::lock_guard<std::mutex> lock(lock_);
std::unique_ptr<T> item = std::move(queue_.front());
queue_.pop();
return item.release();
}
template <class T>
void LeakyBondedQueue<T>::Clear() {
std::lock_guard<std::mutex> lock(lock_);
while (!queue_.empty()) {
// unique_ptr does not need to be freed
queue_.pop();
}
}
template <class T>
size_t LeakyBondedQueue<T>::Length() {
std::lock_guard<std::mutex> lock(lock_);
return queue_.size();
}
template <class T>
size_t LeakyBondedQueue<T>::Capacity() {
return capacity_;
}
template <class T>
bool LeakyBondedQueue<T>::Empty() {
std::lock_guard<std::mutex> lock(lock_);
return queue_.empty();
}
} // namespace common
} // namespace bluetooth