3 #ifndef __CDS_INTRUSIVE_VYUKOV_MPMC_CYCLE_QUEUE_H
4 #define __CDS_INTRUSIVE_VYUKOV_MPMC_CYCLE_QUEUE_H
6 #include <cds/intrusive/details/base.h>
7 #include <cds/container/vyukov_mpmc_cycle_queue.h>
9 namespace cds { namespace intrusive {
11 /// Vyukov's MPMC bounded queue
12 /** @ingroup cds_intrusive_queue
13 This algorithm is developed by Dmitry Vyukov (see http://www.1024cores.net)
15 Implementation of intrusive version is based on non-intrusive class container::VyukovMPMCCycleQueue.
18 - \p T - type stored in queue.
19 - \p Options - queue's options
21 Options \p Options are:
22 - opt::buffer - buffer to store items. Mandatory option, see option description for full list of possible types.
23 - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter
24 - opt::disposer - the functor used for dispose removed items. Default is opt::v::empty_disposer. This option is used
25 only in \ref clear function.
26 - opt::alignment - the alignment for internal queue data. Default is opt::cache_line_alignment
27 - opt::memory_model - C++ memory ordering model. Can be opt::v::relaxed_ordering (relaxed memory model, the default)
28 or opt::v::sequential_consistent (sequentially consisnent memory model).
31 Instead of saving copy of enqueued data, the intrusive implementation stores pointer to passed data.
35 #include <cds/intrusive/vyukov_mpmc_cycle_queue.h>
41 // Queue of Foo pointers, capacity is 1024, statically allocated buffer:
42 typedef cds::intrusive::VyukovMPMCCycleQueue<
44 ,cds::opt::buffer< cds::opt::v::static_buffer< Foo, 1024 > >
48 // Queue of Foo pointers, capacity is 1024, dynamically allocated buffer:
49 typedef cds::intrusive::VyukovMPMCCycleQueue<
51 ,cds::opt::buffer< cds::opt::v::dynamic_buffer< Foo > >
53 dynamic_queue dynQueue( 1024 );
57 template <typename T, typename... Options>
58 class VyukovMPMCCycleQueue
59 : private container::VyukovMPMCCycleQueue< T *, Options... >
62 typedef container::VyukovMPMCCycleQueue< T *, Options... > base_class;
65 typedef T value_type ; ///< type of data stored in the queue
66 typedef typename base_class::item_counter item_counter ; ///< Item counter type
67 typedef typename base_class::memory_model memory_model ; ///< Memory ordering. See cds::opt::memory_model option
68 typedef typename base_class::options::disposer disposer ; ///< Item disposer
71 typedef typename base_class::options options;
75 /// Rebind template arguments
76 template <typename T2, typename... Options2>
78 typedef VyukovMPMCCycleQueue< T2, Options2...> other ; ///< Rebinding result
82 /// Constructs the queue of capacity \p nCapacity
84 For cds::opt::v::static_buffer the \p nCapacity parameter is ignored.
86 VyukovMPMCCycleQueue( size_t nCapacity = 0 )
87 : base_class( nCapacity )
90 /// Enqueues \p data to queue
92 Note that the intrusive queue stores pointer to \p data passed, not the copy of data.
94 bool enqueue( value_type& data )
96 return base_class::enqueue( &data );
99 /// Dequeues an item from queue
101 If queue is empty, returns \p nullptr.
103 value_type * dequeue()
105 value_type * p = nullptr;
106 return base_class::dequeue( p ) ? p : nullptr;
109 /// Synonym of \ref enqueue
110 bool push( value_type& data )
112 return enqueue( data );
115 /// Synonym of \ref dequeue
121 /// Clears queue in lock-free manner.
123 \p f parameter is a functor to dispose removed items.
124 The interface of \p DISPOSER is:
127 void operator ()( T * val );
130 You can pass \p disposer by reference using \p std::ref.
131 The disposer will be called immediately for each item.
133 template <typename Disposer>
134 void clear( Disposer f )
137 while ( (pv = pop()) != nullptr ) {
144 This function uses the disposer that is specified in \p Options.
151 /// Checks if the queue is empty
154 return base_class::empty();
158 /// Returns queue's item count
160 The value returned depends on opt::item_counter option. For atomicity::empty_item_counter,
161 this function always returns 0.
165 return base_class::size();
168 /// Returns capacity of cyclic buffer
169 size_t capacity() const
171 return base_class::capacity();
174 }} // namespace cds::intrusive
176 #endif // #ifndef __CDS_INTRUSIVE_VYUKOV_MPMC_CYCLE_QUEUE_H