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