mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-08 04:27:12 +03:00
117 lines
3.8 KiB
C++
117 lines
3.8 KiB
C++
#ifndef BELL_QUEUE_H
|
|
#define BELL_QUEUE_H
|
|
|
|
#include <queue>
|
|
#include <atomic>
|
|
#include <condition_variable>
|
|
#include <atomic>
|
|
|
|
namespace bell
|
|
{
|
|
template <typename dataType>
|
|
class Queue
|
|
{
|
|
private:
|
|
/// Queue
|
|
std::queue<dataType> m_queue;
|
|
/// Mutex to controll multiple access
|
|
mutable std::mutex m_mutex;
|
|
/// Conditional variable used to fire event
|
|
std::condition_variable m_cv;
|
|
/// Atomic variable used to terminate immediately wpop and wtpop functions
|
|
std::atomic<bool> m_forceExit = false;
|
|
|
|
public:
|
|
/// <summary> Add a new element in the queue. </summary>
|
|
/// <param name="data"> New element. </param>
|
|
void push(dataType const &data)
|
|
{
|
|
m_forceExit.store(false);
|
|
std::unique_lock<std::mutex> lk(m_mutex);
|
|
m_queue.push(data);
|
|
lk.unlock();
|
|
m_cv.notify_one();
|
|
}
|
|
/// <summary> Check queue empty. </summary>
|
|
/// <returns> True if the queue is empty. </returns>
|
|
bool isEmpty() const
|
|
{
|
|
std::unique_lock<std::mutex> lk(m_mutex);
|
|
return m_queue.empty();
|
|
}
|
|
/// <summary> Pop element from queue. </summary>
|
|
/// <param name="popped_value"> [in,out] Element. </param>
|
|
/// <returns> false if the queue is empty. </returns>
|
|
bool pop(dataType &popped_value)
|
|
{
|
|
std::unique_lock<std::mutex> lk(m_mutex);
|
|
if (m_queue.empty())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
popped_value = m_queue.front();
|
|
m_queue.pop();
|
|
return true;
|
|
}
|
|
}
|
|
/// <summary> Wait and pop an element in the queue. </summary>
|
|
/// <param name="popped_value"> [in,out] Element. </param>
|
|
/// <returns> False for forced exit. </returns>
|
|
bool wpop(dataType &popped_value)
|
|
{
|
|
std::unique_lock<std::mutex> lk(m_mutex);
|
|
m_cv.wait(lk, [&]() -> bool
|
|
{ return !m_queue.empty() || m_forceExit.load(); });
|
|
if (m_forceExit.load())
|
|
return false;
|
|
popped_value = m_queue.front();
|
|
m_queue.pop();
|
|
return true;
|
|
}
|
|
/// <summary> Timed wait and pop an element in the queue. </summary>
|
|
/// <param name="popped_value"> [in,out] Element. </param>
|
|
/// <param name="milliseconds"> [in] Wait time. </param>
|
|
/// <returns> False for timeout or forced exit. </returns>
|
|
bool wtpop(dataType &popped_value, long milliseconds = 1000)
|
|
{
|
|
std::unique_lock<std::mutex> lk(m_mutex);
|
|
m_cv.wait_for(lk, std::chrono::milliseconds(milliseconds), [&]() -> bool
|
|
{ return !m_queue.empty() || m_forceExit.load(); });
|
|
if (m_forceExit.load())
|
|
return false;
|
|
if (m_queue.empty())
|
|
return false;
|
|
popped_value = m_queue.front();
|
|
m_queue.pop();
|
|
return true;
|
|
}
|
|
/// <summary> Queue size. </summary>
|
|
int size()
|
|
{
|
|
std::unique_lock<std::mutex> lk(m_mutex);
|
|
return static_cast<int>(m_queue.size());
|
|
}
|
|
/// <summary> Free the queue and force stop. </summary>
|
|
void clear()
|
|
{
|
|
m_forceExit.store(true);
|
|
std::unique_lock<std::mutex> lk(m_mutex);
|
|
while (!m_queue.empty())
|
|
{
|
|
//delete m_queue.front();
|
|
m_queue.pop();
|
|
}
|
|
lk.unlock();
|
|
m_cv.notify_one();
|
|
}
|
|
/// <summary> Check queue in forced exit state. </summary>
|
|
bool isExit() const
|
|
{
|
|
return m_forceExit.load();
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif |