#ifndef UDPC_THREADSAFE_QUEUE_HPP #define UDPC_THREADSAFE_QUEUE_HPP #define UDPC_TSQUEUE_DEFAULT_CAPACITY 32 #include #include #include #include template class TSQueue { public: TSQueue(unsigned int capacity = UDPC_TSQUEUE_DEFAULT_CAPACITY); ~TSQueue(); // disable copy TSQueue(const TSQueue &other) = delete; TSQueue &operator=(const TSQueue &other) = delete; // enable move TSQueue(TSQueue &&other); TSQueue &operator=(TSQueue &&other); bool push(const T &data); T top(); bool pop(); void clear(); void changeCapacity(unsigned int newCapacity); unsigned int size(); unsigned int capacity(); bool empty(); private: std::mutex mutex; RB::RingBuffer rb; }; template TSQueue::TSQueue(unsigned int capacity) : mutex(), rb(capacity) { rb.setResizePolicy(false); } template TSQueue::TSQueue(TSQueue &&other) : TSQueue::TSQueue(other.rb.getCapacity()) { std::lock_guard lock(other.mutex); for(unsigned int i = 0; i < other.rb.getSize(); ++i) { rb.push(other.rb[i]); } } template TSQueue& TSQueue::operator =(TSQueue &&other) { std::scoped_lock lock(other.mutex, mutex); rb.resize(0); rb.changeCapacity(other.rb.getCapacity()); for(unsigned int i = 0; i < other.rb.getSize(); ++i) { rb.push(other.rb[i]); } } template TSQueue::~TSQueue() {} template bool TSQueue::push(const T &data) { std::lock_guard lock(mutex); if(rb.getSize() == rb.getCapacity()) { return false; } rb.push(data); return true; } template T TSQueue::top() { std::lock_guard lock(mutex); T value = rb.top(); return value; } template bool TSQueue::pop() { std::lock_guard lock(mutex); if(rb.empty()) { return false; } rb.pop(); return true; } template void TSQueue::clear() { std::lock_guard lock(mutex); rb.resize(0); } template void TSQueue::changeCapacity(unsigned int newCapacity) { std::lock_guard lock(mutex); rb.changeCapacity(newCapacity); } template unsigned int TSQueue::size() { std::lock_guard lock(mutex); unsigned int size = rb.getSize(); return size; } template unsigned int TSQueue::capacity() { std::lock_guard lock(mutex); unsigned int capacity = rb.getCapacity(); return capacity; } template bool TSQueue::empty() { // No lock required, since this is calling size() that uses a lock unsigned int size = this->size(); return size == 0; } #endif