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