3 #ifndef __CDS_CONTAINER_MSPRIORITY_QUEUE_H
4 #define __CDS_CONTAINER_MSPRIORITY_QUEUE_H
7 #include <cds/container/details/base.h>
8 #include <cds/intrusive/mspriority_queue.h>
10 namespace cds { namespace container {
12 /// MSPriorityQueue related definitions
13 /** @ingroup cds_nonintrusive_helper
15 namespace mspriority_queue {
17 #ifdef CDS_DOXYGEN_INVOKED
18 /// Synonym for cds::intrusive::mspriority_queue::stat
19 typedef cds::intrusive::mspriority_queue::stat<> stat;
21 /// Synonym for cds::intrusive::mspriority_queue::empty_stat
22 typedef cds::intrusive::mspriority_queue::empty_stat empty_stat;
24 using cds::intrusive::mspriority_queue::stat;
25 using cds::intrusive::mspriority_queue::empty_stat;
28 /// Type traits for MSPriorityQueue
30 The type traits for cds::container::MSPriorityQueue is the same as for
31 cds::intrusive::MSPriorityQueue (see cds::intrusive::mspriority_queue::type_traits)
32 plus some additional properties.
34 struct type_traits: public cds::intrusive::mspriority_queue::type_traits
36 /// The allocator use to allocate memory for values
37 typedef CDS_DEFAULT_ALLOCATOR allocator;
41 The move policy used in MSPriorityQueue::pop functions
43 Default is opt::v::assignment_move_policy.
45 typedef cds::opt::v::assignment_move_policy move_policy;
48 /// Metafunction converting option list to traits
50 This is a wrapper for <tt> cds::opt::make_options< type_traits, Options...> </tt>
52 See \ref MSPriorityQueue, \ref type_traits, \ref cds::opt::make_options.
54 template <typename... Options>
56 # ifdef CDS_DOXYGEN_INVOKED
57 typedef implementation_defined type ; ///< Metafunction result
59 typedef typename cds::opt::make_options<
60 typename cds::opt::find_type_traits< type_traits, Options... >::type
65 } // namespace mspriority_queue
67 /// Michael & Scott array-based lock-based concurrent priority queue heap
68 /** @ingroup cds_nonintrusive_priority_queue
70 - [1996] G.Hunt, M.Michael, S. Parthasarathy, M.Scott
71 "An efficient algorithm for concurrent priority queue heaps"
73 \p %MSPriorityQueue augments the standard array-based heap data structure with
74 a mutual-exclusion lock on the heap's size and locks on each node in the heap.
75 Each node also has a tag that indicates whether
76 it is empty, valid, or in a transient state due to an update to the heap
77 by an inserting thread.
78 The algorithm allows concurrent insertions and deletions in opposite directions,
79 without risking deadlock and without the need for special server threads.
80 It also uses a "bit-reversal" technique to scatter accesses across the fringe
81 of the tree to reduce contention.
82 On large heaps the algorithm achieves significant performance improvements
83 over serialized single-lock algorithm, for various insertion/deletion
84 workloads. For small heaps it still performs well, but not as well as
85 single-lock algorithm.
88 - \p T - type to be stored in the list. The priority is a part of \p T type.
89 - \p Traits - type traits. See mspriority_queue::type_traits for explanation.
91 It is possible to declare option-based queue with cds::container::mspriority_queue::make_traits
92 metafunction instead of \p Traits template argument.
93 Template argument list \p Options of \p %cds::container::mspriority_queue::make_traits metafunction are:
94 - opt::buffer - the buffer type for heap array. Possible type are: opt::v::static_buffer, opt::v::dynamic_buffer.
95 Default is \p %opt::v::dynamic_buffer.
96 You may specify any type of values for the buffer since at instantiation time
97 the \p buffer::rebind member metafunction is called to change the type of values stored in the buffer.
98 - opt::compare - priority compare functor. No default functor is provided.
99 If the option is not specified, the opt::less is used.
100 - opt::less - specifies binary predicate used for priority compare. Default is \p std::less<T>.
101 - opt::lock_type - lock type. Default is cds::lock::Spin.
102 - opt::back_off - back-off strategy. Default is cds::backoff::yield
103 - opt::allocator - allocator (like \p std::allocator) for the values of queue's items.
104 Default is \ref CDS_DEFAULT_ALLOCATOR
105 - opt::move_policy - policy for moving item's value. Default is opt::v::assignment_move_policy.
106 If the compiler supports move semantics it would be better to specify the move policy
107 based on the move semantics for type \p T.
108 - opt::stat - internal statistics. Available types: mspriority_queue::stat, mspriority_queue::empty_stat (the default)
110 template <typename T, class Traits>
111 class MSPriorityQueue: protected cds::intrusive::MSPriorityQueue< T, Traits >
114 typedef cds::intrusive::MSPriorityQueue< T, Traits > base_class;
117 typedef T value_type ; ///< Value type stored in the queue
118 typedef Traits traits ; ///< Traits template parameter
120 typedef typename base_class::key_comparator key_comparator; ///< priority comparing functor based on opt::compare and opt::less option setter.
121 typedef typename base_class::lock_type lock_type; ///< heap's size lock type
122 typedef typename base_class::back_off back_off ; ///< Back-off strategy
123 typedef typename base_class::stat stat ; ///< internal statistics type
124 typedef typename traits::allocator::template rebind<value_type>::other allocator_type; ///< Value allocator
125 typedef typename traits::move_policy move_policy; ///< Move policy for type \p T
129 typedef cds::details::Allocator< value_type, allocator_type > cxx_allocator;
131 struct value_deleter {
132 void operator()( value_type * p ) const
134 cxx_allocator().Delete( p );
137 typedef std::unique_ptr<value_type, value_deleter> scoped_ptr;
141 /// Constructs empty priority queue
143 For cds::opt::v::static_buffer the \p nCapacity parameter is ignored.
145 MSPriorityQueue( size_t nCapacity )
146 : base_class( nCapacity )
149 /// Clears priority queue and destructs the object
155 /// Inserts a item into priority queue
157 If the priority queue is full, the function returns \p false,
158 no item has been added.
159 Otherwise, the function inserts the copy of \p val into the heap
162 The function use copy constructor to create new heap item from \p val.
164 bool push( value_type const& val )
166 scoped_ptr pVal( cxx_allocator().New( val ));
167 if ( base_class::push( *(pVal.get()) )) {
174 /// Inserts a item into priority queue
176 If the priority queue is full, the function returns \p false,
177 no item has been added.
178 Otherwise, the function inserts a new item created from \p args arguments
179 into the heap and returns \p true.
181 template <typename... Args>
182 bool emplace( Args&&... args )
184 scoped_ptr pVal( cxx_allocator().MoveNew( std::forward<Args>(args)... ));
185 if ( base_class::push( *(pVal.get()) )) {
192 /// Extracts item with high priority
194 If the priority queue is empty, the function returns \p false.
195 Otherwise, it returns \p true and \p dest contains the copy of extracted item.
196 The item is deleted from the heap.
198 The function uses \ref move_policy to move extracted value from the heap's top
201 The function is equivalent of such call:
203 pop_with( dest, move_policy() );
206 bool pop( value_type& dest )
208 return pop_with( dest, move_policy() );
211 /// Extracts item with high priority
213 If the priority queue is empty, the function returns \p false.
214 Otherwise, it returns \p true and \p dest contains the copy of extracted item.
215 The item is deleted from the heap.
217 The function uses \p MoveFunc \p f to move extracted value from the heap's top
218 to \p dest. The interface of \p MoveFunc is:
220 struct move_functor {
221 void operator()( Q& dest, T& src );
224 In \p MoveFunc you may use move semantics for \p src argument
225 since \p src will be destroyed.
227 template <typename Q, typename MoveFunc>
228 bool pop_with( Q& dest, MoveFunc f )
230 value_type * pVal = base_class::pop();
233 cxx_allocator().Delete( pVal );
239 /// Clears the queue (not atomic)
241 This function is no atomic, but thread-safe
245 base_class::clear_with( []( value_type& src ) { cxx_allocator().Delete( &src ); });
248 /// Clears the queue (not atomic)
250 This function is no atomic, but thread-safe.
252 For each item removed the functor \p f is called.
253 \p Func interface is:
257 void operator()( value_type& item );
260 A lambda function or a function pointer can be used as \p f.
262 template <typename Func>
263 void clear_with( Func f )
265 base_class::clear_with( [&f]( value_type& val ) { f(val); value_deleter()( &val ); } );
268 /// Checks is the priority queue is empty
271 return base_class::empty();
274 /// Checks if the priority queue is full
277 return base_class::full();
280 /// Returns current size of priority queue
283 return base_class::size();
286 /// Return capacity of the priority queue
287 size_t capacity() const
289 return base_class::capacity();
292 /// Returns const reference to internal statistics
293 stat const& statistics() const
295 return base_class::statistics();
299 }} // namespace cds::container
301 #endif // #ifndef __CDS_CONTAINER_MSPRIORITY_QUEUE_H