ringbuffer.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
  4. */
  5. #ifndef BX_RINGBUFFER_H_HEADER_GUARD
  6. #define BX_RINGBUFFER_H_HEADER_GUARD
  7. #include "bx.h"
  8. #include "cpu.h"
  9. #include "uint32_t.h"
  10. namespace bx
  11. {
  12. /// Ring buffer control structure. Tracking "read", "write", and "current" head.
  13. ///
  14. /// This is not container, and data control represents is user defined. Read/write/current are
  15. /// just indices.
  16. ///
  17. /// @notice One slot is always reseved. When creating ring buffer of N slots, N-1 slots can be
  18. /// used.
  19. ///
  20. class RingBufferControl
  21. {
  22. BX_CLASS(RingBufferControl
  23. , NO_DEFAULT_CTOR
  24. , NO_COPY
  25. );
  26. public:
  27. /// Constructor.
  28. ///
  29. /// @param[in] _size Maximum number of slots.
  30. ///
  31. RingBufferControl(uint32_t _size);
  32. /// Destructor.
  33. ~RingBufferControl();
  34. /// Returns 'true' if ring buffer is empty.
  35. ///
  36. /// @returns Returns 'true' if ring buffer is empty.
  37. ///
  38. bool isEmpty() const;
  39. /// Returns total size of ring buffer.
  40. ///
  41. /// @returns Total size of ring buffer.
  42. ///
  43. uint32_t getSize() const;
  44. /// Returns number of empty slots.
  45. ///
  46. /// @returns Number of empty slots.
  47. ///
  48. uint32_t getNumEmpty() const;
  49. /// Returns number of used slots.
  50. ///
  51. /// @returns Number of used slots.
  52. ///
  53. uint32_t getNumUsed() const;
  54. /// Returns number of reserved slots.
  55. ///
  56. /// @returns Number of reserved slots.
  57. ///
  58. uint32_t getNumReserved() const;
  59. /// Resize ring buffer. Resize happens at write head, read and current head will be moved
  60. /// forward or backward if write head is behind them.
  61. ///
  62. /// @param[in] _size Amount to resize. Value can be positive when growing size or negative
  63. /// when shrinking size of buffer.
  64. ///
  65. void resize(int32_t _size);
  66. /// Consume slots, makes slots free to be reserved. Moves "read" head forward.
  67. ///
  68. /// @returns Number of reserved slots reserved.
  69. ///
  70. uint32_t consume(uint32_t _size); // consumer only
  71. /// Reserve slots, makes slots non-free, but ready to be used yet. Moves "write" head forward.
  72. ///
  73. /// @param[in] _size Number of slots.
  74. /// @param[in] _mustSucceed If argument is true it will not reseve any slots unless `_size`
  75. /// of slots is reseved.
  76. ///
  77. /// @returns Number of reserved slots reserved.
  78. ///
  79. uint32_t reserve(uint32_t _size, bool _mustSucceed = false); // producer only
  80. /// Commit slots, makes slots used, and ready to be consumed. Moves "current" head forward.
  81. ///
  82. /// @param[in] _size Number of commited slots.
  83. ///
  84. uint32_t commit(uint32_t _size); // producer only
  85. /// Calculate distance between two slots. Function takes wrapping into account.
  86. ///
  87. /// @param[in] _from From.
  88. /// @param[in] _to To.
  89. ///
  90. /// @returns Distance between slots.
  91. ///
  92. uint32_t distance(uint32_t _from, uint32_t _to) const; // both
  93. /// Invalidate ring buffer.
  94. ///
  95. void reset();
  96. uint32_t m_size; //!< Size of ring buffer.
  97. uint32_t m_current; //!< Currently operated area start.
  98. uint32_t m_write; //!< Write head.
  99. uint32_t m_read; //!< Read head.
  100. };
  101. /// Lock-less single producer, single consumer ring buffer control structure. Tracking "read",
  102. /// "write", and "current" head.
  103. ///
  104. /// This is not container, and data control represents is user defined. Read/write/current are
  105. /// just indices.
  106. ///
  107. /// @notice One slot is always reseved. When creating ring buffer of N slots, N-1 slots can be
  108. /// used.
  109. ///
  110. class SpScRingBufferControl
  111. {
  112. BX_CLASS(SpScRingBufferControl
  113. , NO_DEFAULT_CTOR
  114. , NO_COPY
  115. );
  116. public:
  117. /// Constructor.
  118. ///
  119. /// @param[in] _size Maximum number of slots.
  120. ///
  121. SpScRingBufferControl(uint32_t _size);
  122. /// Destructor.
  123. ~SpScRingBufferControl();
  124. /// Returns 'true' if ring buffer is empty.
  125. ///
  126. /// @returns Returns 'true' if ring buffer is empty.
  127. ///
  128. bool isEmpty() const;
  129. /// Returns total size of ring buffer.
  130. ///
  131. /// @returns Total size of ring buffer.
  132. ///
  133. uint32_t getSize() const;
  134. /// Returns number of empty slots.
  135. ///
  136. /// @returns Number of empty slots.
  137. ///
  138. uint32_t getNumEmpty() const;
  139. /// Returns number of used slots.
  140. ///
  141. /// @returns Number of used slots.
  142. ///
  143. uint32_t getNumUsed() const;
  144. /// Returns number of reserved slots.
  145. ///
  146. /// @returns Number of reserved slots.
  147. ///
  148. uint32_t getNumReserved() const;
  149. /// Resize ring buffer. Resize happens at write head, read and current head will be moved
  150. /// forward or backward if write head is behind them.
  151. ///
  152. /// @param[in] _size Amount to resize. Value can be positive when growing size or negative
  153. /// when shrinking size of buffer.
  154. ///
  155. void resize(int32_t _size);
  156. /// Consume slots, makes slots free to be reserved. Moves "read" head forward.
  157. ///
  158. /// @returns Number of reserved slots reserved.
  159. ///
  160. uint32_t consume(uint32_t _size); // consumer only
  161. /// Reserve slots, makes slots non-free, but ready to be used yet. Moves "write" head forward.
  162. ///
  163. /// @param[in] _size Number of slots.
  164. /// @param[in] _mustSucceed If argument is true it will not reseve any slots unless `_size`
  165. /// of slots is reseved.
  166. ///
  167. /// @returns Number of reserved slots reserved.
  168. ///
  169. uint32_t reserve(uint32_t _size, bool _mustSucceed = false); // producer only
  170. /// Commit slots, makes slots used, and ready to be consumed. Moves "current" head forward.
  171. ///
  172. /// @param[in] _size Number of commited slots.
  173. ///
  174. uint32_t commit(uint32_t _size); // producer only
  175. /// Calculate distance between two slots. Function takes wrapping into account.
  176. ///
  177. /// @param[in] _from From.
  178. /// @param[in] _to To.
  179. ///
  180. /// @returns Distance between slots.
  181. ///
  182. uint32_t distance(uint32_t _from, uint32_t _to) const; // both
  183. /// Invalidate ring buffer.
  184. ///
  185. void reset();
  186. uint32_t m_size; //!< Size of ring buffer.
  187. uint32_t m_current; //!< Currently operated area start.
  188. uint32_t m_write; //!< Write head.
  189. uint32_t m_read; //!< Read head.
  190. };
  191. ///
  192. template <typename ControlT>
  193. class ReadRingBufferT
  194. {
  195. BX_CLASS(ReadRingBufferT
  196. , NO_DEFAULT_CTOR
  197. , NO_COPY
  198. );
  199. public:
  200. ///
  201. ReadRingBufferT(ControlT& _control, const char* _buffer, uint32_t _size);
  202. ///
  203. ~ReadRingBufferT();
  204. ///
  205. void end();
  206. ///
  207. void read(char* _data, uint32_t _len);
  208. ///
  209. void skip(uint32_t _len);
  210. private:
  211. template <typename Ty>
  212. friend class WriteRingBufferT;
  213. ControlT& m_control;
  214. uint32_t m_read;
  215. uint32_t m_end;
  216. const uint32_t m_size;
  217. const char* m_buffer;
  218. };
  219. ///
  220. typedef ReadRingBufferT<RingBufferControl> ReadRingBuffer;
  221. ///
  222. typedef ReadRingBufferT<SpScRingBufferControl> SpScReadRingBuffer;
  223. ///
  224. template <typename ControlT>
  225. class WriteRingBufferT
  226. {
  227. BX_CLASS(WriteRingBufferT
  228. , NO_DEFAULT_CTOR
  229. , NO_COPY
  230. );
  231. public:
  232. ///
  233. WriteRingBufferT(ControlT& _control, char* _buffer, uint32_t _size);
  234. ///
  235. ~WriteRingBufferT();
  236. ///
  237. void end();
  238. ///
  239. void write(const char* _data, uint32_t _len);
  240. ///
  241. void write(ReadRingBufferT<ControlT>& _read, uint32_t _len);
  242. ///
  243. void skip(uint32_t _len);
  244. private:
  245. ControlT& m_control;
  246. uint32_t m_write;
  247. uint32_t m_end;
  248. const uint32_t m_size;
  249. char* m_buffer;
  250. };
  251. ///
  252. typedef WriteRingBufferT<RingBufferControl> WriteRingBuffer;
  253. ///
  254. typedef WriteRingBufferT<SpScRingBufferControl> SpScWriteRingBuffer;
  255. } // namespace bx
  256. #include "inline/ringbuffer.inl"
  257. #endif // BX_RINGBUFFER_H_HEADER_GUARD