| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- /*
- * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
- * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
- */
- #ifndef BX_RINGBUFFER_H_HEADER_GUARD
- #define BX_RINGBUFFER_H_HEADER_GUARD
- #include "bx.h"
- #include "cpu.h"
- #include "uint32_t.h"
- namespace bx
- {
- /// Ring buffer control structure. Tracking "read", "write", and "current" head.
- ///
- /// This is not container, and data control represents is user defined. Read/write/current are
- /// just indices.
- ///
- /// @notice One slot is always reseved. When creating ring buffer of N slots, N-1 slots can be
- /// used.
- ///
- class RingBufferControl
- {
- BX_CLASS(RingBufferControl
- , NO_DEFAULT_CTOR
- , NO_COPY
- );
- public:
- /// Constructor.
- ///
- /// @param[in] _size Maximum number of slots.
- ///
- RingBufferControl(uint32_t _size);
- /// Destructor.
- ~RingBufferControl();
- /// Returns 'true' if ring buffer is empty.
- ///
- /// @returns Returns 'true' if ring buffer is empty.
- ///
- bool isEmpty() const;
- /// Returns total size of ring buffer.
- ///
- /// @returns Total size of ring buffer.
- ///
- uint32_t getSize() const;
- /// Returns number of empty slots.
- ///
- /// @returns Number of empty slots.
- ///
- uint32_t getNumEmpty() const;
- /// Returns number of used slots.
- ///
- /// @returns Number of used slots.
- ///
- uint32_t getNumUsed() const;
- /// Returns number of reserved slots.
- ///
- /// @returns Number of reserved slots.
- ///
- uint32_t getNumReserved() const;
- /// Resize ring buffer. Resize happens at write head, read and current head will be moved
- /// forward or backward if write head is behind them.
- ///
- /// @param[in] _size Amount to resize. Value can be positive when growing size or negative
- /// when shrinking size of buffer.
- ///
- void resize(int32_t _size);
- /// Consume slots, makes slots free to be reserved. Moves "read" head forward.
- ///
- /// @returns Number of reserved slots reserved.
- ///
- uint32_t consume(uint32_t _size); // consumer only
- /// Reserve slots, makes slots non-free, but ready to be used yet. Moves "write" head forward.
- ///
- /// @param[in] _size Number of slots.
- /// @param[in] _mustSucceed If argument is true it will not reseve any slots unless `_size`
- /// of slots is reseved.
- ///
- /// @returns Number of reserved slots reserved.
- ///
- uint32_t reserve(uint32_t _size, bool _mustSucceed = false); // producer only
- /// Commit slots, makes slots used, and ready to be consumed. Moves "current" head forward.
- ///
- /// @param[in] _size Number of commited slots.
- ///
- uint32_t commit(uint32_t _size); // producer only
- /// Calculate distance between two slots. Function takes wrapping into account.
- ///
- /// @param[in] _from From.
- /// @param[in] _to To.
- ///
- /// @returns Distance between slots.
- ///
- uint32_t distance(uint32_t _from, uint32_t _to) const; // both
- /// Invalidate ring buffer.
- ///
- void reset();
- uint32_t m_size; //!< Size of ring buffer.
- uint32_t m_current; //!< Currently operated area start.
- uint32_t m_write; //!< Write head.
- uint32_t m_read; //!< Read head.
- };
- /// Lock-less single producer, single consumer ring buffer control structure. Tracking "read",
- /// "write", and "current" head.
- ///
- /// This is not container, and data control represents is user defined. Read/write/current are
- /// just indices.
- ///
- /// @notice One slot is always reseved. When creating ring buffer of N slots, N-1 slots can be
- /// used.
- ///
- class SpScRingBufferControl
- {
- BX_CLASS(SpScRingBufferControl
- , NO_DEFAULT_CTOR
- , NO_COPY
- );
- public:
- /// Constructor.
- ///
- /// @param[in] _size Maximum number of slots.
- ///
- SpScRingBufferControl(uint32_t _size);
- /// Destructor.
- ~SpScRingBufferControl();
- /// Returns 'true' if ring buffer is empty.
- ///
- /// @returns Returns 'true' if ring buffer is empty.
- ///
- bool isEmpty() const;
- /// Returns total size of ring buffer.
- ///
- /// @returns Total size of ring buffer.
- ///
- uint32_t getSize() const;
- /// Returns number of empty slots.
- ///
- /// @returns Number of empty slots.
- ///
- uint32_t getNumEmpty() const;
- /// Returns number of used slots.
- ///
- /// @returns Number of used slots.
- ///
- uint32_t getNumUsed() const;
- /// Returns number of reserved slots.
- ///
- /// @returns Number of reserved slots.
- ///
- uint32_t getNumReserved() const;
- /// Resize ring buffer. Resize happens at write head, read and current head will be moved
- /// forward or backward if write head is behind them.
- ///
- /// @param[in] _size Amount to resize. Value can be positive when growing size or negative
- /// when shrinking size of buffer.
- ///
- void resize(int32_t _size);
- /// Consume slots, makes slots free to be reserved. Moves "read" head forward.
- ///
- /// @returns Number of reserved slots reserved.
- ///
- uint32_t consume(uint32_t _size); // consumer only
- /// Reserve slots, makes slots non-free, but ready to be used yet. Moves "write" head forward.
- ///
- /// @param[in] _size Number of slots.
- /// @param[in] _mustSucceed If argument is true it will not reseve any slots unless `_size`
- /// of slots is reseved.
- ///
- /// @returns Number of reserved slots reserved.
- ///
- uint32_t reserve(uint32_t _size, bool _mustSucceed = false); // producer only
- /// Commit slots, makes slots used, and ready to be consumed. Moves "current" head forward.
- ///
- /// @param[in] _size Number of commited slots.
- ///
- uint32_t commit(uint32_t _size); // producer only
- /// Calculate distance between two slots. Function takes wrapping into account.
- ///
- /// @param[in] _from From.
- /// @param[in] _to To.
- ///
- /// @returns Distance between slots.
- ///
- uint32_t distance(uint32_t _from, uint32_t _to) const; // both
- /// Invalidate ring buffer.
- ///
- void reset();
- uint32_t m_size; //!< Size of ring buffer.
- uint32_t m_current; //!< Currently operated area start.
- uint32_t m_write; //!< Write head.
- uint32_t m_read; //!< Read head.
- };
- ///
- template <typename ControlT>
- class ReadRingBufferT
- {
- BX_CLASS(ReadRingBufferT
- , NO_DEFAULT_CTOR
- , NO_COPY
- );
- public:
- ///
- ReadRingBufferT(ControlT& _control, const char* _buffer, uint32_t _size);
- ///
- ~ReadRingBufferT();
- ///
- void end();
- ///
- void read(char* _data, uint32_t _len);
- ///
- void skip(uint32_t _len);
- private:
- template <typename Ty>
- friend class WriteRingBufferT;
- ControlT& m_control;
- uint32_t m_read;
- uint32_t m_end;
- const uint32_t m_size;
- const char* m_buffer;
- };
- ///
- typedef ReadRingBufferT<RingBufferControl> ReadRingBuffer;
- ///
- typedef ReadRingBufferT<SpScRingBufferControl> SpScReadRingBuffer;
- ///
- template <typename ControlT>
- class WriteRingBufferT
- {
- BX_CLASS(WriteRingBufferT
- , NO_DEFAULT_CTOR
- , NO_COPY
- );
- public:
- ///
- WriteRingBufferT(ControlT& _control, char* _buffer, uint32_t _size);
- ///
- ~WriteRingBufferT();
- ///
- void end();
- ///
- void write(const char* _data, uint32_t _len);
- ///
- void write(ReadRingBufferT<ControlT>& _read, uint32_t _len);
- ///
- void skip(uint32_t _len);
- private:
- ControlT& m_control;
- uint32_t m_write;
- uint32_t m_end;
- const uint32_t m_size;
- char* m_buffer;
- };
- ///
- typedef WriteRingBufferT<RingBufferControl> WriteRingBuffer;
- ///
- typedef WriteRingBufferT<SpScRingBufferControl> SpScWriteRingBuffer;
- } // namespace bx
- #include "inline/ringbuffer.inl"
- #endif // BX_RINGBUFFER_H_HEADER_GUARD
|