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

Class template bounded_ticket_queue
PrevUpHomeNext

Class template bounded_ticket_queue

boost::lockfree::bounded_ticket_queue

Synopsis

// In header: <boost/lockfree/bounded_ticket_queue.hpp>

template<typename T, typename... Options> 
class bounded_ticket_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;
  bounded_ticket_queue();
  template<typename Enabler = std::enable_if< !has_capacity > > 
    explicit bounded_ticket_queue(size_type);
  template<typename Enabler = std::enable_if< !has_capacity > > 
    bounded_ticket_queue(size_type, allocator const &);
  bounded_ticket_queue(const bounded_ticket_queue &) = delete;
  bounded_ticket_queue & operator=(const bounded_ticket_queue &) = delete;
  bounded_ticket_queue(bounded_ticket_queue &&) = delete;
  bounded_ticket_queue & operator=(bounded_ticket_queue &&) = delete;
  ~bounded_ticket_queue();
  bool empty() const;
  size_type capacity() const;
  bool push(const T &);
  bool push(T &&);
  bool pop(T &);
  template<typename U, 
           typename Enabler = typename std::enable_if< std::is_constructible< U, T&& >::value >::type> 
    bool pop(U &);
  std::optional< T > pop(uses_optional_t);
  template<typename U> std::optional< U > pop(uses_optional_t);
  template<typename Functor> bool consume_one(Functor &&);
  template<typename Functor> size_t consume_all(Functor &&);
};

Description

Bounded ticket queue based on Dmitry Vyukov's bounded MPMC queue (the "Dyukov turnstile") (reference).

The queue uses a fixed-size ring buffer of cells, each protected by a monotonically increasing ticket (sequence number). Producers and consumers coordinate solely by advancing this ticket.

The data structure is linearizable.

Caveats. 

  • Multi-producer push is not lock-free. A concurrent producer that has claimed a slot via CAS but is then suspended can block all other producers once the ring buffer wraps around to that slot. In practice preemption is brief, but hard real-time systems should prefer a single-producer configuration.

  • Multi-consumer pop is not lock-free. Symmetric stall risk as multi-producer push. Prefer single_consumer<true> for hard real-time.

  • Unfairness. The CAS-based slot reservation provides no FIFO or fairness guarantee.

Policies. 

Requirements. 

  • T must be copy- or move-constructible, depending on which push overload is used.

  • T must be move-constructible and move-assignable.

bounded_ticket_queue public member functions

  1. bool is_lock_free() const;

    With single-producer and single-consumer the queue is wait-free (no CAS used). For multi-consumer or multi-producer configurations only the atomic positions used with CAS are checked.

    Returns:

    true if the implementation is lock-free.

  2. bounded_ticket_queue();

    Construct a queue with compile-time capacity.

    Storage is allocated in a static buffer; no heap allocation is performed.

    Requires:

    Must specify a capacity<> argument >= 2.

  3. template<typename Enabler = std::enable_if< !has_capacity > > 
      explicit bounded_ticket_queue(size_type n);

    Construct a queue with runtime capacity.

    Parameters:

    n

    Queue capacity. Must be >= 2. Not required to be a power of two, but power-of-two sizes use a fast masking path.

    Requires:

    Must not specify a capacity<> argument.

  4. template<typename Enabler = std::enable_if< !has_capacity > > 
      bounded_ticket_queue(size_type n, allocator const & alloc);

    Construct a queue with runtime capacity and custom allocator.

    Parameters:

    n

    Queue capacity. Must be >= 2.

    alloc

    Allocator used for the cell storage. Its value_type is rebound to cell.

    Requires:

    Must not specify a capacity<> argument.

  5. bounded_ticket_queue(const bounded_ticket_queue &) = delete;
  6. bounded_ticket_queue & operator=(const bounded_ticket_queue &) = delete;
  7. bounded_ticket_queue(bounded_ticket_queue &&) = delete;
  8. bounded_ticket_queue & operator=(bounded_ticket_queue &&) = delete;
  9. ~bounded_ticket_queue();

    Destroys the queue.

  10. bool empty() const;

    Check whether the queue is empty.

    [Note] Note

    The result is only accurate when no other thread modifies the queue concurrently.

    Returns:

    true if the queue is empty, false otherwise.

  11. size_type capacity() const;

    Returns:

    the capacity of the queue.

  12. bool push(const T & t);

    Pushes a value to the queue.

    [Note] Note

    Thread-safe. Multiple producers may call push concurrently. Never allocates memory.

    Returns:

    true if the value was pushed, false if the queue is full.

  13. bool push(T && t);
  14. bool pop(T & ret);

    Pops an element from the queue.

    Returns:

    true if an element was popped, false if the queue was empty.

  15. template<typename U, 
             typename Enabler = typename std::enable_if< std::is_constructible< U, T&& >::value >::type> 
      bool pop(U & ret);

    Pops an element from the queue.

    Template Parameters:

    U

    type to receive the popped value; U must be constructible from T&& and assignable from U.

    Returns:

    true if an element was popped, false if the queue was empty.

  16. std::optional< T > pop(uses_optional_t);

    Pops an element, returning a std::optional<T>.

    Returns:

    std::optional containing the value on success, std::nullopt if the queue is empty.

  17. template<typename U> std::optional< U > pop(uses_optional_t);

    Pops an element, returning a std::optional.

    Template Parameters:

    U

    type to receive the popped value; T must be convertible to U.

    Returns:

    std::optional<U> containing the value on success, std::nullopt if the queue is empty.

  18. template<typename Functor> bool consume_one(Functor && f);

    Consumes one element via a functor.

    Moves one element out of the slot, passes the resulting rvalue to the functor, and releases the slot for reuse once the functor returns.

    Returns:

    true if an element was consumed.

  19. 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.

    Returns:

    the number of elements consumed.


PrevUpHomeNext