fifo_queue.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #ifndef _FIFO_QUEUE_H_
  2. #define _FIFO_QUEUE_H_
  3. // a simple lockless thread-safe,
  4. // single reader, single writer queue
  5. #include "common/atomic.h"
  6. namespace Common
  7. {
  8. template <typename T>
  9. class FifoQueue
  10. {
  11. public:
  12. FifoQueue() : m_size(0)
  13. {
  14. m_write_ptr = m_read_ptr = new ElementPtr();
  15. }
  16. ~FifoQueue()
  17. {
  18. // this will empty out the whole queue
  19. delete m_read_ptr;
  20. }
  21. u32 Size() const
  22. {
  23. return m_size;
  24. }
  25. bool Empty() const
  26. {
  27. //return (m_read_ptr == m_write_ptr);
  28. return (0 == m_size);
  29. }
  30. T& Front() const
  31. {
  32. return *m_read_ptr->current;
  33. }
  34. template <typename Arg>
  35. void Push(Arg&& t)
  36. {
  37. // create the element, add it to the queue
  38. m_write_ptr->current = new T(std::forward<Arg>(t));
  39. // set the next pointer to a new element ptr
  40. // then advance the write pointer
  41. m_write_ptr = m_write_ptr->next = new ElementPtr();
  42. Common::AtomicIncrement(m_size);
  43. }
  44. void Pop()
  45. {
  46. Common::AtomicDecrement(m_size);
  47. ElementPtr *const tmpptr = m_read_ptr;
  48. // advance the read pointer
  49. m_read_ptr = m_read_ptr->next;
  50. // set the next element to NULL to stop the recursive deletion
  51. tmpptr->next = NULL;
  52. delete tmpptr; // this also deletes the element
  53. }
  54. bool Pop(T& t)
  55. {
  56. if (Empty())
  57. return false;
  58. t = std::move(Front());
  59. Pop();
  60. return true;
  61. }
  62. // not thread-safe
  63. void Clear()
  64. {
  65. m_size = 0;
  66. delete m_read_ptr;
  67. m_write_ptr = m_read_ptr = new ElementPtr();
  68. }
  69. private:
  70. // stores a pointer to element
  71. // and a pointer to the next ElementPtr
  72. class ElementPtr
  73. {
  74. public:
  75. ElementPtr() : current(NULL), next(NULL) {}
  76. ~ElementPtr()
  77. {
  78. if (current)
  79. {
  80. delete current;
  81. // recusion ftw
  82. if (next)
  83. delete next;
  84. }
  85. }
  86. T *volatile current;
  87. ElementPtr *volatile next;
  88. };
  89. ElementPtr *volatile m_write_ptr;
  90. ElementPtr *volatile m_read_ptr;
  91. volatile u32 m_size;
  92. };
  93. }
  94. #endif