mirror of
https://github.com/gwm17/DaqGrimoire.git
synced 2024-11-23 11:18:49 -05:00
128 lines
2.3 KiB
C
128 lines
2.3 KiB
C
|
#ifndef THREAD_SAFE_QUEUE_H
|
||
|
#define THREAD_SAFE_QUEUE_H
|
||
|
|
||
|
|
||
|
#include <deque>
|
||
|
#include <mutex>
|
||
|
#include <thread>
|
||
|
#include <condition_variable>
|
||
|
#include <atomic>
|
||
|
|
||
|
namespace DaqGrimoire {
|
||
|
|
||
|
template<typename T>
|
||
|
class ThreadSafeQueue
|
||
|
{
|
||
|
public:
|
||
|
ThreadSafeQueue() = default;
|
||
|
ThreadSafeQueue(const ThreadSafeQueue&) = delete; //no copy
|
||
|
~ThreadSafeQueue() { Clear(); }
|
||
|
|
||
|
void PushBack(const T& data)
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
m_queue.push_back(data);
|
||
|
|
||
|
std::scoped_lock<std::mutex> condGuard(m_conditionMutex);
|
||
|
m_conditional.notify_one();
|
||
|
}
|
||
|
|
||
|
void PushFront(const T& data)
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
m_queue.push_front(data);
|
||
|
|
||
|
std::scoped_lock<std::mutex> conditionGuard(m_conditionMutex);
|
||
|
m_conditional.notify_one();
|
||
|
}
|
||
|
|
||
|
void PopBack()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
m_queue.pop_back();
|
||
|
}
|
||
|
|
||
|
void PopFront()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
m_queue.pop_front();
|
||
|
}
|
||
|
|
||
|
const T& Front()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
return m_queue.front();
|
||
|
}
|
||
|
|
||
|
const T& Back()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
return m_queue.back();
|
||
|
}
|
||
|
|
||
|
std::size_t Size()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
return m_queue.size();
|
||
|
}
|
||
|
|
||
|
bool IsEmpty()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
return m_queue.empty();
|
||
|
}
|
||
|
|
||
|
void Clear()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
m_queue.clear();
|
||
|
}
|
||
|
|
||
|
//For iterator loops, need begin()/end() idiom
|
||
|
|
||
|
std::deque<T>::iterator begin()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
return m_queue.begin();
|
||
|
}
|
||
|
|
||
|
std::deque<T>::iterator end()
|
||
|
{
|
||
|
std::scoped_lock<std::mutex> guard(m_queueMutex);
|
||
|
return m_queue.end();
|
||
|
}
|
||
|
|
||
|
void Wait()
|
||
|
{
|
||
|
while (IsEmpty() && !m_isForceWakeup)
|
||
|
{
|
||
|
std::unique_lock<std::mutex> guard(m_conditionMutex);
|
||
|
m_conditional.wait(guard);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ForceWakeup()
|
||
|
{
|
||
|
m_isForceWakeup = true;
|
||
|
|
||
|
std::unique_lock<std::mutex> guard(m_conditionMutex);
|
||
|
m_conditional.notify_one();
|
||
|
}
|
||
|
|
||
|
void ResetWakeup()
|
||
|
{
|
||
|
m_isForceWakeup = false;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
std::mutex m_queueMutex;
|
||
|
std::deque<T> m_queue;
|
||
|
|
||
|
std::mutex m_conditionMutex;
|
||
|
std::condition_variable m_conditional;
|
||
|
|
||
|
std::atomic<bool> m_isForceWakeup = false;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#endif
|