Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This version of Boost is under active development. You are currently in the develop branch. The current version is 1.91.0.
boost::lockfree::mpsc_weak_queue
// In header: <boost/lockfree/mpsc_weak_queue.hpp> template<typename T, typename... Options> class mpsc_weak_queue { public: // types typedef T value_type; typedef implementation_defined::allocator allocator; typedef implementation_defined::size_type size_type; // public member functions bool is_lock_free() const; mpsc_weak_queue(); template<typename U, typename Enabler = std::enable_if< has_capacity || !use_freelist > > explicit mpsc_weak_queue(typename boost::allocator_rebind< node_allocator, U >::type const &); template<typename Enabler = std::enable_if< has_capacity || !use_freelist > > explicit mpsc_weak_queue(allocator const &); template<typename Enabler = std::enable_if< !has_capacity && use_freelist > > explicit mpsc_weak_queue(size_type); template<typename Enabler = std::enable_if< !has_capacity && use_freelist > > mpsc_weak_queue(size_type, allocator const &); mpsc_weak_queue(const mpsc_weak_queue &) = delete; mpsc_weak_queue & operator=(const mpsc_weak_queue &) = delete; mpsc_weak_queue(mpsc_weak_queue &&) = delete; mpsc_weak_queue & operator=(mpsc_weak_queue &&) = delete; template<typename Enabler = std::enable_if< can_reserve > > void reserve(size_type); template<typename Enabler = std::enable_if< can_reserve > > void reserve_unsafe(size_type); ~mpsc_weak_queue(); bool empty() const; bool push(const T &); bool push(T &&); template<typename Enabler = std::enable_if< use_freelist > > bool bounded_push(const T &); template<typename Enabler = std::enable_if< use_freelist > > bool bounded_push(T &&); bool unsynchronized_push(const T &); bool unsynchronized_push(T &&); bool pop(T &); template<typename U, typename Enabler = std::enable_if_t< std::is_constructible< U, T&& >::value > > bool pop(U &); std::optional< T > pop(uses_optional_t); template<typename U> std::optional< U > pop(uses_optional_t); bool unsynchronized_pop(T &); template<typename U, typename Enabler = std::enable_if_t< std::is_constructible< U, T&& >::value > > bool unsynchronized_pop(U &); template<typename Functor> bool consume_one(Functor &&); template<typename Functor> bool unsynchronized_consume_one(Functor &&); template<typename Functor> size_t consume_all(Functor &&); };
Multi-producer/single-consumer queue based on Dmitry Vyukov's MPSC algorithm.
The push and pop methods execute in a bounded number of instructions (wait-free execution), but the queue as a whole is not lock-free in the strict sense (see Limitations).
By default, a freelist manages node memory. Freed nodes are recycled internally rather than returned to the OS until the queue is destroyed.
Limitations. A good writeup of the limitations of this algorithm is available at Ode to a Vyukov Queue.
Push atomicity: push exchanges the tail then links the previous node. If a producer thread terminates or stalls between these steps, the queue becomes inconsistent. The consumer will see a broken link and stop delivering elements until the producer completes the link. If the producer permanently terminates, the queue is permanently broken.
Non-linearizable: per-producer FIFO is preserved, but no global ordering across concurrent producers exists. pop may return false even if the queue is non-empty when a concurrent push is in progress.
Policies.
boost::lockfree::freelist (default true):
When enabled, freed nodes enter an internal freelist for reuse, avoiding repeated allocation. When disabled, the allocator handles every allocation and deallocation. Allocator operations may not be lock-free.
boost::lockfree::fixed_sized (default false):
When enabled, push never performs dynamic allocation, guaranteeing lock-free behavior. Nodes reside in a fixed array addressed by index. Capacity is limited to the index type's range (typically 2^16-2). This is required for lock-free operation on platforms lacking double-width CAS.
boost::lockfree::capacity (optional):
Sets queue size at compile time. Implies fixed_sized<true>.
boost::lockfree::allocator (default std::allocator<void>).
Requirements.
T must be move-constructible.
T must be move-assignable.
![]() |
Note |
|---|---|
Only one consumer thread is supported. Multiple producer threads are supported. |
mpsc_weak_queue public member functionsbool is_lock_free() const;
![]() |
Warning |
|---|---|
Only checks whether the head, tail, and freelist can be modified in a lock-free manner. On most platforms the entire implementation is lock-free when this returns true. |
Returns: |
true if the implementation is lock-free. |
mpsc_weak_queue();
Construct a queue.
Requires a capacity<> argument when freelist is enabled.
template<typename U, typename Enabler = std::enable_if< has_capacity || !use_freelist > > explicit mpsc_weak_queue(typename boost::allocator_rebind< node_allocator, U >::type const & alloc);
Construct a fixed-sized queue with a custom allocator.
Requires a capacity<> argument when freelist is enabled.
template<typename Enabler = std::enable_if< has_capacity || !use_freelist > > explicit mpsc_weak_queue(allocator const & alloc);
Construct a fixed-sized queue with a custom allocator.
Requires a capacity<> argument when freelist is enabled.
template<typename Enabler = std::enable_if< !has_capacity && use_freelist > > explicit mpsc_weak_queue(size_type n);
Construct a variable-sized queue.
Allocates n nodes initially for the freelist.
Requires that no capacity<> argument is specified and that freelist is enabled.
template<typename Enabler = std::enable_if< !has_capacity && use_freelist > > mpsc_weak_queue(size_type n, allocator const & alloc);
Construct a variable-sized queue with a custom allocator.
Allocates n nodes initially for the freelist.
Requires that no capacity<> argument is specified and that freelist is enabled.
mpsc_weak_queue(const mpsc_weak_queue &) = delete;
mpsc_weak_queue & operator=(const mpsc_weak_queue &) = delete;
mpsc_weak_queue(mpsc_weak_queue &&) = delete;
mpsc_weak_queue & operator=(mpsc_weak_queue &&) = delete;
template<typename Enabler = std::enable_if< can_reserve > > void reserve(size_type n);
Allocate n nodes for freelist
![]() |
Note |
|---|---|
thread-safe, may block if memory allocator blocks |
Requires: |
only valid if no capacity<> argument given |
template<typename Enabler = std::enable_if< can_reserve > > void reserve_unsafe(size_type n);
Allocate n nodes for freelist
![]() |
Note |
|---|---|
not thread-safe, may block if memory allocator blocks |
Requires: |
only valid if no capacity<> argument given |
~mpsc_weak_queue();
Destroys the queue and frees all nodes from the freelist.
bool empty() const;
Check whether the queue is empty.
![]() |
Note |
|---|---|
The result is only accurate when no other thread modifies the queue concurrently. |
Returns: |
true if the queue is empty, false otherwise. |
bool push(const T & t);
Pushes a value to the queue.
![]() |
Note |
|---|---|
Thread-safe. Multiple producers may call push concurrently. When the memory pool is exhausted and the pool is not fixed-sized, a new node is allocated via the allocator, which may not be lock-free. |
Returns: |
true if the value was pushed, false if node allocation failed. |
bool push(T && t);
Pushes a value to the queue.
![]() |
Note |
|---|---|
Thread-safe. Multiple producers may call push concurrently. When the memory pool is exhausted and the pool is not fixed-sized, a new node is allocated via the allocator, which may not be lock-free. |
Returns: |
true if the value was pushed, false if node allocation failed. |
template<typename Enabler = std::enable_if< use_freelist > > bool bounded_push(const T & t);
Pushes a value to the queue without allocating.
![]() |
Note |
|---|---|
Thread-safe. Multiple producers may call bounded_push concurrently. Unlike push, bounded_push never allocates memory; it fails when the freelist is exhausted. |
Returns: |
true if the value was pushed, false if the freelist is empty. |
Throws: |
std::bad_alloc if the allocator throws during node construction. |
template<typename Enabler = std::enable_if< use_freelist > > bool bounded_push(T && t);
Pushes a value to the queue without allocating.
![]() |
Note |
|---|---|
Thread-safe. Multiple producers may call bounded_push concurrently. Unlike push, bounded_push never allocates memory; it fails when the freelist is exhausted. |
Returns: |
true if the value was pushed, false if the freelist is empty. |
Throws: |
std::bad_alloc if the allocator throws during node construction. |
bool unsynchronized_push(const T & t);
Pushes a value to the queue without synchronization.
![]() |
Note |
|---|---|
Not thread-safe. Only one producer thread should call unsynchronized_push. When the memory pool is exhausted and the pool is not fixed-sized, a new node is allocated via the allocator, which may not be lock-free. |
Returns: |
true if the value was pushed, false if node allocation failed. |
Throws: |
std::bad_alloc if the allocator throws during node construction. |
bool unsynchronized_push(T && t);
Pushes a value to the queue without synchronization.
![]() |
Note |
|---|---|
Not thread-safe. Only one producer thread should call unsynchronized_push. When the memory pool is exhausted and the pool is not fixed-sized, a new node is allocated via the allocator, which may not be lock-free. |
Returns: |
true if the value was pushed, false if node allocation failed. |
Throws: |
std::bad_alloc if the allocator throws during node construction. |
bool pop(T & ret);
Pops an element from the queue.
![]() |
Note |
|---|---|
Thread-safe and wait-free. Only one consumer thread should call pop. The output argument may be modified even when the operation fails. pop may return false even if the queue is non-empty when a concurrent push is in progress (see Limitations). |
Returns: |
true if an element was popped, false if the queue was empty. |
template<typename U, typename Enabler = std::enable_if_t< std::is_constructible< U, T&& >::value > > bool pop(U & ret);
Pops an element from the queue.
![]() |
Note |
|---|---|
Thread-safe and wait-free. Only one consumer thread should call pop. The output argument may be modified even when the operation fails. pop may return false even if the queue is non-empty when a concurrent push is in progress (see Limitations). |
Template Parameters: |
|
||
Returns: |
true if an element was popped, false if the queue was empty. |
std::optional< T > pop(uses_optional_t);
Pops an element, returning a std::optional<T>.
![]() |
Note |
|---|---|
Thread-safe and wait-free. Only one consumer thread should call this overload. |
Returns: |
std::optional containing the value on success, std::nullopt if the queue is empty. |
template<typename U> std::optional< U > pop(uses_optional_t);
Pops an element, returning a std::optional.
![]() |
Note |
|---|---|
Thread-safe and wait-free. Only one consumer thread should call this overload. |
Template Parameters: |
|
||
Returns: |
std::optional<U> containing the value on success, std::nullopt if the queue is empty. |
bool unsynchronized_pop(T & ret);
Pops an element without synchronization.
![]() |
Note |
|---|---|
Not thread-safe but wait-free. Only one consumer thread should call unsynchronized_pop. The output argument may be modified even when the operation fails. |
Returns: |
true if an element was popped, false if the queue was empty. |
template<typename U, typename Enabler = std::enable_if_t< std::is_constructible< U, T&& >::value > > bool unsynchronized_pop(U & ret);
Pops an element without synchronization.
![]() |
Note |
|---|---|
Not thread-safe but wait-free. Only one consumer thread should call unsynchronized_pop. |
Template Parameters: |
|
||
Returns: |
true if an element was popped, false if the queue was empty. |
template<typename Functor> bool consume_one(Functor && f);
Consumes one element via a functor.
Pops one element and applies the functor to it.
![]() |
Note |
|---|---|
Thread-safe and wait-free when the functor is thread-safe and non-blocking. Only one consumer thread should call this. |
Returns: |
true if an element was consumed. |
template<typename Functor> bool unsynchronized_consume_one(Functor && f);
Consumes one element via a functor without synchronization.
Pops one element and applies the functor to it.
![]() |
Note |
|---|---|
Not thread-safe but wait-free. Only one consumer thread should call this. |
Returns: |
true if an element was consumed. |
template<typename Functor> size_t consume_all(Functor && f);
Consumes all elements via a functor.
Sequentially pops all elements and applies the functor to each.
![]() |
Note |
|---|---|
Thread-safe and wait-free when the functor is thread-safe and non-blocking. Only one consumer thread should call this. |
Returns: |
the number of elements consumed. |