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