mt_circular_queue.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #ifndef MT_CIRCULAR_QUEUE_H
  2. #define MT_CIRCULAR_QUEUE_H
  3. #include "circular_queue.h"
  4. #include "lock.h"
  5. #include "cond.h"
  6. template <class T> class MTCircularQueue : public CircularQueue<T>
  7. {
  8. private:
  9. Lock m_lock;
  10. ConditionVariable m_full;
  11. ConditionVariable m_empty;
  12. public:
  13. class iterator {
  14. public:
  15. // NOTE: unless we add locking, iterating over a MTCircularQueue which can be updated by another thread is unsafe!
  16. iterator(const MTCircularQueue &queue, UInt32 idx) = 0;
  17. };
  18. MTCircularQueue(UInt32 size = 64) : CircularQueue<T>(size) {}
  19. void push(const T& t);
  20. void push_wait(const T& t);
  21. void push_locked(const T& t);
  22. T pop(void);
  23. T pop_wait(void);
  24. T pop_locked(void);
  25. void full_wait(void);
  26. void empty_wait(void);
  27. void full_wait_locked(void);
  28. void empty_wait_locked(void);
  29. };
  30. template <class T>
  31. void
  32. MTCircularQueue<T>::full_wait(void)
  33. {
  34. ScopedLock sl(m_lock);
  35. full_wait_locked();
  36. }
  37. template <class T>
  38. void
  39. MTCircularQueue<T>::full_wait_locked(void)
  40. {
  41. while(CircularQueue<T>::full())
  42. m_full.wait(m_lock);
  43. }
  44. template <class T>
  45. void
  46. MTCircularQueue<T>::empty_wait(void)
  47. {
  48. ScopedLock sl(m_lock);
  49. empty_wait_locked();
  50. }
  51. template <class T>
  52. void
  53. MTCircularQueue<T>::empty_wait_locked()
  54. {
  55. while(CircularQueue<T>::empty())
  56. m_empty.wait(m_lock);
  57. }
  58. template <class T>
  59. void
  60. MTCircularQueue<T>::push_locked(const T& t)
  61. {
  62. bool wasEmpty = CircularQueue<T>::empty();
  63. CircularQueue<T>::push(t);
  64. if (wasEmpty)
  65. m_empty.signal();
  66. }
  67. template <class T>
  68. void
  69. MTCircularQueue<T>::push(const T& t)
  70. {
  71. ScopedLock sl(m_lock);
  72. push_locked(t);
  73. }
  74. template <class T>
  75. void
  76. MTCircularQueue<T>::push_wait(const T& t)
  77. {
  78. ScopedLock sl(m_lock);
  79. full_wait_locked();
  80. push_locked(t);
  81. }
  82. template <class T>
  83. T
  84. MTCircularQueue<T>::pop_locked()
  85. {
  86. bool wasFull = CircularQueue<T>::full();
  87. T t = CircularQueue<T>::pop();
  88. if (wasFull)
  89. m_full.signal();
  90. return t;
  91. }
  92. template <class T>
  93. T
  94. MTCircularQueue<T>::pop()
  95. {
  96. ScopedLock sl(m_lock);
  97. return pop_locked();
  98. }
  99. template <class T>
  100. T
  101. MTCircularQueue<T>::pop_wait()
  102. {
  103. ScopedLock sl(m_lock);
  104. empty_wait_locked();
  105. return pop_locked();
  106. }
  107. #endif //MT_CIRCULAR_QUEUE_H