RingQueue.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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();
  34. RingQueue(long size);
  35. ~RingQueue();
  36. /* 设置队列大小 */
  37. void setQueueSize(long size);
  38. /* 入队 */
  39. bool enQueue(const T& data);
  40. bool enQueue(T&& data);
  41. /* 出队 */
  42. bool deQueue(T& data);
  43. T& deQueue();
  44. /* 获取队列中第一个值(下一个出队的元素),但是不出队 */
  45. T& front();
  46. /* 获取队列大小,队列中有效值的大小 */
  47. long getQueueSize();
  48. /* 获取队列容量 */
  49. long getQueueCapacity();
  50. /* 判断队列是否为空 */
  51. bool isEmpty();
  52. /* 判断队列是否已满 */
  53. bool isFull();
  54. private:
  55. std::mutex m_mutex; /* 互斥锁 */
  56. T* m_queue = nullptr; /* 队列 */
  57. long m_capacity = 0; /* 队列容量 */
  58. long m_front = 0; /* 队头 */
  59. long m_rear = 0; /* 队尾 */
  60. };
  61. /* =====================================================================
  62. * ***************************** 函数实现 *****************************
  63. * ===================================================================== */
  64. /* 这个构造函数需要调用 setQueueSize 设置环形队列的大小 */
  65. template<typename T>
  66. RingQueue<T>::RingQueue() : m_capacity(0) , m_front(-1), m_rear(-1)
  67. {
  68. }
  69. template<typename T>
  70. RingQueue<T>::RingQueue(long capacicy) : m_capacity(capacicy)
  71. {
  72. m_front = -1;
  73. m_rear = -1;
  74. m_queue = new T[m_capacity];
  75. }
  76. template<typename T>
  77. RingQueue<T>::~RingQueue()
  78. {
  79. if(m_queue != nullptr)
  80. {
  81. delete[] m_queue;
  82. m_queue = nullptr;
  83. }
  84. }
  85. /**
  86. * @brief 设置队列大小
  87. * 注意:使用这个设置,如果队列中存储的是指针,指针的内存区域需要在调用这个函数之前释放,不然可能会造成
  88. * 内存泄漏
  89. *
  90. * @tparam T
  91. * @param size
  92. */
  93. template<typename T>
  94. void RingQueue<T>::setQueueSize(long size)
  95. {
  96. if(m_queue != nullptr)
  97. {
  98. delete[] m_queue;
  99. m_queue = nullptr;
  100. }
  101. m_capacity = size;
  102. m_front = -1;
  103. m_rear = -1;
  104. m_queue = new T[m_capacity];
  105. }
  106. /* 入队 */
  107. template<typename T>
  108. bool RingQueue<T>::enQueue(const T& data)
  109. {
  110. m_mutex.lock();
  111. /* 先检查队列是否还有剩余空间 */
  112. if(isFull())
  113. {
  114. return false;
  115. }
  116. else if(m_rear == -1)
  117. {
  118. m_front = 0;
  119. m_rear = 0;
  120. }
  121. /* 数据入队 */
  122. m_queue[m_rear] = data;
  123. m_rear = (m_rear + 1) % m_capacity;
  124. m_mutex.unlock();
  125. return true;
  126. }
  127. /* 入队,传入右值 */
  128. template<typename T>
  129. bool RingQueue<T>::enQueue(T&& data)
  130. {
  131. m_mutex.lock();
  132. /* 先检查队列是否还有剩余空间 */
  133. if(isFull())
  134. {
  135. return false;
  136. }
  137. else if(m_rear == -1)
  138. {
  139. m_front = 0;
  140. m_rear = 0;
  141. }
  142. m_queue[m_rear] = std::move(data);
  143. m_rear = (m_rear + 1) % m_capacity;
  144. m_mutex.unlock();
  145. return true;
  146. }
  147. /* 出队 */
  148. template<typename T>
  149. bool RingQueue<T>::deQueue(T& data)
  150. {
  151. m_mutex.lock();
  152. if(isEmpty())
  153. {
  154. return false;
  155. }
  156. data = std::move(m_queue[m_front]);
  157. /* 判断队列是否为空了 */
  158. m_front = (m_front + 1) % m_capacity;
  159. if(m_front == m_rear)
  160. {
  161. m_front = -1;
  162. m_rear = -1;
  163. }
  164. m_mutex.unlock();
  165. return true;
  166. }
  167. /* 出队 */
  168. template<typename T>
  169. T& RingQueue<T>::deQueue()
  170. {
  171. std::lock_guard<std::mutex> lock(m_mutex);
  172. if(isEmpty())
  173. {
  174. return T();
  175. }
  176. long tmp = m_front;
  177. m_front = (m_front + 1) % m_capacity;
  178. if(m_front == m_rear)
  179. {
  180. m_front = -1;
  181. m_rear = -1;
  182. }
  183. return std::move(m_queue[tmp]);
  184. }
  185. /* 获取队列中第一个值(下一个出队的元素),但是不出队 */
  186. template<typename T>
  187. T& RingQueue<T>::front()
  188. {
  189. std::lock_guard<std::mutex> lock(m_mutex);
  190. if(isEmpty())
  191. {
  192. return T();
  193. }
  194. return m_queue[m_front];
  195. }
  196. /* 获取队列中有效值的大小 */
  197. template<typename T>
  198. long RingQueue<T>::getQueueSize()
  199. {
  200. if(m_rear == -1)
  201. {
  202. return 0;
  203. }
  204. else if(m_rear > m_front)
  205. {
  206. return m_rear - m_front;
  207. }
  208. else if(m_rear < m_front)
  209. {
  210. return m_capacity - ( m_front - m_rear );
  211. }
  212. /* 这时候是队列满 */
  213. return m_capacity;
  214. }
  215. /* 获取队列容量 */
  216. template<typename T>
  217. long RingQueue<T>::getQueueCapacity()
  218. {
  219. return m_capacity;
  220. }
  221. /**
  222. * @brief 判断队列是否为空
  223. *
  224. * @tparam T
  225. * @return true
  226. * @return false
  227. */
  228. template<typename T>
  229. bool RingQueue<T>::isEmpty()
  230. {
  231. if((m_front == m_rear) && (m_front == -1))
  232. {
  233. return true;
  234. }
  235. return false;
  236. }
  237. /**
  238. * @brief 判断队列是否已满,这里判断依赖入队和出队后的队头和队尾指针的位置
  239. * 1、队头和队尾指针相等,但是队尾指针不等于-1,表示队列已满
  240. *
  241. * @tparam T
  242. * @return true
  243. * @return false
  244. */
  245. template<typename T>
  246. bool RingQueue<T>::isFull()
  247. {
  248. /* 如果m_rear或者m_front不等于-1,说明此时里面有内容
  249. * 同时m_front == m_rear,队列就满了 */
  250. if(m_front == m_rear && m_rear != -1)
  251. {
  252. return true;
  253. }
  254. return false;
  255. }
  256. #endif /* RINGQUEUE_H */