circular_queue.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #ifndef CIRCULAR_QUEUE_H
  2. #define CIRCULAR_QUEUE_H
  3. #include <assert.h>
  4. #include <string.h>
  5. template <class T> class CircularQueue
  6. {
  7. private:
  8. const UInt32 m_size;
  9. volatile UInt32 m_first; // next element to be inserted here
  10. UInt8 padding1[60];
  11. volatile UInt32 m_last; // last element is here
  12. UInt8 padding2[60];
  13. T* const m_queue;
  14. public:
  15. typedef T value_type;
  16. class iterator : public std::iterator<std::forward_iterator_tag, T, std::ptrdiff_t, const T*, const T&>
  17. {
  18. private:
  19. CircularQueue &_queue;
  20. UInt32 _idx;
  21. public:
  22. iterator(CircularQueue &queue, UInt32 idx) : _queue(queue), _idx(idx) {}
  23. T& operator*() const { return _queue.at(_idx); }
  24. T* operator->() const { return &_queue.at(_idx); }
  25. iterator& operator++() { _idx++; return *this; }
  26. bool operator==(iterator const& rhs) const { return &_queue == &rhs._queue && _idx == rhs._idx; }
  27. bool operator!=(iterator const& rhs) const { return ! (*this == rhs); }
  28. };
  29. CircularQueue(UInt32 size = 63);
  30. CircularQueue(const CircularQueue &queue);
  31. ~CircularQueue();
  32. void push(const T& t);
  33. void pushCircular(const T& t);
  34. T& next(void);
  35. T pop(void);
  36. T& front(void);
  37. const T& front(void) const;
  38. T& back(void);
  39. const T& back(void) const;
  40. bool full(void) const;
  41. bool empty(void) const;
  42. UInt32 size(void) const;
  43. iterator begin(void) { return iterator(*this, 0); }
  44. iterator end(void) { return iterator(*this, size()); }
  45. T& operator[](UInt32 idx) const { return m_queue[(m_last + idx) % m_size]; }
  46. T& at(UInt32 idx) const { assert(idx < size()); return (*this)[idx]; }
  47. };
  48. template <class T>
  49. CircularQueue<T>::CircularQueue(UInt32 size)
  50. // Since we use head == tail as the empty condition instead of an extra empty flag, we can hold at most m_size-1 elements
  51. : m_size(size + 1)
  52. , m_first(0)
  53. , m_last(0)
  54. , m_queue(new T[m_size])
  55. {
  56. }
  57. // Copy only the size parameter from the other CircularQueue
  58. template <class T>
  59. CircularQueue<T>::CircularQueue(const CircularQueue &queue)
  60. : m_size(queue.m_size)
  61. , m_first(0)
  62. , m_last(0)
  63. , m_queue(new T[m_size])
  64. {
  65. assert(queue.size() == 0);
  66. }
  67. template <class T>
  68. CircularQueue<T>::~CircularQueue()
  69. {
  70. delete [] m_queue;
  71. }
  72. template <class T>
  73. void
  74. CircularQueue<T>::push(const T& t)
  75. {
  76. assert(!full());
  77. m_queue[m_first] = t;
  78. m_first = (m_first + 1) % m_size;
  79. }
  80. template <class T>
  81. void
  82. CircularQueue<T>::pushCircular(const T& t)
  83. {
  84. if (full())
  85. pop();
  86. push(t);
  87. }
  88. template <class T>
  89. T&
  90. CircularQueue<T>::next(void)
  91. {
  92. assert(!full());
  93. T& t = m_queue[m_first];
  94. m_first = (m_first + 1) % m_size;
  95. return t;
  96. }
  97. template <class T>
  98. T
  99. CircularQueue<T>::pop()
  100. {
  101. assert(!empty());
  102. UInt32 idx = m_last;
  103. m_last = (m_last + 1) % m_size;
  104. return m_queue[idx];
  105. }
  106. template <class T>
  107. T &
  108. CircularQueue<T>::front()
  109. {
  110. assert(!empty());
  111. return m_queue[m_last];
  112. }
  113. template <class T>
  114. const T &
  115. CircularQueue<T>::front() const
  116. {
  117. assert(!empty());
  118. return m_queue[m_last];
  119. }
  120. template <class T>
  121. T &
  122. CircularQueue<T>::back()
  123. {
  124. assert(!empty());
  125. return m_queue[(m_first + m_size - 1) % m_size];
  126. }
  127. template <class T>
  128. const T &
  129. CircularQueue<T>::back() const
  130. {
  131. assert(!empty());
  132. return m_queue[(m_first + m_size - 1) % m_size];
  133. }
  134. template <class T>
  135. bool
  136. CircularQueue<T>::full(void) const
  137. {
  138. return (m_first + 1) % m_size == m_last;
  139. }
  140. template <class T>
  141. bool
  142. CircularQueue<T>::empty(void) const
  143. {
  144. return m_first == m_last;
  145. }
  146. template <class T>
  147. UInt32
  148. CircularQueue<T>::size() const
  149. {
  150. return (m_first + m_size - m_last) % m_size;
  151. }
  152. #endif // CIRCULAR_QUEUE_H