Queue.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #ifndef BELL_QUEUE_H
  2. #define BELL_QUEUE_H
  3. #include <atomic>
  4. #include <condition_variable>
  5. #include <queue>
  6. namespace bell {
  7. template <typename dataType>
  8. class Queue {
  9. private:
  10. /// Queue
  11. std::queue<dataType> m_queue;
  12. /// Mutex to controll multiple access
  13. mutable std::mutex m_mutex;
  14. /// Conditional variable used to fire event
  15. std::condition_variable m_cv;
  16. /// Atomic variable used to terminate immediately wpop and wtpop functions
  17. std::atomic<bool> m_forceExit = false;
  18. public:
  19. /// <summary> Add a new element in the queue. </summary>
  20. /// <param name="data"> New element. </param>
  21. void push(dataType const& data) {
  22. m_forceExit.store(false);
  23. std::unique_lock<std::mutex> lk(m_mutex);
  24. m_queue.push(data);
  25. lk.unlock();
  26. m_cv.notify_one();
  27. }
  28. /// <summary> Check queue empty. </summary>
  29. /// <returns> True if the queue is empty. </returns>
  30. bool isEmpty() const {
  31. std::unique_lock<std::mutex> lk(m_mutex);
  32. return m_queue.empty();
  33. }
  34. /// <summary> Pop element from queue. </summary>
  35. /// <param name="popped_value"> [in,out] Element. </param>
  36. /// <returns> false if the queue is empty. </returns>
  37. bool pop(dataType& popped_value) {
  38. std::unique_lock<std::mutex> lk(m_mutex);
  39. if (m_queue.empty()) {
  40. return false;
  41. } else {
  42. popped_value = m_queue.front();
  43. m_queue.pop();
  44. return true;
  45. }
  46. }
  47. /// <summary> Wait and pop an element in the queue. </summary>
  48. /// <param name="popped_value"> [in,out] Element. </param>
  49. /// <returns> False for forced exit. </returns>
  50. bool wpop(dataType& popped_value) {
  51. std::unique_lock<std::mutex> lk(m_mutex);
  52. m_cv.wait(lk,
  53. [&]() -> bool { return !m_queue.empty() || m_forceExit.load(); });
  54. if (m_forceExit.load())
  55. return false;
  56. popped_value = m_queue.front();
  57. m_queue.pop();
  58. return true;
  59. }
  60. /// <summary> Timed wait and pop an element in the queue. </summary>
  61. /// <param name="popped_value"> [in,out] Element. </param>
  62. /// <param name="milliseconds"> [in] Wait time. </param>
  63. /// <returns> False for timeout or forced exit. </returns>
  64. bool wtpop(dataType& popped_value, long milliseconds = 1000) {
  65. std::unique_lock<std::mutex> lk(m_mutex);
  66. m_cv.wait_for(lk, std::chrono::milliseconds(milliseconds), [&]() -> bool {
  67. return !m_queue.empty() || m_forceExit.load();
  68. });
  69. if (m_forceExit.load())
  70. return false;
  71. if (m_queue.empty())
  72. return false;
  73. popped_value = m_queue.front();
  74. m_queue.pop();
  75. return true;
  76. }
  77. /// <summary> Queue size. </summary>
  78. int size() {
  79. std::unique_lock<std::mutex> lk(m_mutex);
  80. return static_cast<int>(m_queue.size());
  81. }
  82. /// <summary> Free the queue and force stop. </summary>
  83. void clear() {
  84. m_forceExit.store(true);
  85. std::unique_lock<std::mutex> lk(m_mutex);
  86. while (!m_queue.empty()) {
  87. //delete m_queue.front();
  88. m_queue.pop();
  89. }
  90. lk.unlock();
  91. m_cv.notify_one();
  92. }
  93. /// <summary> Check queue in forced exit state. </summary>
  94. bool isExit() const { return m_forceExit.load(); }
  95. };
  96. } // namespace bell
  97. #endif