spscqueue.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright 2010-2012 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef __BX_SPSCQUEUE_H__
  6. #define __BX_SPSCQUEUE_H__
  7. #include <list>
  8. #include "bx.h"
  9. #include "cpu.h"
  10. #include "mutex.h"
  11. #include "uint32_t.h"
  12. namespace bx
  13. {
  14. // http://drdobbs.com/article/print?articleId=210604448&siteSectionName=
  15. template <typename Ty>
  16. class SpScUnboundedQueueLf
  17. {
  18. BX_CLASS_NO_COPY_NO_ASSIGNMENT(SpScUnboundedQueueLf);
  19. public:
  20. SpScUnboundedQueueLf()
  21. : m_first(new Node(NULL) )
  22. , m_divider(m_first)
  23. , m_last(m_first)
  24. {
  25. }
  26. ~SpScUnboundedQueueLf()
  27. {
  28. while (NULL != m_first)
  29. {
  30. Node* node = m_first;
  31. m_first = node->m_next;
  32. delete node;
  33. }
  34. }
  35. void push(Ty* _ptr) // producer only
  36. {
  37. m_last->m_next = new Node( (void*)_ptr);
  38. atomicExchangePtr( (void**)&m_last, m_last->m_next);
  39. while (m_first != m_divider)
  40. {
  41. Node* node = m_first;
  42. m_first = m_first->m_next;
  43. delete node;
  44. }
  45. }
  46. Ty* peek() // consumer only
  47. {
  48. if (m_divider != m_last)
  49. {
  50. Ty* ptr = (Ty*)m_divider->m_next->m_ptr;
  51. return ptr;
  52. }
  53. return NULL;
  54. }
  55. Ty* pop() // consumer only
  56. {
  57. if (m_divider != m_last)
  58. {
  59. Ty* ptr = (Ty*)m_divider->m_next->m_ptr;
  60. atomicExchangePtr( (void**)&m_divider, m_divider->m_next);
  61. return ptr;
  62. }
  63. return NULL;
  64. }
  65. private:
  66. struct Node
  67. {
  68. Node(void* _ptr)
  69. : m_ptr(_ptr)
  70. , m_next(NULL)
  71. {
  72. }
  73. void* m_ptr;
  74. Node* m_next;
  75. };
  76. Node* m_first;
  77. Node* m_divider;
  78. Node* m_last;
  79. };
  80. template<typename Ty>
  81. class SpScUnboundedQueueMutex
  82. {
  83. BX_CLASS_NO_COPY_NO_ASSIGNMENT(SpScUnboundedQueueMutex);
  84. public:
  85. SpScUnboundedQueueMutex()
  86. {
  87. }
  88. ~SpScUnboundedQueueMutex()
  89. {
  90. BX_CHECK(m_queue.empty(), "Queue is not empty!");
  91. }
  92. void push(Ty* _item)
  93. {
  94. bx::LwMutexScope lock(m_mutex);
  95. m_queue.push_back(_item);
  96. }
  97. Ty* peek()
  98. {
  99. bx::LwMutexScope lock(m_mutex);
  100. if (!m_queue.empty() )
  101. {
  102. return m_queue.front();
  103. }
  104. return NULL;
  105. }
  106. Ty* pop()
  107. {
  108. bx::LwMutexScope lock(m_mutex);
  109. if (!m_queue.empty() )
  110. {
  111. Ty* item = m_queue.front();
  112. m_queue.pop_front();
  113. return item;
  114. }
  115. return NULL;
  116. }
  117. private:
  118. bx::LwMutex m_mutex;
  119. std::list<Ty*> m_queue;
  120. };
  121. #if BX_CONFIG_SPSCQUEUE_USE_MUTEX
  122. # define SpScUnboundedQueue SpScUnboundedQueueMutex
  123. #else
  124. # define SpScUnboundedQueue SpScUnboundedQueueLf
  125. #endif // BX_CONFIG_SPSCQUEUE_USE_MUTEX
  126. template <typename Ty>
  127. class SpScBlockingUnboundedQueue
  128. {
  129. BX_CLASS_NO_COPY_NO_ASSIGNMENT(SpScBlockingUnboundedQueue);
  130. public:
  131. SpScBlockingUnboundedQueue()
  132. {
  133. }
  134. ~SpScBlockingUnboundedQueue()
  135. {
  136. }
  137. void push(Ty* _ptr) // producer only
  138. {
  139. m_queue.push( (void*)_ptr);
  140. m_count.post();
  141. }
  142. Ty* peek() // consumer only
  143. {
  144. return (Ty*)m_queue.peek();
  145. }
  146. Ty* pop(int32_t _msecs = -1) // consumer only
  147. {
  148. if (m_count.wait(_msecs) )
  149. {
  150. return (Ty*)m_queue.pop();
  151. }
  152. return NULL;
  153. }
  154. private:
  155. Semaphore m_count;
  156. SpScUnboundedQueue<void> m_queue;
  157. };
  158. } // namespace bx
  159. #endif // __BX_RINGBUFFER_H__