9f699af9569448fda658c83c718fdd2a1c734364
[libcds.git] / cds / container / impl / skip_list_set.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_IMPL_SKIP_LIST_SET_H
4 #define __CDS_CONTAINER_IMPL_SKIP_LIST_SET_H
5
6 #include <cds/details/binary_functor_wrapper.h>
7 #include <cds/container/details/guarded_ptr_cast.h>
8
9 namespace cds { namespace container {
10
11     /// Lock-free skip-list set
12     /** @ingroup cds_nonintrusive_set
13         \anchor cds_nonintrusive_SkipListSet_hp
14
15         The implementation of well-known probabilistic data structure called skip-list
16         invented by W.Pugh in his papers:
17             - [1989] W.Pugh Skip Lists: A Probabilistic Alternative to Balanced Trees
18             - [1990] W.Pugh A Skip List Cookbook
19
20         A skip-list is a probabilistic data structure that provides expected logarithmic
21         time search without the need of rebalance. The skip-list is a collection of sorted
22         linked list. Nodes are ordered by key. Each node is linked into a subset of the lists.
23         Each list has a level, ranging from 0 to 32. The bottom-level list contains
24         all the nodes, and each higher-level list is a sublist of the lower-level lists.
25         Each node is created with a random top level (with a random height), and belongs
26         to all lists up to that level. The probability that a node has the height 1 is 1/2.
27         The probability that a node has the height N is 1/2 ** N (more precisely,
28         the distribution depends on an random generator provided, but our generators
29         have this property).
30
31         The lock-free variant of skip-list is implemented according to book
32             - [2008] M.Herlihy, N.Shavit "The Art of Multiprocessor Programming",
33                 chapter 14.4 "A Lock-Free Concurrent Skiplist"
34
35         Template arguments:
36         - \p GC - Garbage collector used.
37         - \p T - type to be stored in the list.
38         - \p Traits - set traits, default is \p skip_list::traits.
39             It is possible to declare option-based list with \p cds::container::skip_list::make_traits metafunction 
40             istead of \p Traits template argument.
41
42         @warning The skip-list requires up to 67 hazard pointers that may be critical for some GCs for which
43             the guard count is limited (like as \p gc::HP). Those GCs should be explicitly initialized with
44             hazard pointer enough: \code cds::gc::HP myhp( 67 ) \endcode. Otherwise an run-time exception may be raised
45             when you try to create skip-list object.
46
47         @note There are several specializations of \p %SkipListSet for each \p GC. You should include:
48         - <tt><cds/container/skip_list_set_hp.h></tt> for \p gc::HP garbage collector
49         - <tt><cds/container/skip_list_set_dhp.h></tt> for \p gc::DHP garbage collector
50         - <tt><cds/container/skip_list_set_rcu.h></tt> for \ref cds_nonintrusive_SkipListSet_rcu "RCU type"
51         - <tt><cds/container/skip_list_set_nogc.h></tt> for \ref cds_nonintrusive_SkipListSet_nogc "non-deletable SkipListSet"
52
53         <b>Iterators</b>
54
55         The class supports a forward iterator (\ref iterator and \ref const_iterator).
56         The iteration is ordered.
57         The iterator object is thread-safe: the element pointed by the iterator object is guarded,
58         so, the element cannot be reclaimed while the iterator object is alive.
59         However, passing an iterator object between threads is dangerous.
60
61         \warning Due to concurrent nature of skip-list set it is not guarantee that you can iterate
62         all elements in the set: any concurrent deletion can exclude the element
63         pointed by the iterator from the set, and your iteration can be terminated
64         before end of the set. Therefore, such iteration is more suitable for debugging purpose only
65
66         Remember, each iterator object requires 2 additional hazard pointers, that may be
67         a limited resource for \p GC like \p gc::HP (for \p gc::DHP the count of
68         guards is unlimited).
69
70         The iterator class supports the following minimalistic interface:
71         \code
72         struct iterator {
73             // Default ctor
74             iterator();
75
76             // Copy ctor
77             iterator( iterator const& s);
78
79             value_type * operator ->() const;
80             value_type& operator *() const;
81
82             // Pre-increment
83             iterator& operator ++();
84
85             // Copy assignment
86             iterator& operator = (const iterator& src);
87
88             bool operator ==(iterator const& i ) const;
89             bool operator !=(iterator const& i ) const;
90         };
91         \endcode
92         Note, the iterator object returned by \p end(), \p cend() member functions points to \p nullptr and should not be dereferenced.
93     */
94     template <
95         typename GC,
96         typename T,
97 #ifdef CDS_DOXYGEN_INVOKED
98         typename Traits = skip_list::traits
99 #else
100         typename Traits
101 #endif
102     >
103     class SkipListSet:
104 #ifdef CDS_DOXYGEN_INVOKED
105         protected intrusive::SkipListSet< GC, T, Traits >
106 #else
107         protected details::make_skip_list_set< GC, T, Traits >::type
108 #endif
109     {
110         //@cond
111         typedef details::make_skip_list_set< GC, T, Traits > maker;
112         typedef typename maker::type base_class;
113         //@endcond
114     public:
115         typedef GC     gc;          ///< Garbage collector used
116         typedef T      value_type;  ///< @anchor cds_containewr_SkipListSet_value_type Value type to be stored in the set
117         typedef Traits traits;      ///< Options specified
118
119         typedef typename base_class::back_off     back_off;       ///< Back-off strategy
120         typedef typename traits::allocator        allocator_type; ///< Allocator type used for allocate/deallocate the skip-list nodes
121         typedef typename base_class::item_counter item_counter;   ///< Item counting policy used
122         typedef typename maker::key_comparator    key_comparator; ///< key comparison functor
123         typedef typename base_class::memory_model memory_model;   ///< Memory ordering. See cds::opt::memory_model option
124         typedef typename traits::random_level_generator random_level_generator; ///< random level generator
125         typedef typename traits::stat             stat;           ///< internal statistics type
126
127     protected:
128         //@cond
129         typedef typename maker::node_type           node_type;
130         typedef typename maker::node_allocator      node_allocator;
131
132         typedef std::unique_ptr< node_type, typename maker::node_deallocator >    scoped_node_ptr;
133         //@endcond
134
135     public:
136         /// Guarded pointer
137         typedef cds::gc::guarded_ptr< gc, node_type, value_type, details::guarded_ptr_cast_set<node_type, value_type> > guarded_ptr;
138
139     protected:
140         //@cond
141         unsigned int random_level()
142         {
143             return base_class::random_level();
144         }
145         //@endcond
146
147     public:
148         /// Default ctor
149         SkipListSet()
150             : base_class()
151         {}
152
153         /// Destructor destroys the set object
154         ~SkipListSet()
155         {}
156
157     public:
158         /// Iterator type
159         typedef skip_list::details::iterator< typename base_class::iterator >  iterator;
160
161         /// Const iterator type
162         typedef skip_list::details::iterator< typename base_class::const_iterator >   const_iterator;
163
164         /// Returns a forward iterator addressing the first element in a set
165         iterator begin()
166         {
167             return iterator( base_class::begin() );
168         }
169
170         /// Returns a forward const iterator addressing the first element in a set
171         const_iterator begin() const
172         {
173             return const_iterator( base_class::begin() );
174         }
175
176         /// Returns a forward const iterator addressing the first element in a set
177         const_iterator cbegin() const
178         {
179             return const_iterator( base_class::cbegin() );
180         }
181
182         /// Returns a forward iterator that addresses the location succeeding the last element in a set.
183         iterator end()
184         {
185             return iterator( base_class::end() );
186         }
187
188         /// Returns a forward const iterator that addresses the location succeeding the last element in a set.
189         const_iterator end() const
190         {
191             return const_iterator( base_class::end() );
192         }
193
194         /// Returns a forward const iterator that addresses the location succeeding the last element in a set.
195         const_iterator cend() const
196         {
197             return const_iterator( base_class::cend() );
198         }
199
200     public:
201         /// Inserts new node
202         /**
203             The function creates a node with copy of \p val value
204             and then inserts the node created into the set.
205
206             The type \p Q should contain as minimum the complete key for the node.
207             The object of \ref value_type should be constructible from a value of type \p Q.
208             In trivial case, \p Q is equal to \ref value_type.
209
210             Returns \p true if \p val is inserted into the set, \p false otherwise.
211         */
212         template <typename Q>
213         bool insert( Q const& val )
214         {
215             scoped_node_ptr sp( node_allocator().New( random_level(), val ));
216             if ( base_class::insert( *sp.get() )) {
217                 sp.release();
218                 return true;
219             }
220             return false;
221         }
222
223         /// Inserts new node
224         /**
225             The function allows to split creating of new item into two part:
226             - create item with key only
227             - insert new item into the set
228             - if inserting is success, calls  \p f functor to initialize value-fields of \p val.
229
230             The functor signature is:
231             \code
232                 void func( value_type& val );
233             \endcode
234             where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
235             \p val no any other changes could be made on this set's item by concurrent threads.
236             The user-defined functor is called only if the inserting is success.
237         */
238         template <typename Q, typename Func>
239         bool insert( Q const& val, Func f )
240         {
241             scoped_node_ptr sp( node_allocator().New( random_level(), val ));
242             if ( base_class::insert( *sp.get(), [&f]( node_type& val ) { f( val.m_Value ); } )) {
243                 sp.release();
244                 return true;
245             }
246             return false;
247         }
248
249         /// Ensures that the item exists in the set
250         /**
251             The operation performs inserting or changing data with lock-free manner.
252
253             If the \p val key not found in the set, then the new item created from \p val
254             is inserted into the set. Otherwise, the functor \p func is called with the item found.
255             The functor \p Func should be a function with signature:
256             \code
257                 void func( bool bNew, value_type& item, const Q& val );
258             \endcode
259             or a functor:
260             \code
261                 struct my_functor {
262                     void operator()( bool bNew, value_type& item, const Q& val );
263                 };
264             \endcode
265
266             with arguments:
267             - \p bNew - \p true if the item has been inserted, \p false otherwise
268             - \p item - item of the set
269             - \p val - argument \p key passed into the \p %ensure() function
270
271             The functor may change non-key fields of the \p item; however, \p func must guarantee
272             that during changing no any other modifications could be made on this item by concurrent threads.
273
274             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
275             \p second is true if new item has been added or \p false if the item with \p key
276             already is in the set.
277
278             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
279         */
280         template <typename Q, typename Func>
281         std::pair<bool, bool> ensure( const Q& val, Func func )
282         {
283             scoped_node_ptr sp( node_allocator().New( random_level(), val ));
284             std::pair<bool, bool> bRes = base_class::ensure( *sp,
285                 [&func, &val](bool bNew, node_type& node, node_type&){ func( bNew, node.m_Value, val ); });
286             if ( bRes.first && bRes.second )
287                 sp.release();
288             return bRes;
289         }
290
291         /// Inserts data of type \p value_type created in-place from <tt>std::forward<Args>(args)...</tt>
292         /**
293             Returns \p true if inserting successful, \p false otherwise.
294         */
295         template <typename... Args>
296         bool emplace( Args&&... args )
297         {
298             scoped_node_ptr sp( node_allocator().New( random_level(), std::forward<Args>(args)... ));
299             if ( base_class::insert( *sp.get() )) {
300                 sp.release();
301                 return true;
302             }
303             return false;
304         }
305
306         /// Delete \p key from the set
307         /** \anchor cds_nonintrusive_SkipListSet_erase_val
308
309             The set item comparator should be able to compare the type \p value_type
310             and the type \p Q.
311
312             Return \p true if key is found and deleted, \p false otherwise
313         */
314         template <typename Q>
315         bool erase( Q const& key )
316         {
317             return base_class::erase( key );
318         }
319
320         /// Deletes the item from the set using \p pred predicate for searching
321         /**
322             The function is an analog of \ref cds_nonintrusive_SkipListSet_erase_val "erase(Q const&)"
323             but \p pred is used for key comparing.
324             \p Less functor has the interface like \p std::less.
325             \p Less must imply the same element order as the comparator used for building the set.
326         */
327         template <typename Q, typename Less>
328         bool erase_with( Q const& key, Less pred )
329         {
330             CDS_UNUSED( pred );
331             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >() );
332         }
333
334         /// Delete \p key from the set
335         /** \anchor cds_nonintrusive_SkipListSet_erase_func
336
337             The function searches an item with key \p key, calls \p f functor
338             and deletes the item. If \p key is not found, the functor is not called.
339
340             The functor \p Func interface:
341             \code
342             struct extractor {
343                 void operator()(value_type const& val);
344             };
345             \endcode
346
347             Since the key of \p value_type is not explicitly specified,
348             template parameter \p Q defines the key type to search in the list.
349             The list item comparator should be able to compare the type \p T of list item
350             and the type \p Q.
351
352             Return \p true if key is found and deleted, \p false otherwise
353         */
354         template <typename Q, typename Func>
355         bool erase( Q const& key, Func f )
356         {
357             return base_class::erase( key, [&f]( node_type const& node) { f( node.m_Value ); } );
358         }
359
360         /// Deletes the item from the set using \p pred predicate for searching
361         /**
362             The function is an analog of \ref cds_nonintrusive_SkipListSet_erase_func "erase(Q const&, Func)"
363             but \p pred is used for key comparing.
364             \p Less functor has the interface like \p std::less.
365             \p Less must imply the same element order as the comparator used for building the set.
366         */
367         template <typename Q, typename Less, typename Func>
368         bool erase_with( Q const& key, Less pred, Func f )
369         {
370             CDS_UNUSED( pred );
371             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
372                 [&f]( node_type const& node) { f( node.m_Value ); } );
373         }
374
375         /// Extracts the item from the set with specified \p key
376         /** \anchor cds_nonintrusive_SkipListSet_hp_extract
377             The function searches an item with key equal to \p key in the set,
378             unlinks it from the set, and returns it in \p result parameter.
379             If the item with key equal to \p key is not found the function returns \p false.
380
381             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
382
383             The item extracted is freed automatically by garbage collector \p GC
384             when returned \ref guarded_ptr object will be destroyed or released.
385             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
386
387             Usage:
388             \code
389             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
390             skip_list theList;
391             // ...
392             {
393                 skip_list::guarded_ptr gp;
394                 if ( theList.extract( gp, 5 ) ) {
395                     // Deal with gp
396                     // ...
397                 }
398                 // Destructor of gp releases internal HP guard and frees the pointer
399             }
400             \endcode
401         */
402         template <typename Q>
403         bool extract( guarded_ptr& result, Q const& key )
404         {
405             return base_class::extract_( result.guard(), key, typename base_class::key_comparator() );
406         }
407
408         /// Extracts the item from the set with comparing functor \p pred
409         /**
410             The function is an analog of \ref cds_nonintrusive_SkipListSet_hp_extract "extract(Q const&)"
411             but \p pred predicate is used for key comparing.
412
413             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
414             in any order.
415             \p pred must imply the same element order as the comparator used for building the set.
416         */
417         template <typename Q, typename Less>
418         bool extract_with( guarded_ptr& ptr, Q const& key, Less pred )
419         {
420             CDS_UNUSED( pred );
421             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >  wrapped_less;
422             return base_class::extract_( ptr.guard(), key, cds::opt::details::make_comparator_from_less<wrapped_less>() );
423         }
424
425         /// Extracts an item with minimal key from the set
426         /**
427             The function searches an item with minimal key, unlinks it, and returns the item found in \p result parameter.
428             If the skip-list is empty the function returns \p false.
429
430             The item extracted is freed automatically by garbage collector \p GC
431             when returned \ref guarded_ptr object will be destroyed or released.
432             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
433
434             Usage:
435             \code
436             typedef cds::continer::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
437             skip_list theList;
438             // ...
439             {
440                 skip_list::guarded_ptr gp;
441                 if ( theList.extract_min( gp )) {
442                     // Deal with gp
443                     //...
444                 }
445                 // Destructor of gp releases internal HP guard and then frees the pointer
446             }
447             \endcode
448         */
449         bool extract_min( guarded_ptr& result)
450         {
451             return base_class::extract_min_( result.guard() );
452         }
453
454         /// Extracts an item with maximal key from the set
455         /**
456             The function searches an item with maximal key, unlinks it, and returns the pointer to item found in \p result parameter.
457             If the skip-list is empty the function returns \p false.
458
459             The item found is freed by garbage collector \p GC automatically
460             when returned \ref guarded_ptr object will be destroyed or released.
461             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
462
463             Usage:
464             \code
465             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
466             skip_list theList;
467             // ...
468             {
469                 skip_list::guarded_ptr gp;
470                 if ( theList.extract_max( gp )) {
471                     // Deal with gp
472                     //...
473                 }
474                 // Destructor of gp releases internal HP guard and then frees the pointer
475             }
476             \endcode
477         */
478         bool extract_max( guarded_ptr& result )
479         {
480             return base_class::extract_max_( result.guard() );
481         }
482
483         /// Find the \p key
484         /** \anchor cds_nonintrusive_SkipListSet_find_func
485
486             The function searches the item with key equal to \p key and calls the functor \p f for item found.
487             The interface of \p Func functor is:
488             \code
489             struct functor {
490                 void operator()( value_type& item, Q& key );
491             };
492             \endcode
493             where \p item is the item found, \p key is the <tt>find</tt> function argument.
494
495             The functor may change non-key fields of \p item. Note that the functor is only guarantee
496             that \p item cannot be disposed during functor is executing.
497             The functor does not serialize simultaneous access to the set's \p item. If such access is
498             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
499
500             Note the hash functor specified for class \p Traits template parameter
501             should accept a parameter of type \p Q that may be not the same as \p value_type.
502
503             The function returns \p true if \p key is found, \p false otherwise.
504         */
505         template <typename Q, typename Func>
506         bool find( Q& key, Func f )
507         {
508             return base_class::find( key, [&f]( node_type& node, Q& v ) { f( node.m_Value, v ); });
509         }
510         //@cond
511         template <typename Q, typename Func>
512         bool find( Q const& key, Func f )
513         {
514             return base_class::find( key, [&f]( node_type& node, Q& v ) { f( node.m_Value, v ); } );
515         }
516         //@endcond
517
518         /// Finds \p key using \p pred predicate for searching
519         /**
520             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_func "find(Q&, Func)"
521             but \p pred is used for key comparing.
522             \p Less functor has the interface like \p std::less.
523             \p Less must imply the same element order as the comparator used for building the set.
524         */
525         template <typename Q, typename Less, typename Func>
526         bool find_with( Q& key, Less pred, Func f )
527         {
528             CDS_UNUSED( pred );
529             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
530                 [&f]( node_type& node, Q& v ) { f( node.m_Value, v ); } );
531         }
532         //@cond
533         template <typename Q, typename Less, typename Func>
534         bool find_with( Q const& key, Less pred, Func f )
535         {
536             CDS_UNUSED( pred );
537             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
538                                           [&f]( node_type& node, Q& v ) { f( node.m_Value, v ); } );
539         }
540         //@endcond
541
542         /// Find \p key
543         /** \anchor cds_nonintrusive_SkipListSet_find_val
544
545             The function searches the item with key equal to \p key
546             and returns \p true if it is found, and \p false otherwise.
547
548             Note the hash functor specified for class \p Traits template parameter
549             should accept a parameter of type \p Q that may be not the same as \ref value_type.
550         */
551         template <typename Q>
552         bool find( Q const& key )
553         {
554             return base_class::find( key );
555         }
556
557         /// Finds \p key using \p pred predicate for searching
558         /**
559             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_val "find(Q const&)"
560             but \p pred is used for key comparing.
561             \p Less functor has the interface like \p std::less.
562             \p Less must imply the same element order as the comparator used for building the set.
563         */
564         template <typename Q, typename Less>
565         bool find_with( Q const& key, Less pred )
566         {
567             CDS_UNUSED( pred );
568             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >());
569         }
570
571         /// Finds \p key and return the item found
572         /** \anchor cds_nonintrusive_SkipListSet_hp_get
573             The function searches the item with key equal to \p key
574             and assigns the item found to guarded pointer \p result.
575             The function returns \p true if \p key is found, and \p false otherwise.
576             If \p key is not found the \p result parameter is left unchanged.
577
578             It is safe when a concurrent thread erases the item returned in \p result guarded pointer.
579             In this case the item will be freed later by garbage collector \p GC automatically
580             when \p guarded_ptr object will be destroyed or released.
581             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
582
583             Usage:
584             \code
585             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
586             skip_list theList;
587             // ...
588             {
589                 skip_list::guarded_ptr gp;
590                 if ( theList.get( gp, 5 ) ) {
591                     // Deal with gp
592                     //...
593                 }
594                 // Destructor of guarded_ptr releases internal HP guard
595             }
596             \endcode
597
598             Note the compare functor specified for class \p Traits template parameter
599             should accept a parameter of type \p Q that can be not the same as \p value_type.
600         */
601         template <typename Q>
602         bool get( guarded_ptr& result, Q const& key )
603         {
604             return base_class::get_with_( result.guard(), key, typename base_class::key_comparator() );
605         }
606
607         /// Finds \p key and return the item found
608         /**
609             The function is an analog of \ref cds_nonintrusive_SkipListSet_hp_get "get( guarded_ptr&, Q const&)"
610             but \p pred is used for comparing the keys.
611
612             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
613             in any order.
614             \p pred must imply the same element order as the comparator used for building the set.
615         */
616         template <typename Q, typename Less>
617         bool get_with( guarded_ptr& result, Q const& key, Less pred )
618         {
619             CDS_UNUSED( pred );
620             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >  wrapped_less;
621             return base_class::get_with_( result.guard(), key, cds::opt::details::make_comparator_from_less< wrapped_less >());
622         }
623
624         /// Clears the set (not atomic).
625         /**
626             The function deletes all items from the set.
627             The function is not atomic, thus, in multi-threaded environment with parallel insertions
628             this sequence
629             \code
630             set.clear();
631             assert( set.empty() );
632             \endcode
633             the assertion could be raised.
634
635             For each item the \ref disposer provided by \p Traits template parameter will be called.
636         */
637         void clear()
638         {
639             base_class::clear();
640         }
641
642         /// Checks if the set is empty
643         bool empty() const
644         {
645             return base_class::empty();
646         }
647
648         /// Returns item count in the set
649         /**
650             The value returned depends on item counter type provided by \p Traits template parameter.
651             If it is \p atomicity::empty_item_counter this function always returns 0.
652             Therefore, the function is not suitable for checking the set emptiness, use \p empty()
653             member function for this purpose.
654         */
655         size_t size() const
656         {
657             return base_class::size();
658         }
659
660         /// Returns const reference to internal statistics
661         stat const& statistics() const
662         {
663             return base_class::statistics();
664         }
665     };
666
667 }} // namespace cds::container
668
669 #endif // #ifndef __CDS_CONTAINER_IMPL_SKIP_LIST_SET_H