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