fifo_queue.h 2.2 KB

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