jaffarCommon
Loading...
Searching...
No Matches
Public Member Functions | List of all members
jaffarCommon::concurrent::DrainBuffer< T > Class Template Reference

#include <concurrent.hpp>

Public Member Functions

__JAFFAR_COMMON_INLINE__ void reserve (const size_t capacity)
 
__JAFFAR_COMMON_INLINE__ void clear ()
 
__JAFFAR_COMMON_INLINE__ void push_back_no_lock (T element)
 
__JAFFAR_COMMON_INLINE__ size_t pop_front_get_batch (T *elements, const size_t maxCount)
 
__JAFFAR_COMMON_INLINE__ bool pop_front_get (T &element)
 
__JAFFAR_COMMON_INLINE__ bool pop_back_get (T &element)
 
__JAFFAR_COMMON_INLINE__ size_t wasSize () const
 

Detailed Description

template<class T>
class jaffarCommon::concurrent::DrainBuffer< T >

A fixed-capacity buffer specialized for a fill-once / drain-from-both-ends lifecycle, with a lock-free concurrent drain phase.

It is built for the pattern where one phase fills the buffer single-threaded (no contention), a barrier follows, and then many threads concurrently consume the elements – most pulling batches from the front, a few pulling single elements from the back – until it is empty. There is never a push concurrent with a pop. (This is exactly how a best-first search step works: the ordered set of states for the step is laid down once, then worker threads drain it.)

Versus a mutex-guarded std::deque this wins three ways: the fill is a plain sequential store with no per-element allocation; the storage is contiguous, so the concurrent drain is cache- and prefetcher-friendly; and front/back claiming is lock-free (a single CAS) instead of taking a mutex. Both ends are claimed by advancing counters packed into one 64-bit atomic, so a front and a back claim can never alias the same slot. Indices only grow within a step and are reset (clear()) only while the buffer is quiescent, so there is no ABA hazard.

Note
Capacity is fixed at reserve() time; the fill phase must not exceed it. Capacity is limited to UINT32_MAX elements (the claim counters are 32-bit halves).

Member Function Documentation

◆ clear()

template<class T >
__JAFFAR_COMMON_INLINE__ void jaffarCommon::concurrent::DrainBuffer< T >::clear ( )
inline

Resets the buffer to empty for a new fill phase. Must be called while quiescent (no concurrent drain in flight), e.g. right before the single-threaded fill of the next step.

◆ pop_back_get()

template<class T >
__JAFFAR_COMMON_INLINE__ bool jaffarCommon::concurrent::DrainBuffer< T >::pop_back_get ( T &  element)
inline

Claims a single element from the back. Lock-free.

Parameters
[out]elementStorage for the claimed element
Returns
True if an element was claimed; false if empty

◆ pop_front_get()

template<class T >
__JAFFAR_COMMON_INLINE__ bool jaffarCommon::concurrent::DrainBuffer< T >::pop_front_get ( T &  element)
inline

Claims a single element from the front. Lock-free.

Parameters
[out]elementStorage for the claimed element
Returns
True if an element was claimed; false if empty

◆ pop_front_get_batch()

template<class T >
__JAFFAR_COMMON_INLINE__ size_t jaffarCommon::concurrent::DrainBuffer< T >::pop_front_get_batch ( T *  elements,
const size_t  maxCount 
)
inline

Claims up to maxCount elements from the front in a single lock-free step, copying them into the provided buffer in front-to-back order.

Parameters
[out]elementsDestination buffer; room for at least maxCount elements
[in]maxCountMaximum number of elements to claim
Returns
The number of elements actually claimed (0 if empty)

◆ push_back_no_lock()

template<class T >
__JAFFAR_COMMON_INLINE__ void jaffarCommon::concurrent::DrainBuffer< T >::push_back_no_lock ( element)
inline

Appends an element during the (single-threaded) fill phase.

Parameters
[in]elementThe element to append to the buffer
Note
Not thread safe – intended to be called by a single filler thread between clear() and the start of the concurrent drain.

◆ reserve()

template<class T >
__JAFFAR_COMMON_INLINE__ void jaffarCommon::concurrent::DrainBuffer< T >::reserve ( const size_t  capacity)
inline

Allocates the backing storage. Must be called once before use.

Parameters
[in]capacityMaximum number of elements the buffer will ever hold in a single fill phase

◆ wasSize()

template<class T >
__JAFFAR_COMMON_INLINE__ size_t jaffarCommon::concurrent::DrainBuffer< T >::wasSize ( ) const
inline

Number of elements not yet claimed, at the time of checking. Safe to call concurrently.

Returns
The number of elements not yet claimed at the moment of the call

The documentation for this class was generated from the following file: