|
dispenso 1.5.1
A library for task parallelism
|
A lock-free single-producer single-consumer ring buffer with fixed capacity. More...
#include <spsc_ring_buffer.h>
Public Member Functions | |
| SPSCRingBuffer ()=default | |
| Constructs an empty ring buffer. | |
| SPSCRingBuffer (const SPSCRingBuffer &)=delete | |
| Ring buffers are not copyable. | |
| SPSCRingBuffer (SPSCRingBuffer &&)=delete | |
| Ring buffers are not movable. | |
| ~SPSCRingBuffer () | |
| Destroys the ring buffer. | |
| bool | try_push (T &&item) |
| Attempts to push an element into the buffer by moving. | |
| bool | try_push (const T &item) |
| Attempts to push an element into the buffer by copying. | |
| template<typename... Args> | |
| bool | try_emplace (Args &&... args) |
| Attempts to construct an element in-place in the buffer. | |
| bool | try_pop (T &item) |
| Attempts to pop an element from the buffer. | |
| OpResult< T > | try_pop () |
| Attempts to pop an element from the buffer, returning an optional. | |
| bool | try_pop_into (T *storage) |
| Attempts to pop an element into uninitialized storage. | |
| template<typename InputIt > | |
| size_type | try_push_batch (InputIt first, InputIt last) |
| Attempts to push multiple elements into the buffer. | |
| template<typename OutputIt > | |
| size_type | try_pop_batch (OutputIt dest, size_type maxCount) |
| Attempts to pop multiple elements from the buffer. | |
| bool | empty () const |
| Checks if the buffer is empty. | |
| bool | full () const |
| Checks if the buffer is full. | |
| size_type | size () const |
| Returns the current number of elements in the buffer. | |
Static Public Member Functions | |
| static constexpr size_type | capacity () noexcept |
| Returns the maximum number of elements the buffer can hold. | |
A lock-free single-producer single-consumer ring buffer with fixed capacity.
This class implements a bounded, lock-free ring buffer optimized for the case where there is exactly one producer thread and exactly one consumer thread. It uses relaxed memory ordering where possible and acquire/release semantics only where necessary for correctness.
The buffer stores elements in a contiguous array, avoiding dynamic memory allocation after construction. The capacity is fixed at compile time via a template parameter.
Unlike std::array-based implementations, this buffer does NOT require the element type to be default-constructible. Elements are constructed in-place when pushed and destroyed when popped.
| T | The type of elements stored in the buffer. Must be move-constructible. |
| Capacity | The minimum number of elements the buffer can hold. Must be at least 1. Defaults to 16, which provides good cache locality. |
| RoundUpToPowerOfTwo | If true (default), rounds up the internal buffer size to the next power of two for faster index wrap-around using bitwise AND instead of modulo. This may result in actual capacity being larger than requested. Set to false to use exactly the requested capacity. |
This class is designed for exactly one producer thread and one consumer thread:
try_push() or try_emplace() at any timetry_pop() at any timeempty(), full(), and size() may be called from any thread, but provide only a snapshot that may be immediately staleThe implementation uses:
memory_order_relaxed for local reads of head/tailmemory_order_acquire when reading the "other" index (consumer reads head, producer reads tail)memory_order_release when updating head/tail after successful push/popDefinition at line 111 of file spsc_ring_buffer.h.
|
default |
Constructs an empty ring buffer.
The buffer is initialized with no elements. The internal storage is uninitialized - elements are only constructed when pushed.
|
delete |
Ring buffers are not copyable.
Copying a concurrent data structure would require synchronization and could lead to subtle bugs. Use move semantics if you need to transfer ownership.
|
delete |
Ring buffers are not movable.
Moving a ring buffer while producer/consumer threads are active would be unsafe. If you need to transfer ownership, ensure all threads have stopped first.
|
inline |
Destroys the ring buffer.
All elements remaining in the buffer are destroyed. Ensure no producer or consumer threads are accessing the buffer when it is destroyed.
Definition at line 178 of file spsc_ring_buffer.h.
|
inlinestaticconstexprnoexcept |
Returns the maximum number of elements the buffer can hold.
When RoundUpToPowerOfTwo is true (default), this may be larger than the requested Capacity template parameter, as the internal buffer is rounded up to the next power of two for performance.
Definition at line 591 of file spsc_ring_buffer.h.
|
inline |
Checks if the buffer is empty.
Definition at line 539 of file spsc_ring_buffer.h.
|
inline |
Checks if the buffer is full.
Definition at line 554 of file spsc_ring_buffer.h.
|
inline |
Returns the current number of elements in the buffer.
Definition at line 572 of file spsc_ring_buffer.h.
|
inline |
Attempts to construct an element in-place in the buffer.
If the buffer has space, constructs an element directly in the buffer storage using the provided arguments, avoiding any copy or move operations.
| Args | The types of arguments to forward to T's constructor. |
| args | The arguments to forward to the element constructor. |
Definition at line 278 of file spsc_ring_buffer.h.
|
inline |
Attempts to pop an element from the buffer, returning an optional.
If the buffer has elements, moves the front element into an OpResult and returns it. If the buffer is empty, returns an empty OpResult.
This provides a cleaner API than try_pop(T&) when default-constructibility of T is not guaranteed or when a more functional style is preferred.
Definition at line 358 of file spsc_ring_buffer.h.
|
inline |
Attempts to pop an element from the buffer.
If the buffer has elements, moves the front element into the output parameter and returns true. If the buffer is empty, returns false and leaves the output parameter unchanged.
| [out] | item | The location to move the popped element to. |
Definition at line 317 of file spsc_ring_buffer.h.
|
inline |
Attempts to pop multiple elements from the buffer.
Pops up to maxCount elements from the buffer into the output iterator in a single atomic head update. This reduces atomic operation overhead when consuming multiple items.
| OutputIt | Output iterator type. Must be assignable from T. |
| dest | Output iterator to write popped elements to. |
| maxCount | Maximum number of elements to pop. |
Definition at line 496 of file spsc_ring_buffer.h.
|
inline |
Attempts to pop an element into uninitialized storage.
Similar to try_pop, but uses placement new to construct the element into the provided storage. This is useful when T is not default-constructible.
| [out] | storage | Pointer to uninitialized storage where the element will be move-constructed. Must have proper alignment for T. |
Definition at line 398 of file spsc_ring_buffer.h.
|
inline |
Attempts to push an element into the buffer by copying.
If the buffer has space, the element is copied into the buffer and the function returns true. If the buffer is full, the function returns false.
| item | The element to push (will be copied). |
Definition at line 241 of file spsc_ring_buffer.h.
|
inline |
Attempts to push an element into the buffer by moving.
If the buffer has space, the element is moved into the buffer and the function returns true. If the buffer is full, the function returns false and the element is unchanged.
| item | The element to push (will be moved from on success). |
Definition at line 212 of file spsc_ring_buffer.h.
|
inline |
Attempts to push multiple elements into the buffer.
Pushes as many elements as possible from the range [first, last) into the buffer in a single atomic tail update. This reduces atomic operation overhead when pushing multiple items.
| InputIt | Input iterator type. Must dereference to a type convertible to T. |
| first | Iterator to the first element to push. |
| last | Iterator past the last element to push. |
Definition at line 438 of file spsc_ring_buffer.h.