Move libcds 1.6.0 from SVN
[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 NULL 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 #   ifdef CDS_EMPLACE_SUPPORT
398         /// Inserts data of type \ref cds_containewr_SkipListSet_value_type "value_type" constructed with <tt>std::forward<Args>(args)...</tt>
399         /**
400             Returns \p true if inserting successful, \p false otherwise.
401
402             @note This function is available only for compiler that supports
403             variadic template and move semantics
404         */
405         template <typename... Args>
406         bool emplace( Args&&... args )
407         {
408             scoped_node_ptr sp( node_allocator().New( random_level(), std::forward<Args>(args)... ));
409             if ( base_class::insert( *sp.get() )) {
410                 sp.release();
411                 return true;
412             }
413             return false;
414         }
415 #   endif
416
417         /// Delete \p key from the set
418         /** \anchor cds_nonintrusive_SkipListSet_erase_val
419
420             The set item comparator should be able to compare the type \p value_type
421             and the type \p Q.
422
423             Return \p true if key is found and deleted, \p false otherwise
424         */
425         template <typename Q>
426         bool erase( Q const& key )
427         {
428             return base_class::erase( key );
429         }
430
431         /// Deletes the item from the set using \p pred predicate for searching
432         /**
433             The function is an analog of \ref cds_nonintrusive_SkipListSet_erase_val "erase(Q const&)"
434             but \p pred is used for key comparing.
435             \p Less functor has the interface like \p std::less.
436             \p Less must imply the same element order as the comparator used for building the set.
437         */
438         template <typename Q, typename Less>
439         bool erase_with( Q const& key, Less pred )
440         {
441             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >() );
442         }
443
444         /// Delete \p key from the set
445         /** \anchor cds_nonintrusive_SkipListSet_erase_func
446
447             The function searches an item with key \p key, calls \p f functor
448             and deletes the item. If \p key is not found, the functor is not called.
449
450             The functor \p Func interface:
451             \code
452             struct extractor {
453                 void operator()(value_type const& val);
454             };
455             \endcode
456             The functor may be passed by reference using <tt>boost:ref</tt>
457
458             Since the key of \p value_type is not explicitly specified,
459             template parameter \p Q defines the key type to search in the list.
460             The list item comparator should be able to compare the type \p T of list item
461             and the type \p Q.
462
463             Return \p true if key is found and deleted, \p false otherwise
464
465             See also: \ref erase
466         */
467         template <typename Q, typename Func>
468         bool erase( Q const& key, Func f )
469         {
470 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
471             return base_class::erase( key, [&f]( node_type const& node) { cds::unref(f)( node.m_Value ); } );
472 #       else
473             erase_functor<Func> wrapper(f);
474             return base_class::erase( key, cds::ref(wrapper));
475 #       endif
476         }
477
478         /// Deletes the item from the set using \p pred predicate for searching
479         /**
480             The function is an analog of \ref cds_nonintrusive_SkipListSet_erase_func "erase(Q const&, Func)"
481             but \p pred is used for key comparing.
482             \p Less functor has the interface like \p std::less.
483             \p Less must imply the same element order as the comparator used for building the set.
484         */
485         template <typename Q, typename Less, typename Func>
486         bool erase_with( Q const& key, Less pred, Func f )
487         {
488 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
489             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
490                 [&f]( node_type const& node) { cds::unref(f)( node.m_Value ); } );
491 #       else
492             erase_functor<Func> wrapper(f);
493             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
494                 cds::ref(wrapper));
495 #       endif
496         }
497
498         /// Extracts the item from the set with specified \p key
499         /** \anchor cds_nonintrusive_SkipListSet_hp_extract
500             The function searches an item with key equal to \p key in the set,
501             unlinks it from the set, and returns it in \p result parameter.
502             If the item with key equal to \p key is not found the function returns \p false.
503
504             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
505
506             The item extracted is freed automatically by garbage collector \p GC
507             when returned \ref guarded_ptr object will be destroyed or released.
508             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
509
510             Usage:
511             \code
512             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
513             skip_list theList;
514             // ...
515             {
516                 skip_list::guarded_ptr gp;
517                 if ( theList.extract( gp, 5 ) ) {
518                     // Deal with gp
519                     // ...
520                 }
521                 // Destructor of gp releases internal HP guard and frees the pointer
522             }
523             \endcode
524         */
525         template <typename Q>
526         bool extract( guarded_ptr& result, Q const& key )
527         {
528             return base_class::extract_( result.guard(), key, typename base_class::key_comparator() );
529         }
530
531         /// Extracts the item from the set with comparing functor \p pred
532         /**
533             The function is an analog of \ref cds_nonintrusive_SkipListSet_hp_extract "extract(Q const&)"
534             but \p pred predicate is used for key comparing.
535
536             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
537             in any order.
538             \p pred must imply the same element order as the comparator used for building the set.
539         */
540         template <typename Q, typename Less>
541         bool extract_with( guarded_ptr& ptr, Q const& key, Less pred )
542         {
543             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >  wrapped_less;
544             return base_class::extract_( ptr.guard(), key, cds::opt::details::make_comparator_from_less<wrapped_less>() );
545         }
546
547         /// Extracts an item with minimal key from the set
548         /**
549             The function searches an item with minimal key, unlinks it, and returns the item found in \p result parameter.
550             If the skip-list is empty the function returns \p false.
551
552             The item extracted is freed automatically by garbage collector \p GC
553             when returned \ref guarded_ptr object will be destroyed or released.
554             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
555
556             Usage:
557             \code
558             typedef cds::continer::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
559             skip_list theList;
560             // ...
561             {
562                 skip_list::guarded_ptr gp;
563                 if ( theList.extract_min( gp )) {
564                     // Deal with gp
565                     //...
566                 }
567                 // Destructor of gp releases internal HP guard and then frees the pointer
568             }
569             \endcode
570         */
571         bool extract_min( guarded_ptr& result)
572         {
573             return base_class::extract_min_( result.guard() );
574         }
575
576         /// Extracts an item with maximal key from the set
577         /**
578             The function searches an item with maximal key, unlinks it, and returns the pointer to item found in \p result parameter.
579             If the skip-list is empty the function returns \p false.
580
581             The item found is freed by garbage collector \p GC automatically
582             when returned \ref guarded_ptr object will be destroyed or released.
583             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
584
585             Usage:
586             \code
587             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
588             skip_list theList;
589             // ...
590             {
591                 skip_list::guarded_ptr gp;
592                 if ( theList.extract_max( gp )) {
593                     // Deal with gp
594                     //...
595                 }
596                 // Destructor of gp releases internal HP guard and then frees the pointer
597             }
598             \endcode
599         */
600         bool extract_max( guarded_ptr& result )
601         {
602             return base_class::extract_max_( result.guard() );
603         }
604
605         /// Find the key \p val
606         /** \anchor cds_nonintrusive_SkipListSet_find_func
607
608             The function searches the item with key equal to \p val and calls the functor \p f for item found.
609             The interface of \p Func functor is:
610             \code
611             struct functor {
612                 void operator()( value_type& item, Q& val );
613             };
614             \endcode
615             where \p item is the item found, \p val is the <tt>find</tt> function argument.
616
617             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
618
619             The functor may change non-key fields of \p item. Note that the functor is only guarantee
620             that \p item cannot be disposed during functor is executing.
621             The functor does not serialize simultaneous access to the set's \p item. If such access is
622             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
623
624             The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor
625             can modify both arguments.
626
627             Note the hash functor specified for class \p Traits template parameter
628             should accept a parameter of type \p Q that may be not the same as \p value_type.
629
630             The function returns \p true if \p val is found, \p false otherwise.
631         */
632         template <typename Q, typename Func>
633         bool find( Q& val, Func f )
634         {
635 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
636             return base_class::find( val, [&f]( node_type& node, Q& v ) { cds::unref(f)( node.m_Value, v ); });
637 #       else
638             find_functor<Func> wrapper(f);
639             return base_class::find( val, cds::ref(wrapper));
640 #       endif
641         }
642
643         /// Finds the key \p val using \p pred predicate for searching
644         /**
645             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_func "find(Q&, Func)"
646             but \p pred is used for key comparing.
647             \p Less functor has the interface like \p std::less.
648             \p Less must imply the same element order as the comparator used for building the set.
649         */
650         template <typename Q, typename Less, typename Func>
651         bool find_with( Q& val, Less pred, Func f )
652         {
653 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
654             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
655                 [&f]( node_type& node, Q& v ) { cds::unref(f)( node.m_Value, v ); } );
656 #       else
657             find_functor<Func> wrapper(f);
658             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(), cds::ref(wrapper));
659 #       endif
660         }
661
662         /// Find the key \p val
663         /** \anchor cds_nonintrusive_SkipListSet_find_cfunc
664
665             The function searches the item with key equal to \p val and calls the functor \p f for item found.
666             The interface of \p Func functor is:
667             \code
668             struct functor {
669                 void operator()( value_type& item, Q const& val );
670             };
671             \endcode
672             where \p item is the item found, \p val is the <tt>find</tt> function argument.
673
674             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
675
676             The functor may change non-key fields of \p item. Note that the functor is only guarantee
677             that \p item cannot be disposed during functor is executing.
678             The functor does not serialize simultaneous access to the set's \p item. If such access is
679             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
680
681             Note the hash functor specified for class \p Traits template parameter
682             should accept a parameter of type \p Q that may be not the same as \p value_type.
683
684             The function returns \p true if \p val is found, \p false otherwise.
685         */
686         template <typename Q, typename Func>
687         bool find( Q const& val, Func f )
688         {
689 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
690             return base_class::find( val, [&f]( node_type& node, Q const& v ) { cds::unref(f)( node.m_Value, v ); });
691 #       else
692             find_functor<Func> wrapper(f);
693             return base_class::find( val, cds::ref(wrapper));
694 #       endif
695         }
696
697         /// Finds the key \p val using \p pred predicate for searching
698         /**
699             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_cfunc "find(Q const&, Func)"
700             but \p pred is used for key comparing.
701             \p Less functor has the interface like \p std::less.
702             \p Less must imply the same element order as the comparator used for building the set.
703         */
704         template <typename Q, typename Less, typename Func>
705         bool find_with( Q const& val, Less cmp, Func f )
706         {
707 #       ifdef CDS_CXX11_LAMBDA_SUPPORT
708             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
709                 [&f]( node_type& node, Q const& v ) { cds::unref(f)( node.m_Value, v ); } );
710 #       else
711             find_functor<Func> wrapper(f);
712             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >(),
713                 cds::ref(wrapper));
714 #       endif
715         }
716
717         /// Find the key \p val
718         /** \anchor cds_nonintrusive_SkipListSet_find_val
719
720             The function searches the item with key equal to \p val
721             and returns \p true if it is found, and \p false otherwise.
722
723             Note the hash functor specified for class \p Traits template parameter
724             should accept a parameter of type \p Q that may be not the same as \ref value_type.
725         */
726         template <typename Q>
727         bool find( Q const& val )
728         {
729             return base_class::find( val );
730         }
731
732         /// Finds the key \p val using \p pred predicate for searching
733         /**
734             The function is an analog of \ref cds_nonintrusive_SkipListSet_find_val "find(Q const&)"
735             but \p pred is used for key comparing.
736             \p Less functor has the interface like \p std::less.
737             \p Less must imply the same element order as the comparator used for building the set.
738         */
739         template <typename Q, typename Less>
740         bool find_with( Q const& val, Less pred )
741         {
742             return base_class::find_with( val, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >());
743         }
744
745         /// Finds \p key and return the item found
746         /** \anchor cds_nonintrusive_SkipListSet_hp_get
747             The function searches the item with key equal to \p key
748             and assigns the item found to guarded pointer \p result.
749             The function returns \p true if \p key is found, and \p false otherwise.
750             If \p key is not found the \p result parameter is left unchanged.
751
752             It is safe when a concurrent thread erases the item returned in \p result guarded pointer.
753             In this case the item will be freed later by garbage collector \p GC automatically
754             when \p guarded_ptr object will be destroyed or released.
755             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
756
757             Usage:
758             \code
759             typedef cds::container::SkipListSet< cds::gc::HP, foo, my_traits >  skip_list;
760             skip_list theList;
761             // ...
762             {
763                 skip_list::guarded_ptr gp;
764                 if ( theList.get( gp, 5 ) ) {
765                     // Deal with gp
766                     //...
767                 }
768                 // Destructor of guarded_ptr releases internal HP guard
769             }
770             \endcode
771
772             Note the compare functor specified for class \p Traits template parameter
773             should accept a parameter of type \p Q that can be not the same as \p value_type.
774         */
775         template <typename Q>
776         bool get( guarded_ptr& result, Q const& key )
777         {
778             return base_class::get_with_( result.guard(), key, typename base_class::key_comparator() );
779         }
780
781         /// Finds \p key and return the item found
782         /**
783             The function is an analog of \ref cds_nonintrusive_SkipListSet_hp_get "get( guarded_ptr&, Q const&)"
784             but \p pred is used for comparing the keys.
785
786             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
787             in any order.
788             \p pred must imply the same element order as the comparator used for building the set.
789         */
790         template <typename Q, typename Less>
791         bool get_with( guarded_ptr& result, Q const& key, Less pred )
792         {
793             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >  wrapped_less;
794             return base_class::get_with_( result.guard(), key, cds::opt::details::make_comparator_from_less< wrapped_less >());
795         }
796
797         /// Clears the set (non-atomic).
798         /**
799             The function deletes all items from the set.
800             The function is not atomic, thus, in multi-threaded environment with parallel insertions
801             this sequence
802             \code
803             set.clear();
804             assert( set.empty() );
805             \endcode
806             the assertion could be raised.
807
808             For each item the \ref disposer provided by \p Traits template parameter will be called.
809         */
810         void clear()
811         {
812             base_class::clear();
813         }
814
815         /// Checks if the set is empty
816         bool empty() const
817         {
818             return base_class::empty();
819         }
820
821         /// Returns item count in the set
822         /**
823             The value returned depends on item counter type provided by \p Traits template parameter.
824             If it is atomicity::empty_item_counter this function always returns 0.
825             Therefore, the function is not suitable for checking the set emptiness, use \ref empty
826             member function for this purpose.
827         */
828         size_t size() const
829         {
830             return base_class::size();
831         }
832
833         /// Returns const reference to internal statistics
834         stat const& statistics() const
835         {
836             return base_class::statistics();
837         }
838
839     };
840
841 }} // namespace cds::container
842
843 #endif // #ifndef __CDS_CONTAINER_SKIP_LIST_SET_IMPL_H