瀏覽代碼

Cleanup. (#349)

Branimir Karadžić 3 周之前
父節點
當前提交
54941d2a3c
共有 2 個文件被更改,包括 112 次插入23 次删除
  1. 39 10
      include/bx/inline/ringbuffer.inl
  2. 73 13
      include/bx/ringbuffer.h

+ 39 - 10
include/bx/inline/ringbuffer.inl

@@ -21,11 +21,6 @@ namespace bx
 	{
 	}
 
-	inline uint32_t RingBufferControl::available() const
-	{
-		return distance(m_read, m_current);
-	}
-
 	inline bool RingBufferControl::isEmpty() const
 	{
 		return m_read == m_write;
@@ -119,7 +114,7 @@ namespace bx
 	}
 
 	inline SpScRingBufferControl::SpScRingBufferControl(uint32_t _size)
-		: m_size(_size)
+		: m_size(max(_size, 2) )
 		, m_current(0)
 		, m_write(0)
 		, m_read(0)
@@ -130,11 +125,45 @@ namespace bx
 	{
 	}
 
-	inline uint32_t SpScRingBufferControl::available() const
+	inline bool SpScRingBufferControl::isEmpty() const
+	{
+		return m_read == m_write;
+	}
+
+	inline uint32_t SpScRingBufferControl::getSize() const
+	{
+		return m_size;
+	}
+
+	inline uint32_t SpScRingBufferControl::getNumEmpty() const
+	{
+		return m_size - distance(m_read, m_write) - 1;
+	}
+
+	inline uint32_t SpScRingBufferControl::getNumUsed() const
 	{
 		return distance(m_read, m_current);
 	}
 
+	inline uint32_t SpScRingBufferControl::getNumReserved() const
+	{
+		return distance(m_current, m_write);
+	}
+
+	inline void SpScRingBufferControl::resize(int32_t _size)
+	{
+		_size = 0 > _size
+			// can shrink only by number of empty slots.
+			? bx::max(_size, -int32_t(getNumEmpty() ) )
+			: _size
+			;
+
+		m_size += _size;
+
+		m_current += m_current >= m_write ? _size : 0;
+		m_read    += m_read    >= m_write ? _size : 0;
+	}
+
 	inline uint32_t SpScRingBufferControl::consume(uint32_t _size)
 	{
 		const uint32_t maxSize    = distance(m_read, m_current);
@@ -147,13 +176,13 @@ namespace bx
 		return size;
 	}
 
-	inline uint32_t SpScRingBufferControl::reserve(uint32_t _size)
+	inline uint32_t SpScRingBufferControl::reserve(uint32_t _size, bool _mustSucceed)
 	{
 		const uint32_t dist       = distance(m_write, m_read)-1;
 		const uint32_t maxSize    = uint32_sels(dist, m_size-1, dist);
 		const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff);
 		const uint32_t test       = uint32_sub(sizeNoSign, maxSize);
-		const uint32_t size       = uint32_sels(test, _size, maxSize);
+		const uint32_t size       = uint32_sels(test, _size, _mustSucceed ? 0 : maxSize);
 		const uint32_t advance    = uint32_add(m_write, size);
 		const uint32_t write      = uint32_mod(advance, m_size);
 		m_write = write;
@@ -200,7 +229,7 @@ namespace bx
 		, m_size(_size)
 		, m_buffer(_buffer)
 	{
-		BX_ASSERT(_control.available() >= _size, "%d >= %d", _control.available(), _size);
+		BX_ASSERT(_control.getNumUsed() >= _size, "%d >= %d", _control.getNumUsed(), _size);
 	}
 
 	template <typename ControlT>

+ 73 - 13
include/bx/ringbuffer.h

@@ -37,12 +37,6 @@ namespace bx
 		/// Destructor.
 		~RingBufferControl();
 
-		/// Returns number of used slots.
-		///
-		/// @returns Number of used slots.
-		///
-		uint32_t available() const;
-
 		/// Returns 'true' if ring buffer is empty.
 		///
 		/// @returns Returns 'true' if ring buffer is empty.
@@ -122,6 +116,14 @@ namespace bx
 		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
 	{
@@ -131,34 +133,92 @@ namespace bx
 			);
 
 	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.
 		///
-		uint32_t available() const;
+		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.
 		///
-		uint32_t reserve(uint32_t _size); // producer only
+		/// @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();
 
-		const uint32_t m_size;
-		uint32_t m_current;
-		uint32_t m_write;
-		uint32_t m_read;
+		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.
 	};
 
 	///