RingQueue.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #ifndef RINGQUEUE_H
  2. #define RINGQUEUE_H
  3. #include <cstdlib>
  4. #include <utility>
  5. #include <mutex>
  6. #include <atomic>
  7. /**
  8. * @brief 这里采用零公摊的方式,设置多大的空间,就有多大的空间可以使用
  9. * 1、如果队列是空,m_rear和m_front都设置为-1
  10. * 2、m_rear指向最新入队的元素的下一个位置
  11. * 3、m_front指向需要出队的第一个元素
  12. * 4、环形队列自带互斥锁
  13. *
  14. * 判断队列满:
  15. * m_rear == m_front,并且此时都不等于 -1
  16. *
  17. * 判断队列空:
  18. * m_rear == m_front,并且都等于 -1
  19. *
  20. * 获取队列大小:
  21. * 基本原则就是m_rear后面跟着的是有效值,m_front后面跟着的是已经出队的大小
  22. * m_rear > m_front,返回 m_rear - m_front
  23. * m_front > m_rear,返回 m_capacity - (m_front - m_rear)
  24. * m_rear == m_front,且不等于-1,返回 m_capacity
  25. * m_rear == m_front,且等于-1,返回 0
  26. *
  27. * @tparam T 模版类型
  28. */
  29. template<typename T>
  30. class RingQueue
  31. {
  32. public:
  33. RingQueue(long size = 1024);
  34. ~RingQueue();
  35. /* 入队 */
  36. bool enQueue(const T& data);
  37. bool enQueue(T&& data);
  38. /* 出队 */
  39. bool deQueue(T& data);
  40. T& deQueue();
  41. /* 获取队列中第一个值(下一个出队的元素),但是不出队 */
  42. T& front();
  43. /* 获取队列大小,队列中有效值的大小 */
  44. long getQueueSize();
  45. /* 获取队列容量 */
  46. long getQueueCapacity();
  47. /* 判断队列是否为空 */
  48. bool isEmpty();
  49. /* 判断队列是否已满 */
  50. bool isFull();
  51. private:
  52. std::mutex m_mutex; /* 互斥锁 */
  53. T* m_queue = nullptr; /* 队列 */
  54. long m_capacity = 0; /* 队列容量 */
  55. long m_front = 0; /* 队头 */
  56. long m_rear = 0; /* 队尾 */
  57. };
  58. /* =====================================================================
  59. * ***************************** 函数实现 *****************************
  60. * ===================================================================== */
  61. template<typename T>
  62. RingQueue<T>::RingQueue(long capacicy) : m_capacity(capacicy)
  63. {
  64. m_front = -1;
  65. m_rear = -1;
  66. m_queue = new T[m_capacity];
  67. }
  68. template<typename T>
  69. RingQueue<T>::~RingQueue()
  70. {
  71. if(m_queue != nullptr)
  72. {
  73. delete[] m_queue;
  74. m_queue = nullptr;
  75. }
  76. }
  77. /* 入队 */
  78. template<typename T>
  79. bool RingQueue<T>::enQueue(const T& data)
  80. {
  81. m_mutex.lock();
  82. /* 先检查队列是否还有剩余空间 */
  83. if(isFull())
  84. {
  85. return false;
  86. }
  87. else if(m_rear == -1)
  88. {
  89. m_front = 0;
  90. m_rear = 0;
  91. }
  92. /* 数据入队 */
  93. m_queue[m_rear] = data;
  94. m_rear = (m_rear + 1) % m_capacity;
  95. m_mutex.unlock();
  96. return true;
  97. }
  98. /* 入队,传入右值 */
  99. template<typename T>
  100. bool RingQueue<T>::enQueue(T&& data)
  101. {
  102. m_mutex.lock();
  103. /* 先检查队列是否还有剩余空间 */
  104. if(isFull())
  105. {
  106. return false;
  107. }
  108. else if(m_rear == -1)
  109. {
  110. m_front = 0;
  111. m_rear = 0;
  112. }
  113. m_queue[m_rear] = std::move(data);
  114. m_rear = (m_rear + 1) % m_capacity;
  115. m_mutex.unlock();
  116. return true;
  117. }
  118. /* 出队 */
  119. template<typename T>
  120. bool RingQueue<T>::deQueue(T& data)
  121. {
  122. m_mutex.lock();
  123. if(isEmpty())
  124. {
  125. return false;
  126. }
  127. data = std::move(m_queue[m_front]);
  128. /* 判断队列是否为空了 */
  129. m_front = (m_front + 1) % m_capacity;
  130. if(m_front == m_rear)
  131. {
  132. m_front = -1;
  133. m_rear = -1;
  134. }
  135. m_mutex.unlock();
  136. return true;
  137. }
  138. /* 出队 */
  139. template<typename T>
  140. T& RingQueue<T>::deQueue()
  141. {
  142. std::lock_guard<std::mutex> lock(m_mutex);
  143. if(isEmpty())
  144. {
  145. return T();
  146. }
  147. long tmp = m_front;
  148. m_front = (m_front + 1) % m_capacity;
  149. if(m_front == m_rear)
  150. {
  151. m_front = -1;
  152. m_rear = -1;
  153. }
  154. return std::move(m_queue[tmp]);
  155. }
  156. /* 获取队列中第一个值(下一个出队的元素),但是不出队 */
  157. template<typename T>
  158. T& RingQueue<T>::front()
  159. {
  160. std::lock_guard<std::mutex> lock(m_mutex);
  161. if(isEmpty())
  162. {
  163. return T();
  164. }
  165. return m_queue[m_front];
  166. }
  167. /* 获取队列中有效值的大小 */
  168. template<typename T>
  169. long RingQueue<T>::getQueueSize()
  170. {
  171. if(m_rear == -1)
  172. {
  173. return 0;
  174. }
  175. else if(m_rear > m_front)
  176. {
  177. return m_rear - m_front;
  178. }
  179. else if(m_rear < m_front)
  180. {
  181. return m_capacity - ( m_front - m_rear );
  182. }
  183. /* 这时候是队列满 */
  184. return m_capacity;
  185. }
  186. /* 获取队列容量 */
  187. template<typename T>
  188. long RingQueue<T>::getQueueCapacity()
  189. {
  190. return m_capacity;
  191. }
  192. /**
  193. * @brief 判断队列是否为空
  194. *
  195. * @tparam T
  196. * @return true
  197. * @return false
  198. */
  199. template<typename T>
  200. bool RingQueue<T>::isEmpty()
  201. {
  202. if((m_front == m_rear) && (m_front == -1))
  203. {
  204. return true;
  205. }
  206. return false;
  207. }
  208. /**
  209. * @brief 判断队列是否已满,这里判断依赖入队和出队后的队头和队尾指针的位置
  210. * 1、队头和队尾指针相等,但是队尾指针不等于-1,表示队列已满
  211. *
  212. * @tparam T
  213. * @return true
  214. * @return false
  215. */
  216. template<typename T>
  217. bool RingQueue<T>::isFull()
  218. {
  219. /* 如果m_rear或者m_front不等于-1,说明此时里面有内容
  220. * 同时m_front == m_rear,队列就满了 */
  221. if(m_front == m_rear && m_rear != -1)
  222. {
  223. return true;
  224. }
  225. return false;
  226. }
  227. #endif /* RINGQUEUE_H */