#ifndef BELL_QUEUE_H #define BELL_QUEUE_H #include #include #include #include namespace bell { template class Queue { private: /// Queue std::queue 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 m_forceExit = false; public: /// Add a new element in the queue. /// New element. void push(dataType const &data) { m_forceExit.store(false); std::unique_lock lk(m_mutex); m_queue.push(data); lk.unlock(); m_cv.notify_one(); } /// Check queue empty. /// True if the queue is empty. bool isEmpty() const { std::unique_lock lk(m_mutex); return m_queue.empty(); } /// Pop element from queue. /// [in,out] Element. /// false if the queue is empty. bool pop(dataType &popped_value) { std::unique_lock lk(m_mutex); if (m_queue.empty()) { return false; } else { popped_value = m_queue.front(); m_queue.pop(); return true; } } /// Wait and pop an element in the queue. /// [in,out] Element. /// False for forced exit. bool wpop(dataType &popped_value) { std::unique_lock 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; } /// Timed wait and pop an element in the queue. /// [in,out] Element. /// [in] Wait time. /// False for timeout or forced exit. bool wtpop(dataType &popped_value, long milliseconds = 1000) { std::unique_lock 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; } /// Queue size. int size() { std::unique_lock lk(m_mutex); return static_cast(m_queue.size()); } /// Free the queue and force stop. void clear() { m_forceExit.store(true); std::unique_lock lk(m_mutex); while (!m_queue.empty()) { //delete m_queue.front(); m_queue.pop(); } lk.unlock(); m_cv.notify_one(); } /// Check queue in forced exit state. bool isExit() const { return m_forceExit.load(); } }; } #endif