Remove CDS_CXX11_LAMBDA_SUPPORT macro and a lot of emulating code
[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     public:
165         /// Default ctor
166         SkipListSet()
167             : base_class()
168         {}
169
170         /// Destructor destroys the set object
171         ~SkipListSet()
172         {}
173
174     public:
175         /// Iterator type
176         typedef skip_list::details::iterator< typename base_class::iterator >  iterator;
177
178         /// Const iterator type
179         typedef skip_list::details::iterator< typename base_class::const_iterator >   const_iterator;
180
181         /// Returns a forward iterator addressing the first element in a set
182         iterator begin()
183         {
184             return iterator( base_class::begin() );
185         }
186
187         /// Returns a forward const iterator addressing the first element in a set
188         const_iterator begin() const
189         {
190             return const_iterator( base_class::begin() );
191         }
192
193         /// Returns a forward const iterator addressing the first element in a set
194         const_iterator cbegin()
195         {
196             return const_iterator( base_class::cbegin() );
197         }
198
199         /// Returns a forward iterator that addresses the location succeeding the last element in a set.
200         iterator end()
201         {
202             return iterator( base_class::end() );
203         }
204
205         /// Returns a forward const iterator that addresses the location succeeding the last element in a set.
206         const_iterator end() const
207         {
208             return const_iterator( base_class::end() );
209         }
210
211         /// Returns a forward const iterator that addresses the location succeeding the last element in a set.
212         const_iterator cend()
213         {
214             return const_iterator( base_class::cend() );
215         }
216
217     public:
218         /// Inserts new node
219         /**
220             The function creates a node with copy of \p val value
221             and then inserts the node created into the set.
222
223             The type \p Q should contain as minimum the complete key for the node.
224             The object of \ref value_type should be constructible from a value of type \p Q.
225             In trivial case, \p Q is equal to \ref value_type.
226
227             Returns \p true if \p val is inserted into the set, \p false otherwise.
228         */
229         template <typename Q>
230         bool insert( Q const& val )
231         {
232             scoped_node_ptr sp( node_allocator().New( random_level(), val ));
233             if ( base_class::insert( *sp.get() )) {
234                 sp.release();
235                 return true;
236             }
237             return false;
238         }
239
240         /// Inserts new node
241         /**
242             The function allows to split creating of new item into two part:
243             - create item with key only
244             - insert new item into the set
245             - if inserting is success, calls  \p f functor to initialize value-fields of \p val.
246
247             The functor signature is:
248             \code
249                 void func( value_type& val );
250             \endcode
251             where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
252             \p val no any other changes could be made on this set's item by concurrent threads.
253             The user-defined functor is called only if the inserting is success. It may be passed by reference
254             using <tt>boost::ref</tt>
255         */
256         template <typename Q, typename Func>
257         bool insert( Q const& val, Func f )
258         {
259             scoped_node_ptr sp( node_allocator().New( random_level(), val ));
260             if ( base_class::insert( *sp.get(), [&f]( node_type& val ) { cds::unref(f)( val.m_Value ); } )) {
261                 sp.release();
262                 return true;
263             }
264             return false;
265         }
266
267         /// Ensures that the item exists in the set
268         /**
269             The operation performs inserting or changing data with lock-free manner.
270
271             If the \p val key not found in the set, then the new item created from \p val
272             is inserted into the set. Otherwise, the functor \p func is called with the item found.
273             The functor \p Func should be a function with signature:
274             \code
275                 void func( bool bNew, value_type& item, const Q& val );
276             \endcode
277             or a functor:
278             \code
279                 struct my_functor {
280                     void operator()( bool bNew, value_type& item, const Q& val );
281                 };
282             \endcode
283
284             with arguments:
285             - \p bNew - \p true if the item has been inserted, \p false otherwise
286             - \p item - item of the set
287             - \p val - argument \p key passed into the \p ensure function
288
289             The functor may change non-key fields of the \p item; however, \p func must guarantee
290             that during changing no any other modifications could be made on this item by concurrent threads.
291
292             You may pass \p func argument by reference using <tt>boost::ref</tt>.
293
294             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
295             \p second is true if new item has been added or \p false if the item with \p key
296             already is in the set.
297         */
298         template <typename Q, typename Func>
299         std::pair<bool, bool> ensure( const Q& val, Func func )
300         {
301             scoped_node_ptr sp( node_allocator().New( random_level(), val ));
302             std::pair<bool, bool> bRes = base_class::ensure( *sp,
303                 [&func, &val](bool bNew, node_type& node, node_type&){ cds::unref(func)( bNew, node.m_Value, val ); });
304             if ( bRes.first && bRes.second )
305                 sp.release();
306             return bRes;
307         }
308
309         /// Inserts data of type \ref cds_containewr_SkipListSet_value_type "value_type" constructed with <tt>std::forward<Args>(args)...</tt>
310         /**
311             Returns \p true if inserting successful, \p false otherwise.
312         */
313         template <typename... Args>
314         bool emplace( Args&&... args )
315         {
316             scoped_node_ptr sp( node_allocator().New( random_level(), std::forward<Args>(args)... ));
317             if ( base_class::insert( *sp.get() )) {
318                 sp.release();
319                 return true;
320             }
321             return false;
322         }
323
324         /// Delete \p key from the set
325         /** \anchor cds_nonintrusive_SkipListSet_erase_val
326
327             The set item comparator should be able to compare the type \p value_type
328             and the type \p Q.
329
330             Return \p true if key is found and deleted, \p false otherwise
331         */
332         template <typename Q>
333         bool erase( Q const& key )
334         {
335             return base_class::erase( key );
336         }
337
338         /// Deletes the item from the set using \p pred predicate for searching
339         /**
340             The function is an analog of \ref cds_nonintrusive_SkipListSet_erase_val "erase(Q const&)"
341             but \p pred is used for key comparing.
342             \p Less functor has the interface like \p std::less.
343             \p Less must imply the same element order as the comparator used for building the set.
344         */
345         template <typename Q, typename Less>
346         bool erase_with( Q const& key, Less pred )
347         {
348             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >() );
349         }
350
351         /// Delete \p key from the set
352         /** \anchor cds_nonintrusive_SkipListSet_erase_func
353
354             The function searches an item with key \p key, calls \p f functor
355             and deletes the item. If \p key is not found, the functor is not called.
356
357             The functor \p Func interface:
358             \code
359             struct extractor {
360                 void operator()(value_type const& val);
361             };
362             \endcode
363             The functor may be passed by reference using <tt>boost:ref</tt>
364
365             Since the key of \p value_type is not explicitly specified,
366             template parameter \p Q defines the key type to search in the list.
367             The list item comparator should be able to compare the type \p T of list item
368             and the type \p Q.
369
370             Return \p true if key is found and deleted, \p false otherwise
371
372             See also: \ref erase
373         */
374         template <typename Q, typename Func>
375         bool erase( Q const& key, Func f )
376         {
377             return base_class::erase( key, [&f]( node_type const& node) { cds::unref(f)( node.m_Value ); } );
378         }
379
380         /// Deletes the item from the set using \p pred predicate for searching
381         /**
382             The function is an analog of \ref cds_nonintrusive_SkipListSet_erase_func "erase(Q const&, Func)"
383             but \p pred is used for key comparing.
384             \p Less functor has the interface like \p std::less.
385             \p Less must imply the same element order as the comparator used for building the set.
386         */
387         template <typename Q, typename Less, typename Func>
388         bool erase_with( Q const& key, Less pred, Func f )
389         {
390             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
391                 [&f]( node_type const& node) { cds::unref(f)( node.m_Value ); } );
392         }
393
394         /// Extracts the item from the set with specified \p key
395         /** \anchor cds_nonintrusive_SkipListSet_hp_extract
396             The function searches an item with key equal to \p key in the set,
397             unlinks it from the set, and returns it in \p result parameter.
398             If the item with key equal to \p key is not found the function returns \p false.
399
400             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
401
402             The item extracted is freed automatically by garbage collector \p GC
403             when returned \ref guarded_ptr object will be destroyed or released.
404             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
405
406             Usage:
407             \code
408             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
409             skip_list theList;
410             // ...
411             {
412                 skip_list::guarded_ptr gp;
413                 if ( theList.extract( gp, 5 ) ) {
414                     // Deal with gp
415                     // ...
416                 }
417                 // Destructor of gp releases internal HP guard and frees the pointer
418             }
419             \endcode
420         */
421         template <typename Q>
422         bool extract( guarded_ptr& result, Q const& key )
423         {
424             return base_class::extract_( result.guard(), key, typename base_class::key_comparator() );
425         }
426
427         /// Extracts the item from the set with comparing functor \p pred
428         /**
429             The function is an analog of \ref cds_nonintrusive_SkipListSet_hp_extract "extract(Q const&)"
430             but \p pred predicate is used for key comparing.
431
432             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
433             in any order.
434             \p pred must imply the same element order as the comparator used for building the set.
435         */
436         template <typename Q, typename Less>
437         bool extract_with( guarded_ptr& ptr, Q const& key, Less pred )
438         {
439             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >  wrapped_less;
440             return base_class::extract_( ptr.guard(), key, cds::opt::details::make_comparator_from_less<wrapped_less>() );
441         }
442
443         /// Extracts an item with minimal key from the set
444         /**
445             The function searches an item with minimal key, unlinks it, and returns the item found in \p result parameter.
446             If the skip-list is empty the function returns \p false.
447
448             The item extracted is freed automatically by garbage collector \p GC
449             when returned \ref guarded_ptr object will be destroyed or released.
450             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
451
452             Usage:
453             \code
454             typedef cds::continer::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
455             skip_list theList;
456             // ...
457             {
458                 skip_list::guarded_ptr gp;
459                 if ( theList.extract_min( gp )) {
460                     // Deal with gp
461                     //...
462                 }
463                 // Destructor of gp releases internal HP guard and then frees the pointer
464             }
465             \endcode
466         */
467         bool extract_min( guarded_ptr& result)
468         {
469             return base_class::extract_min_( result.guard() );
470         }
471
472         /// Extracts an item with maximal key from the set
473         /**
474             The function searches an item with maximal key, unlinks it, and returns the pointer to item found in \p result parameter.
475             If the skip-list is empty the function returns \p false.
476
477             The item found is freed by garbage collector \p GC automatically
478             when returned \ref guarded_ptr object will be destroyed or released.
479             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
480
481             Usage:
482             \code
483             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
484             skip_list theList;
485             // ...
486             {
487                 skip_list::guarded_ptr gp;
488                 if ( theList.extract_max( gp )) {
489                     // Deal with gp
490                     //...
491                 }
492                 // Destructor of gp releases internal HP guard and then frees the pointer
493             }
494             \endcode
495         */
496         bool extract_max( guarded_ptr& result )
497         {
498             return base_class::extract_max_( result.guard() );
499         }
500
501         /// Find the key \p val
502         /** \anchor cds_nonintrusive_SkipListSet_find_func
503
504             The function searches the item with key equal to \p val and calls the functor \p f for item found.
505             The interface of \p Func functor is:
506             \code
507             struct functor {
508                 void operator()( value_type& item, Q& val );
509             };
510             \endcode
511             where \p item is the item found, \p val is the <tt>find</tt> function argument.
512
513             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
514
515             The functor may change non-key fields of \p item. Note that the functor is only guarantee
516             that \p item cannot be disposed during functor is executing.
517             The functor does not serialize simultaneous access to the set's \p item. If such access is
518             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
519
520             The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor
521             can modify both arguments.
522
523             Note the hash functor specified for class \p Traits template parameter
524             should accept a parameter of type \p Q that may be not the same as \p value_type.
525
526             The function returns \p true if \p val is found, \p false otherwise.
527         */
528         template <typename Q, typename Func>
529         bool find( Q& val, Func f )
530         {
531             return base_class::find( val, [&f]( node_type& node, Q& v ) { cds::unref(f)( node.m_Value, v ); });
532         }
533
534         /// Finds the key \p val using \p pred predicate for searching
535         /**
536             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_func "find(Q&, Func)"
537             but \p pred is used for key comparing.
538             \p Less functor has the interface like \p std::less.
539             \p Less must imply the same element order as the comparator used for building the set.
540         */
541         template <typename Q, typename Less, typename Func>
542         bool find_with( Q& val, Less pred, Func f )
543         {
544             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
545                 [&f]( node_type& node, Q& v ) { cds::unref(f)( node.m_Value, v ); } );
546         }
547
548         /// Find the key \p val
549         /** \anchor cds_nonintrusive_SkipListSet_find_cfunc
550
551             The function searches the item with key equal to \p val and calls the functor \p f for item found.
552             The interface of \p Func functor is:
553             \code
554             struct functor {
555                 void operator()( value_type& item, Q const& val );
556             };
557             \endcode
558             where \p item is the item found, \p val is the <tt>find</tt> function argument.
559
560             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
561
562             The functor may change non-key fields of \p item. Note that the functor is only guarantee
563             that \p item cannot be disposed during functor is executing.
564             The functor does not serialize simultaneous access to the set's \p item. If such access is
565             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
566
567             Note the hash functor specified for class \p Traits template parameter
568             should accept a parameter of type \p Q that may be not the same as \p value_type.
569
570             The function returns \p true if \p val is found, \p false otherwise.
571         */
572         template <typename Q, typename Func>
573         bool find( Q const& val, Func f )
574         {
575             return base_class::find( val, [&f]( node_type& node, Q const& v ) { cds::unref(f)( node.m_Value, v ); });
576         }
577
578         /// Finds the key \p val using \p pred predicate for searching
579         /**
580             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_cfunc "find(Q const&, Func)"
581             but \p pred is used for key comparing.
582             \p Less functor has the interface like \p std::less.
583             \p Less must imply the same element order as the comparator used for building the set.
584         */
585         template <typename Q, typename Less, typename Func>
586         bool find_with( Q const& val, Less cmp, Func f )
587         {
588             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
589                 [&f]( node_type& node, Q const& v ) { cds::unref(f)( node.m_Value, v ); } );
590         }
591
592         /// Find the key \p val
593         /** \anchor cds_nonintrusive_SkipListSet_find_val
594
595             The function searches the item with key equal to \p val
596             and returns \p true if it is found, and \p false otherwise.
597
598             Note the hash functor specified for class \p Traits template parameter
599             should accept a parameter of type \p Q that may be not the same as \ref value_type.
600         */
601         template <typename Q>
602         bool find( Q const& val )
603         {
604             return base_class::find( val );
605         }
606
607         /// Finds the key \p val using \p pred predicate for searching
608         /**
609             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_val "find(Q const&)"
610             but \p pred is used for key comparing.
611             \p Less functor has the interface like \p std::less.
612             \p Less must imply the same element order as the comparator used for building the set.
613         */
614         template <typename Q, typename Less>
615         bool find_with( Q const& val, Less pred )
616         {
617             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >());
618         }
619
620         /// Finds \p key and return the item found
621         /** \anchor cds_nonintrusive_SkipListSet_hp_get
622             The function searches the item with key equal to \p key
623             and assigns the item found to guarded pointer \p result.
624             The function returns \p true if \p key is found, and \p false otherwise.
625             If \p key is not found the \p result parameter is left unchanged.
626
627             It is safe when a concurrent thread erases the item returned in \p result guarded pointer.
628             In this case the item will be freed later by garbage collector \p GC automatically
629             when \p guarded_ptr object will be destroyed or released.
630             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
631
632             Usage:
633             \code
634             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
635             skip_list theList;
636             // ...
637             {
638                 skip_list::guarded_ptr gp;
639                 if ( theList.get( gp, 5 ) ) {
640                     // Deal with gp
641                     //...
642                 }
643                 // Destructor of guarded_ptr releases internal HP guard
644             }
645             \endcode
646
647             Note the compare functor specified for class \p Traits template parameter
648             should accept a parameter of type \p Q that can be not the same as \p value_type.
649         */
650         template <typename Q>
651         bool get( guarded_ptr& result, Q const& key )
652         {
653             return base_class::get_with_( result.guard(), key, typename base_class::key_comparator() );
654         }
655
656         /// Finds \p key and return the item found
657         /**
658             The function is an analog of \ref cds_nonintrusive_SkipListSet_hp_get "get( guarded_ptr&, Q const&)"
659             but \p pred is used for comparing the keys.
660
661             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
662             in any order.
663             \p pred must imply the same element order as the comparator used for building the set.
664         */
665         template <typename Q, typename Less>
666         bool get_with( guarded_ptr& result, Q const& key, Less pred )
667         {
668             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >  wrapped_less;
669             return base_class::get_with_( result.guard(), key, cds::opt::details::make_comparator_from_less< wrapped_less >());
670         }
671
672         /// Clears the set (non-atomic).
673         /**
674             The function deletes all items from the set.
675             The function is not atomic, thus, in multi-threaded environment with parallel insertions
676             this sequence
677             \code
678             set.clear();
679             assert( set.empty() );
680             \endcode
681             the assertion could be raised.
682
683             For each item the \ref disposer provided by \p Traits template parameter will be called.
684         */
685         void clear()
686         {
687             base_class::clear();
688         }
689
690         /// Checks if the set is empty
691         bool empty() const
692         {
693             return base_class::empty();
694         }
695
696         /// Returns item count in the set
697         /**
698             The value returned depends on item counter type provided by \p Traits template parameter.
699             If it is atomicity::empty_item_counter this function always returns 0.
700             Therefore, the function is not suitable for checking the set emptiness, use \ref empty
701             member function for this purpose.
702         */
703         size_t size() const
704         {
705             return base_class::size();
706         }
707
708         /// Returns const reference to internal statistics
709         stat const& statistics() const
710         {
711             return base_class::statistics();
712         }
713
714     };
715
716 }} // namespace cds::container
717
718 #endif // #ifndef __CDS_CONTAINER_SKIP_LIST_SET_IMPL_H