EllenBinTreeSet refactoring
[libcds.git] / cds / container / impl / ellen_bintree_set.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_IMPL_ELLEN_BINTREE_SET_H
4 #define __CDS_CONTAINER_IMPL_ELLEN_BINTREE_SET_H
5
6 #include <traits>
7 #include <cds/container/details/ellen_bintree_base.h>
8 #include <cds/intrusive/impl/ellen_bintree.h>
9 #include <cds/container/details/guarded_ptr_cast.h>
10
11 namespace cds { namespace container {
12
13     /// Set based on Ellen's et al binary search tree
14     /** @ingroup cds_nonintrusive_set
15         @ingroup cds_nonintrusive_tree
16         @anchor cds_container_EllenBinTreeSet
17
18         Source:
19             - [2010] F.Ellen, P.Fatourou, E.Ruppert, F.van Breugel "Non-blocking Binary Search Tree"
20
21         %EllenBinTreeSet is an unbalanced leaf-oriented binary search tree that implements the <i>set</i>
22         abstract data type. Nodes maintains child pointers but not parent pointers.
23         Every internal node has exactly two children, and all data of type \p T currently in
24         the tree are stored in the leaves. Internal nodes of the tree are used to direct \p find
25         operation along the path to the correct leaf. The keys (of \p Key type) stored in internal nodes
26         may or may not be in the set. \p Key type is a subset of \p T type.
27         There should be exactly defined a key extracting functor for converting object of type \p T to
28         object of type \p Key.
29
30         Due to \p extract_min and \p extract_max member functions the \p %EllenBinTreeSet can act as
31         a <i>priority queue</i>. In this case you should provide unique compound key, for example,
32         the priority value plus some uniformly distributed random value.
33
34         @warning Recall the tree is <b>unbalanced</b>. The complexity of operations is <tt>O(log N)</tt>
35         for uniformly distributed random keys, but in worst case the complexity is <tt>O(N)</tt>.
36
37         @note In the current implementation we do not use helping technique described in original paper.
38         So, the current implementation is near to fine-grained lock-based tree.
39         Helping will be implemented in future release
40
41         <b>Template arguments</b> :
42         - \p GC - safe memory reclamation (i.e. light-weight garbage collector) type, like \p cds::gc::HP, cds::gc::DHP
43         - \p Key - key type, a subset of \p T
44         - \p T - type to be stored in tree's leaf nodes.
45         - \p Traits - set traits, default is \p ellen_bintree::traits
46             It is possible to declare option-based tree with \p ellen_bintree::make_set_traits metafunction
47             instead of \p Traits template argument.
48
49         @note Do not include <tt><cds/container/impl/ellen_bintree_set.h></tt> header file directly.
50         There are header file for each GC type:
51         - <tt><cds/container/ellen_bintree_set_hp.h></tt> - for \p cds::gc::HP
52         - <tt><cds/container/ellen_bintree_set_ptb.h></tt> - for \p cds::gc::DHP
53         - <tt><cds/container/ellen_bintree_set_rcu.h></tt> - for RCU GC
54             (see \ref cds_container_EllenBinTreeSet_rcu "RCU-based EllenBinTreeSet")
55
56         @anchor cds_container_EllenBinTreeSet_less
57         <b>Predicate requirements</b>
58
59         \p Traits::less, \p Traits::compare and other predicates using with member fuctions should accept at least parameters
60         of type \p T and \p Key in any combination.
61         For example, for \p Foo struct with \p std::string key field the appropiate \p less functor is:
62         \code
63         struct Foo
64         {
65             std::string m_strKey;
66             ...
67         };
68
69         struct less {
70             bool operator()( Foo const& v1, Foo const& v2 ) const
71             { return v1.m_strKey < v2.m_strKey ; }
72
73             bool operator()( Foo const& v, std::string const& s ) const
74             { return v.m_strKey < s ; }
75
76             bool operator()( std::string const& s, Foo const& v ) const
77             { return s < v.m_strKey ; }
78
79             // Support comparing std::string and char const *
80             bool operator()( std::string const& s, char const * p ) const
81             { return s.compare(p) < 0 ; }
82
83             bool operator()( Foo const& v, char const * p ) const
84             { return v.m_strKey.compare(p) < 0 ; }
85
86             bool operator()( char const * p, std::string const& s ) const
87             { return s.compare(p) > 0; }
88
89             bool operator()( char const * p, Foo const& v ) const
90             { return v.m_strKey.compare(p) > 0; }
91         };
92         \endcode
93     */
94     template <
95         class GC,
96         typename Key,
97         typename T,
98 #ifdef CDS_DOXYGEN_INVOKED
99         class Traits = ellen_bintree::traits
100 #else
101         class Traits
102 #endif
103     >
104     class EllenBinTreeSet
105 #ifdef CDS_DOXYGEN_INVOKED
106         : public cds::intrusive::EllenBinTree< GC, Key, T, Traits >
107 #else
108         : public ellen_bintree::details::make_ellen_bintree_set< GC, Key, T, Traits >::type
109 #endif
110     {
111         //@cond
112         typedef ellen_bintree::details::make_ellen_bintree_set< GC, Key, T, Traits > maker;
113         typedef typename maker::type base_class;
114         //@endcond
115
116     public:
117         typedef GC      gc;         ///< Garbage collector
118         typedef Key     key_type;   ///< type of a key to be stored in internal nodes; key is a part of \p value_type
119         typedef T       value_type; ///< type of value to be stored in the binary tree
120         typedef Traits  traits;    ///< Traits template parameter
121
122 #   ifdef CDS_DOXYGEN_INVOKED
123         typedef implementation_defined key_comparator  ;    ///< key compare functor based on opt::compare and opt::less option setter.
124 #   else
125         typedef typename maker::intrusive_type_traits::compare   key_comparator;
126 #   endif
127         typedef typename base_class::item_counter           item_counter;  ///< Item counting policy used
128         typedef typename base_class::memory_model           memory_model;  ///< Memory ordering. See cds::opt::memory_model option
129         typedef typename base_class::stat                   stat;          ///< internal statistics type
130         typedef typename traits::key_extractor              key_extractor; ///< key extracting functor
131
132         typedef typename traits::allocator                  allocator_type;   ///< Allocator for leaf nodes
133         typedef typename base_class::node_allocator         node_allocator;   ///< Internal node allocator
134         typedef typename base_class::update_desc_allocator  update_desc_allocator; ///< Update descriptor allocator
135
136     protected:
137         //@cond
138         typedef typename maker::cxx_leaf_node_allocator cxx_leaf_node_allocator;
139         typedef typename base_class::value_type         leaf_node;
140         typedef typename base_class::internal_node      internal_node;
141
142         typedef std::unique_ptr< leaf_node, typename maker::leaf_deallocator > scoped_node_ptr;
143         //@endcond
144
145     public:
146         /// Guarded pointer
147         typedef cds::gc::guarded_ptr< gc, leaf_node, value_type, details::guarded_ptr_cast_set<leaf_node, value_type> > guarded_ptr;
148
149     public:
150         /// Default constructor
151         EllenBinTreeSet()
152             : base_class()
153         {}
154
155         /// Clears the set
156         ~EllenBinTreeSet()
157         {}
158
159         /// Inserts new node
160         /**
161             The function creates a node with copy of \p val value
162             and then inserts the node created into the set.
163
164             The type \p Q should contain at least the complete key for the node.
165             The object of \ref value_type should be constructible from a value of type \p Q.
166             In trivial case, \p Q is equal to \ref value_type.
167
168             Returns \p true if \p val is inserted into the set, \p false otherwise.
169         */
170         template <typename Q>
171         bool insert( Q const& val )
172         {
173             scoped_node_ptr sp( cxx_leaf_node_allocator().New( val ));
174             if ( base_class::insert( *sp.get() )) {
175                 sp.release();
176                 return true;
177             }
178             return false;
179         }
180
181         /// Inserts new node
182         /**
183             The function allows to split creating of new item into two part:
184             - create item with key only
185             - insert new item into the set
186             - if inserting is success, calls  \p f functor to initialize value-fields of \p val.
187
188             The functor signature is:
189             \code
190                 void func( value_type& val );
191             \endcode
192             where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
193             \p val no any other changes could be made on this set's item by concurrent threads.
194             The user-defined functor is called only if the inserting is success.
195         */
196         template <typename Q, typename Func>
197         bool insert( Q const& val, Func f )
198         {
199             scoped_node_ptr sp( cxx_leaf_node_allocator().New( val ));
200             if ( base_class::insert( *sp.get(), [&f]( leaf_node& val ) { f( val.m_Value ); } )) {
201                 sp.release();
202                 return true;
203             }
204             return false;
205         }
206
207         /// Ensures that the item exists in the set
208         /**
209             The operation performs inserting or changing data with lock-free manner.
210
211             If the \p val key not found in the set, then the new item created from \p val
212             is inserted into the set. Otherwise, the functor \p func is called with the item found.
213             The functor \p Func should be a function with signature:
214             \code
215                 void func( bool bNew, value_type& item, const Q& val );
216             \endcode
217             or a functor:
218             \code
219                 struct my_functor {
220                     void operator()( bool bNew, value_type& item, const Q& val );
221                 };
222             \endcode
223
224             with arguments:
225             - \p bNew - \p true if the item has been inserted, \p false otherwise
226             - \p item - item of the set
227             - \p val - argument \p key passed into the \p ensure function
228
229             The functor may change non-key fields of the \p item; however, \p func must guarantee
230             that during changing no any other modifications could be made on this item by concurrent threads.
231
232             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
233             \p second is true if new item has been added or \p false if the item with \p key
234             already is in the set.
235
236             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
237         */
238         template <typename Q, typename Func>
239         std::pair<bool, bool> ensure( const Q& val, Func func )
240         {
241             scoped_node_ptr sp( cxx_leaf_node_allocator().New( val ));
242             std::pair<bool, bool> bRes = base_class::ensure( *sp,
243                 [&func, &val](bool bNew, leaf_node& node, leaf_node&){ func( bNew, node.m_Value, val ); });
244             if ( bRes.first && bRes.second )
245                 sp.release();
246             return bRes;
247         }
248
249         /// Inserts data of type \p value_type created in-place from \p args
250         /**
251             Returns \p true if inserting successful, \p false otherwise.
252         */
253         template <typename... Args>
254         bool emplace( Args&&... args )
255         {
256             scoped_node_ptr sp( cxx_leaf_node_allocator().New( std::forward<Args>(args)... ));
257             if ( base_class::insert( *sp.get() )) {
258                 sp.release();
259                 return true;
260             }
261             return false;
262         }
263
264         /// Delete \p key from the set
265         /** \anchor cds_nonintrusive_EllenBinTreeSet_erase_val
266
267             The item comparator should be able to compare the type \p value_type
268             and the type \p Q.
269
270             Return \p true if key is found and deleted, \p false otherwise
271         */
272         template <typename Q>
273         bool erase( Q const& key )
274         {
275             return base_class::erase( key );
276         }
277
278         /// Deletes the item from the set using \p pred predicate for searching
279         /**
280             The function is an analog of \ref cds_nonintrusive_EllenBinTreeSet_erase_val "erase(Q const&)"
281             but \p pred is used for key comparing.
282             \p Less functor has the interface like \p std::less.
283             \p Less must imply the same element order as the comparator used for building the set.
284         */
285         template <typename Q, typename Less>
286         bool erase_with( Q const& key, Less pred )
287         {
288             return base_class::erase_with( key, cds::details::predicate_wrapper< leaf_node, Less, typename maker::value_accessor >());
289         }
290
291         /// Delete \p key from the set
292         /** \anchor cds_nonintrusive_EllenBinTreeSet_erase_func
293
294             The function searches an item with key \p key, calls \p f functor
295             and deletes the item. If \p key is not found, the functor is not called.
296
297             The functor \p Func interface:
298             \code
299             struct extractor {
300                 void operator()(value_type const& val);
301             };
302             \endcode
303
304             Since the key of MichaelHashSet's \p value_type is not explicitly specified,
305             template parameter \p Q defines the key type searching in the list.
306             The list item comparator should be able to compare the type \p T of list item
307             and the type \p Q.
308
309             Return \p true if key is found and deleted, \p false otherwise
310         */
311         template <typename Q, typename Func>
312         bool erase( Q const& key, Func f )
313         {
314             return base_class::erase( key, [&f]( leaf_node const& node) { f( node.m_Value ); } );
315         }
316
317         /// Deletes the item from the set using \p pred predicate for searching
318         /**
319             The function is an analog of \ref cds_nonintrusive_EllenBinTreeSet_erase_func "erase(Q const&, Func)"
320             but \p pred is used for key comparing.
321             \p Less functor has the interface like \p std::less.
322             \p Less must imply the same element order as the comparator used for building the set.
323         */
324         template <typename Q, typename Less, typename Func>
325         bool erase_with( Q const& key, Less pred, Func f )
326         {
327             return base_class::erase_with( key, cds::details::predicate_wrapper< leaf_node, Less, typename maker::value_accessor >(),
328                 [&f]( leaf_node const& node) { f( node.m_Value ); } );
329         }
330
331         /// Extracts an item with minimal key from the set
332         /**
333             If the set is not empty, the function returns \p true, \p result contains a pointer to minimum value.
334             If the set is empty, the function returns \p false, \p result is left unchanged.
335
336             @note Due the concurrent nature of the set, the function extracts <i>nearly</i> minimum key.
337             It means that the function gets leftmost leaf of the tree and tries to unlink it.
338             During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
339             So, the function returns the item with minimum key at the moment of tree traversing.
340
341             The guarded pointer \p dest prevents deallocation of returned item,
342             see cds::gc::guarded_ptr for explanation.
343             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
344         */
345         bool extract_min( guarded_ptr& result )
346         {
347             return base_class::extract_min_( result.guard() );
348         }
349
350         /// Extracts an item with maximal key from the set
351         /**
352             If the set is not empty, the function returns \p true, \p result contains a pointer to maximal value.
353             If the set is empty, the function returns \p false, \p result is left unchanged.
354
355             @note Due the concurrent nature of the set, the function extracts <i>nearly</i> maximal key.
356             It means that the function gets rightmost leaf of the tree and tries to unlink it.
357             During unlinking, a concurrent thread may insert an item with key great than leftmost item's key.
358             So, the function returns the item with maximum key at the moment of tree traversing.
359
360             The guarded pointer \p dest prevents deallocation of returned item,
361             see cds::gc::guarded_ptr for explanation.
362             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
363         */
364         bool extract_max( guarded_ptr& result )
365         {
366             return base_class::extract_max_( result.guard() );
367         }
368
369         /// Extracts an item from the tree
370         /** \anchor cds_nonintrusive_EllenBinTreeSet_extract
371             The function searches an item with key equal to \p key in the tree,
372             unlinks it, and returns pointer to an item found in \p result parameter.
373             If the item  is not found the function returns \p false.
374
375             The guarded pointer \p dest prevents deallocation of returned item,
376             see cds::gc::guarded_ptr for explanation.
377             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
378         */
379         template <typename Q>
380         bool extract( guarded_ptr& result, Q const& key )
381         {
382             return base_class::extract_( result.guard(), key );
383         }
384
385         /// Extracts an item from the set using \p pred for searching
386         /**
387             The function is an analog of \ref cds_nonintrusive_EllenBinTreeSet_extract "extract(guarded_ptr& dest, Q const&)"
388             but \p pred is used for key compare.
389             \p Less has the interface like \p std::less.
390             \p pred must imply the same element order as the comparator used for building the set.
391         */
392         template <typename Q, typename Less>
393         bool extract_with( guarded_ptr& result, Q const& key, Less pred )
394         {
395             return base_class::extract_with_( result.guard(), key,
396                 cds::details::predicate_wrapper< leaf_node, Less, typename maker::value_accessor >());
397         }
398
399         /// Find the key \p key
400         /**
401             @anchor cds_nonintrusive_EllenBinTreeSet_find_func
402
403             The function searches the item with key equal to \p key and calls the functor \p f for item found.
404             The interface of \p Func functor is:
405             \code
406             struct functor {
407                 void operator()( value_type& item, Q& key );
408             };
409             \endcode
410             where \p item is the item found, \p key is the <tt>find</tt> function argument.
411
412             You may pass \p f argument by reference using \p std::ref.
413
414             The functor may change non-key fields of \p item. Note that the functor is only guarantee
415             that \p item cannot be disposed during functor is executing.
416             The functor does not serialize simultaneous access to the set's \p item. If such access is
417             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
418
419             The \p key argument is non-const since it can be used as \p f functor destination i.e., the functor
420             can modify both arguments.
421
422             Note the hash functor specified for class \p Traits template parameter
423             should accept a parameter of type \p Q that may be not the same as \p value_type.
424
425             The function returns \p true if \p key is found, \p false otherwise.
426         */
427         template <typename Q, typename Func>
428         bool find( Q& key, Func f )
429         {
430             return base_class::find( key, [&f]( leaf_node& node, Q& v ) { f( node.m_Value, v ); });
431         }
432         //@cond
433         template <typename Q, typename Func>
434         bool find( Q const& key, Func f )
435         {
436             return base_class::find( key, [&f]( leaf_node& node, Q const& v ) { f( node.m_Value, v ); } );
437         }
438         //@endcond
439
440         /// Finds the key \p key using \p pred predicate for searching
441         /**
442             The function is an analog of \ref cds_nonintrusive_EllenBinTreeSet_find_func "find(Q&, Func)"
443             but \p pred is used for key comparing.
444             \p Less functor has the interface like \p std::less.
445             \p Less must imply the same element order as the comparator used for building the set.
446         */
447         template <typename Q, typename Less, typename Func>
448         bool find_with( Q& key, Less pred, Func f )
449         {
450             return base_class::find_with( key, cds::details::predicate_wrapper< leaf_node, Less, typename maker::value_accessor >(),
451                 [&f]( leaf_node& node, Q& v ) { f( node.m_Value, v ); } );
452         }
453         //@cond
454         template <typename Q, typename Less, typename Func>
455         bool find_with( Q const& key, Less pred, Func f )
456         {
457             return base_class::find_with( key, cds::details::predicate_wrapper< leaf_node, Less, typename maker::value_accessor >(),
458                                           [&f]( leaf_node& node, Q const& v ) { f( node.m_Value, v ); } );
459         }
460         //@endcond
461
462         /// Find the key \p key
463         /** @anchor cds_nonintrusive_EllenBinTreeSet_find_val
464
465             The function searches the item with key equal to \p key
466             and returns \p true if it is found, and \p false otherwise.
467
468             Note the hash functor specified for class \p Traits template parameter
469             should accept a parameter of type \p Q that may be not the same as \ref value_type.
470         */
471         template <typename Q>
472         bool find( Q const & key )
473         {
474             return base_class::find( key );
475         }
476
477         /// Finds the key \p key using \p pred predicate for searching
478         /**
479             The function is an analog of \ref cds_nonintrusive_EllenBinTreeSet_find_val "find(Q const&)"
480             but \p pred is used for key comparing.
481             \p Less functor has the interface like \p std::less.
482             \p Less must imply the same element order as the comparator used for building the set.
483         */
484         template <typename Q, typename Less>
485         bool find_with( Q const& key, Less pred )
486         {
487             return base_class::find_with( key, cds::details::predicate_wrapper< leaf_node, Less, typename maker::value_accessor >());
488         }
489
490         /// Finds \p key and returns the item found
491         /** @anchor cds_nonintrusive_EllenBinTreeSet_get
492             The function searches the item with key equal to \p key and returns the item found in \p result parameter.
493             The function returns \p true if \p key is found, \p false otherwise.
494
495             The guarded pointer \p dest prevents deallocation of returned item,
496             see cds::gc::guarded_ptr for explanation.
497             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
498         */
499         template <typename Q>
500         bool get( guarded_ptr& result, Q const& key )
501         {
502             return base_class::get_( result.guard(), key );
503         }
504
505         /// Finds \p key with predicate \p pred and returns the item found
506         /**
507             The function is an analog of \ref cds_nonintrusive_EllenBinTreeSet_get "get(guarded_ptr&, Q const&)"
508             but \p pred is used for key comparing.
509             \p Less functor has the interface like \p std::less.
510             \p pred must imply the same element order as the comparator used for building the set.
511         */
512         template <typename Q, typename Less>
513         bool get_with( guarded_ptr& result, Q const& key, Less pred )
514         {
515             return base_class::get_with_( result.guard(), key,
516                 cds::details::predicate_wrapper< leaf_node, Less, typename maker::value_accessor >() );
517         }
518
519         /// Clears the set (not atomic)
520         /**
521             The function unlink all items from the tree.
522             The function is not atomic, thus, in multi-threaded environment with parallel insertions
523             this sequence
524             \code
525             set.clear();
526             assert( set.empty() );
527             \endcode
528             the assertion could be raised.
529
530             For each leaf the \ref disposer will be called after unlinking.
531         */
532         void clear()
533         {
534             base_class::clear();
535         }
536
537         /// Checks if the set is empty
538         bool empty() const
539         {
540             return base_class::empty();
541         }
542
543         /// Returns item count in the set
544         /**
545             Only leaf nodes containing user data are counted.
546
547             The value returned depends on item counter type provided by \p Traits template parameter.
548             If it is \p atomicity::empty_item_counter this function always returns 0.
549
550             The function is not suitable for checking the tree emptiness, use \p empty()
551             member function for this purpose.
552         */
553         size_t size() const
554         {
555             return base_class::size();
556         }
557
558         /// Returns const reference to internal statistics
559         stat const& statistics() const
560         {
561             return base_class::statistics();
562         }
563
564         /// Checks internal consistency (not atomic, not thread-safe)
565         /**
566             The debugging function to check internal consistency of the tree.
567         */
568         bool check_consistency() const
569         {
570             return base_class::check_consistency();
571         }
572     };
573
574 }} // namespace cds::container
575
576 #endif // #ifndef __CDS_CONTAINER_IMPL_ELLEN_BINTREE_SET_H