1
0
Fork 0
mirror of https://github.com/gwm17/DaqGrimoire.git synced 2024-11-26 20:28:51 -05:00
DaqGrimoire/include/NetIO/ThreadSafeQueue.h
2022-09-29 20:36:44 -04:00

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