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