e754477310e3a7291bf90dbeaec648a3e5b6352e
[libcds.git] / cds / container / split_list_map_rcu.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_SPLIT_LIST_MAP_RCU_H
4 #define __CDS_CONTAINER_SPLIT_LIST_MAP_RCU_H
5
6 #include <cds/container/split_list_set_rcu.h>
7 #include <cds/details/binary_functor_wrapper.h>
8
9 namespace cds { namespace container {
10
11     /// Split-ordered list map (template specialization for \ref cds_urcu_desc "RCU")
12     /** @ingroup cds_nonintrusive_map
13         \anchor cds_nonintrusive_SplitListMap_rcu
14
15         Hash table implementation based on split-ordered list algorithm discovered by Ori Shalev and Nir Shavit, see
16         - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables"
17         - [2008] Nir Shavit "The Art of Multiprocessor Programming"
18
19         See intrusive::SplitListSet for a brief description of the split-list algorithm.
20
21         Template parameters:
22         - \p RCU - one of \ref cds_urcu_gc "RCU type"
23         - \p Key - key type of an item stored in the map. It should be copy-constructible
24         - \p Value - value type stored in the map
25         - \p Traits - type traits, default is split_list::type_traits. Instead of declaring split_list::type_traits -based
26             struct you may apply option-based notation with split_list::make_traits metafunction.
27
28         <b>Iterators</b>
29
30         The class supports a forward iterator (\ref iterator and \ref const_iterator).
31         The iteration is unordered.
32
33         You may iterate over split-list map items only under RCU lock.
34         Only in this case the iterator is thread-safe since
35         while RCU is locked any map's item cannot be reclaimed.
36
37         The requirement of RCU lock during iterating means that deletion of the elements (i.e. \ref erase)
38         is not possible.
39
40         @warning The iterator object cannot be passed between threads
41
42         \warning Due to concurrent nature of split-list map it is not guarantee that you can iterate
43         all elements in the map: any concurrent deletion can exclude the element
44         pointed by the iterator from the map, and your iteration can be terminated
45         before end of the map. Therefore, such iteration is more suitable for debugging purposes
46
47         The iterator class supports the following minimalistic interface:
48         \code
49         struct iterator {
50             // Default ctor
51             iterator();
52
53             // Copy ctor
54             iterator( iterator const& s);
55
56             value_type * operator ->() const;
57             value_type& operator *() const;
58
59             // Pre-increment
60             iterator& operator ++();
61
62             // Copy assignment
63             iterator& operator = (const iterator& src);
64
65             bool operator ==(iterator const& i ) const;
66             bool operator !=(iterator const& i ) const;
67         };
68         \endcode
69         Note, the iterator object returned by \ref end, \p cend member functions points to \p NULL and should not be dereferenced.
70
71         \par Usage
72
73         You should decide what garbage collector you want, and what ordered list you want to use. Split-ordered list
74         is original data structure based on an ordered list. Suppose, you want construct split-list map based on cds::urcu::general_buffered<> GC
75         and MichaelList as ordered list implementation. Your map should map \p int key to <tt>std::string</tt> value.
76         So, you beginning your program with following include:
77         \code
78         #include <cds/urcu/general_buffered.h>
79         #include <cds/container/michael_list_rcu.h>
80         #include <cds/container/split_list_map_rcu.h>
81
82         namespace cc = cds::container;
83         \endcode
84         The inclusion order is important:
85         - first, include one of \ref cds_urcu_gc "RCU implementation" (<tt>cds/urcu/general_buffered.h</tt> in our case)
86         - second, include file for ordered-list implementation (for this example, <tt>cds/container/michael_list_rcu.h</tt>),
87         - then, the header for RCU-based split-list map <tt>cds/container/split_list_map_rcu.h</tt>.
88
89         Now, you should declare traits for split-list map. The main parts of traits are a hash functor for the map key and a comparing functor for ordered list.
90         We use <tt>std::hash<int></tt> as hash functor and <tt>std::less<int></tt> predicate as comparing functor.
91
92         The second attention: instead of using %MichaelList in %SplitListMap traits we use a tag <tt>cds::contaner::michael_list_tag</tt>
93         for the Michael's list.
94         The split-list requires significant support from underlying ordered list class and it is not good idea to dive you
95         into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface.
96
97         \code
98         // SplitListMap traits
99         struct foo_set_traits: public cc::split_list::type_traits
100         {
101             typedef cc::michael_list_tag   ordered_list    ;   // what type of ordered list we want to use
102             typedef std::hash<int>         hash            ;   // hash functor for the key stored in split-list map
103
104             // Type traits for our MichaelList class
105             struct ordered_list_traits: public cc::michael_list::type_traits
106             {
107                 typedef std::less<int> less   ;   // use our std::less predicate as comparator to order list nodes
108             };
109         };
110         \endcode
111
112         Now you are ready to declare our map class based on \p %SplitListMap:
113         \code
114         typedef cc::SplitListMap< cds::urcu::gc<cds::urcu::general_buffered<> >, int, std::string, foo_set_traits > int_string_map;
115         \endcode
116
117         You may use the modern option-based declaration instead of classic type-traits-based one:
118         \code
119         typedef cc:SplitListMap<
120             cds::urcu::gc<cds::urcu::general_buffered<> >  // RCU type
121             ,int                    // key type
122             ,std::string            // value type
123             ,cc::split_list::make_traits<      // metafunction to build split-list traits
124                 cc::split_list::ordered_list<cc::michael_list_tag>     // tag for underlying ordered list implementation
125                 ,cc::opt::hash< std::hash<int> >        // hash functor
126                 ,cc::split_list::ordered_list_traits<    // ordered list traits desired
127                     cc::michael_list::make_traits<    // metafunction to build lazy list traits
128                         cc::opt::less< std::less<int> >         // less-based compare functor
129                     >::type
130                 >
131             >::type
132         >  int_string_map;
133         \endcode
134         In case of option-based declaration using split_list::make_traits metafunction the struct \p foo_set_traits is not required.
135
136         Now, the map of type \p int_string_map is ready to use in your program.
137
138         Note that in this example we show only mandatory type_traits parts, optional ones is the default and they are inherited
139         from cds::container::split_list::type_traits.
140         The <b>cds</b> library contains many other options for deep tuning of behavior of the split-list and
141         ordered-list containers.
142     */
143     template <
144         class RCU,
145         typename Key,
146         typename Value,
147 #ifdef CDS_DOXYGEN_INVOKED
148         class Traits = split_list::type_traits
149 #else
150         class Traits
151 #endif
152     >
153     class SplitListMap< cds::urcu::gc< RCU >, Key, Value, Traits >:
154         protected container::SplitListSet<
155             cds::urcu::gc< RCU >,
156             std::pair<Key const, Value>,
157             split_list::details::wrap_map_traits<Key, Value, Traits>
158         >
159     {
160         //@cond
161         typedef container::SplitListSet<
162             cds::urcu::gc< RCU >,
163             std::pair<Key const, Value>,
164             split_list::details::wrap_map_traits<Key, Value, Traits>
165         >  base_class;
166         //@endcond
167
168     public:
169         typedef typename base_class::gc gc              ;   ///< Garbage collector
170         typedef Traits                  options         ;   ///< ]p Traits template argument
171         typedef Key                     key_type        ;   ///< key type
172         typedef Value                   mapped_type     ;   ///< type of value stored in the map
173
174         typedef std::pair<key_type const, mapped_type>  value_type  ;   ///< key-value pair type
175         typedef typename base_class::ordered_list       ordered_list;   ///< Underlying ordered list class
176         typedef typename base_class::key_comparator     key_comparator  ;   ///< key comparison functor
177
178         typedef typename base_class::hash           hash            ;   ///< Hash functor for \ref key_type
179         typedef typename base_class::item_counter   item_counter    ;   ///< Item counter type
180
181         typedef typename base_class::rcu_lock       rcu_lock    ; ///< RCU scoped lock
182         typedef typename base_class::exempt_ptr     exempt_ptr  ; ///< pointer to extracted node
183         /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
184         static CDS_CONSTEXPR_CONST bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
185
186     protected:
187         //@cond
188         typedef typename base_class::maker::type_traits::key_accessor key_accessor;
189
190 #   ifndef CDS_CXX11_LAMBDA_SUPPORT
191         template <typename Func>
192         class ensure_functor_wrapper: protected cds::details::functor_wrapper<Func>
193         {
194             typedef cds::details::functor_wrapper<Func> base_class;
195         public:
196             ensure_functor_wrapper() {}
197             ensure_functor_wrapper( Func f ): base_class(f) {}
198
199             template <typename Q>
200             void operator()( bool bNew, value_type& item, const Q& /*val*/ )
201             {
202                 base_class::get()( bNew, item );
203             }
204         };
205
206         template <typename Func>
207         class find_functor_wrapper: protected cds::details::functor_wrapper<Func>
208         {
209             typedef cds::details::functor_wrapper<Func> base_class;
210         public:
211             find_functor_wrapper() {}
212             find_functor_wrapper( Func f ): base_class(f) {}
213
214             template <typename Q>
215             void operator()( value_type& pair, Q const& /*val*/ )
216             {
217                 base_class::get()( pair );
218             }
219         };
220 #   endif   // ifndef CDS_CXX11_LAMBDA_SUPPORT
221         //@endcond
222
223     public:
224         /// Forward iterator
225         typedef typename base_class::iterator iterator;
226
227         /// Const forward iterator
228         typedef typename base_class::const_iterator const_iterator;
229
230         /// Returns a forward iterator addressing the first element in a map
231         /**
232             For empty map \code begin() == end() \endcode
233         */
234         iterator begin()
235         {
236             return base_class::begin();
237         }
238
239         /// Returns an iterator that addresses the location succeeding the last element in a map
240         /**
241             Do not use the value returned by <tt>end</tt> function to access any item.
242             The returned value can be used only to control reaching the end of the map.
243             For empty map \code begin() == end() \endcode
244         */
245         iterator end()
246         {
247             return base_class::end();
248         }
249
250         /// Returns a forward const iterator addressing the first element in a map
251         //@{
252         const_iterator begin() const
253         {
254             return base_class::begin();
255         }
256         const_iterator cbegin()
257         {
258             return base_class::cbegin();
259         }
260         //@}
261
262         /// Returns an const iterator that addresses the location succeeding the last element in a map
263         //@{
264         const_iterator end() const
265         {
266             return base_class::end();
267         }
268         const_iterator cend()
269         {
270             return base_class::cend();
271         }
272         //@}
273
274     public:
275         /// Initializes split-ordered map of default capacity
276         /**
277             The default capacity is defined in bucket table constructor.
278             See intrusive::split_list::expandable_bucket_table, intrusive::split_list::static_bucket_table
279             which selects by intrusive::split_list::dynamic_bucket_table option.
280         */
281         SplitListMap()
282             : base_class()
283         {}
284
285         /// Initializes split-ordered map
286         SplitListMap(
287             size_t nItemCount           ///< estimate average item count
288             , size_t nLoadFactor = 1    ///< load factor - average item count per bucket. Small integer up to 10, default is 1.
289             )
290             : base_class( nItemCount, nLoadFactor )
291         {}
292
293     public:
294         /// Inserts new node with key and default value
295         /**
296             The function creates a node with \p key and default value, and then inserts the node created into the map.
297
298             Preconditions:
299             - The \ref key_type should be constructible from value of type \p K.
300                 In trivial case, \p K is equal to \ref key_type.
301             - The \ref mapped_type should be default-constructible.
302
303             The function applies RCU lock internally.
304
305             Returns \p true if inserting successful, \p false otherwise.
306         */
307         template <typename K>
308         bool insert( K const& key )
309         {
310             //TODO: pass arguments by reference (make_pair makes copy)
311             return base_class::insert( std::make_pair( key, mapped_type() ) );
312         }
313
314         /// Inserts new node
315         /**
316             The function creates a node with copy of \p val value
317             and then inserts the node created into the map.
318
319             Preconditions:
320             - The \ref key_type should be constructible from \p key of type \p K.
321             - The \ref mapped_type should be constructible from \p val of type \p V.
322
323             The function applies RCU lock internally.
324
325             Returns \p true if \p val is inserted into the map, \p false otherwise.
326         */
327         template <typename K, typename V>
328         bool insert( K const& key, V const& val )
329         {
330             //TODO: pass arguments by reference (make_pair makes copy)
331             return base_class::insert( std::make_pair(key, val) );
332         }
333
334         /// Inserts new node and initialize it by a functor
335         /**
336             This function inserts new node with key \p key and if inserting is successful then it calls
337             \p func functor with signature
338             \code
339                 struct functor {
340                     void operator()( value_type& item );
341                 };
342             \endcode
343
344             The argument \p item of user-defined functor \p func is the reference
345             to the map's item inserted:
346                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
347                 - <tt>item.second</tt> is a reference to item's value that may be changed.
348
349             It should be keep in mind that concurrent modifications of \p <tt>item.second</tt> may be possible.
350             User-defined functor \p func should guarantee that during changing item's value no any other changes
351             could be made on this \p item by concurrent threads.
352
353             The user-defined functor can be passed by reference using <tt>boost::ref</tt>
354             and it is called only if inserting is successful.
355
356             The key_type should be constructible from value of type \p K.
357
358             The function allows to split creating of new item into two part:
359             - create item from \p key;
360             - insert new item into the map;
361             - if inserting is successful, initialize the value of item by calling \p func functor
362
363             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
364             it is preferable that the initialization should be completed only if inserting is successful.
365
366             The function applies RCU lock internally.
367         */
368         template <typename K, typename Func>
369         bool insert_key( K const& key, Func func )
370         {
371             //TODO: pass arguments by reference (make_pair makes copy)
372             return base_class::insert( std::make_pair( key, mapped_type() ), func );
373         }
374
375 #   ifdef CDS_EMPLACE_SUPPORT
376         /// For key \p key inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
377         /**
378             \p key_type should be constructible from type \p K
379
380             The function applies RCU lock internally.
381
382             Returns \p true if inserting successful, \p false otherwise.
383
384             @note This function is available only for compiler that supports
385             variadic template and move semantics
386         */
387         template <typename K, typename... Args>
388         bool emplace( K&& key, Args&&... args )
389         {
390             return base_class::emplace( std::forward<K>(key), std::move(mapped_type(std::forward<Args>(args)...)));
391         }
392 #   endif
393
394         /// Ensures that the \p key exists in the map
395         /**
396             The operation performs inserting or changing data with lock-free manner.
397
398             If the \p key not found in the map, then the new item created from \p key
399             is inserted into the map (note that in this case the \ref key_type should be
400             constructible from type \p K).
401             Otherwise, the functor \p func is called with item found.
402             The functor \p Func may be a function with signature:
403             \code
404                 void func( bool bNew, value_type& item );
405             \endcode
406             or a functor:
407             \code
408                 struct my_functor {
409                     void operator()( bool bNew, value_type& item );
410                 };
411             \endcode
412
413             with arguments:
414             - \p bNew - \p true if the item has been inserted, \p false otherwise
415             - \p item - item of the list
416
417             The functor may change any fields of the \p item.second that is \ref mapped_type;
418             however, \p func must guarantee that during changing no any other modifications
419             could be made on this item by concurrent threads.
420
421             You may pass \p func argument by reference using <tt>boost::ref</tt>.
422
423             The function applies RCU lock internally.
424
425             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
426             \p second is true if new item has been added or \p false if the item with \p key
427             already is in the list.
428         */
429         template <typename K, typename Func>
430         std::pair<bool, bool> ensure( K const& key, Func func )
431         {
432             //TODO: pass arguments by reference (make_pair makes copy)
433 #   ifdef CDS_CXX11_LAMBDA_SUPPORT
434             return base_class::ensure( std::make_pair( key, mapped_type() ),
435                 [&func](bool bNew, value_type& item, value_type const& /*val*/) {
436                     cds::unref(func)( bNew, item );
437                 } );
438 #   else
439             ensure_functor_wrapper<Func> fw( func );
440             return base_class::ensure( std::make_pair( key, mapped_type() ), cds::ref(fw) );
441 #   endif
442         }
443
444         /// Deletes \p key from the map
445         /** \anchor cds_nonintrusive_SplitListMap_rcu_erase_val
446
447             RCU \p synchronize method can be called. RCU should not be locked.
448
449             Return \p true if \p key is found and deleted, \p false otherwise
450         */
451         template <typename K>
452         bool erase( K const& key )
453         {
454             return base_class::erase( key );
455         }
456
457         /// Deletes the item from the map using \p pred predicate for searching
458         /**
459             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_erase_val "erase(K const&)"
460             but \p pred is used for key comparing.
461             \p Less functor has the interface like \p std::less.
462             \p Less must imply the same element order as the comparator used for building the map.
463         */
464         template <typename K, typename Less>
465         bool erase_with( K const& key, Less pred )
466         {
467             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>() );
468         }
469
470         /// Deletes \p key from the map
471         /** \anchor cds_nonintrusive_SplitListMap_rcu_erase_func
472
473             The function searches an item with key \p key, calls \p f functor
474             and deletes the item. If \p key is not found, the functor is not called.
475
476             The functor \p Func interface is:
477             \code
478             struct extractor {
479                 void operator()(value_type& item) { ... }
480             };
481             \endcode
482             The functor may be passed by reference using <tt>boost:ref</tt>
483
484             RCU \p synchronize method can be called. RCU should not be locked.
485
486             Return \p true if key is found and deleted, \p false otherwise
487         */
488         template <typename K, typename Func>
489         bool erase( K const& key, Func f )
490         {
491             return base_class::erase( key, f );
492         }
493
494         /// Deletes the item from the map using \p pred predicate for searching
495         /**
496             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_erase_func "erase(K const&, Func)"
497             but \p pred is used for key comparing.
498             \p Less functor has the interface like \p std::less.
499             \p Less must imply the same element order as the comparator used for building the map.
500         */
501         template <typename K, typename Less, typename Func>
502         bool erase_with( K const& key, Less pred, Func f )
503         {
504             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>(), f );
505         }
506
507         /// Extracts an item from the map
508         /** \anchor cds_nonintrusive_SplitListMap_rcu_extract
509             The function searches an item with key equal to \p key in the map,
510             unlinks it from the map, places item pointer into \p dest argument, and returns \p true.
511             If the item with the key equal to \p key is not found the function return \p false.
512
513             @note The function does NOT call RCU read-side lock or synchronization,
514             and does NOT dispose the item found. It just excludes the item from the map
515             and returns a pointer to item found.
516             You should lock RCU before calling of the function, and you should synchronize RCU
517             outside the RCU lock to free extracted item
518
519             \code
520             typedef cds::urcu::gc< general_buffered<> > rcu;
521             typedef cds::container::SplitListMap< rcu, int, Foo > splitlist_map;
522
523             splitlist_map theMap;
524             // ...
525
526             typename splitlist_map::exempt_ptr p;
527             {
528                 // first, we should lock RCU
529                 typename splitlist_map::rcu_lock lock;
530
531                 // Now, you can apply extract function
532                 // Note that you must not delete the item found inside the RCU lock
533                 if ( theMap.extract( p, 10 )) {
534                     // do something with p
535                     ...
536                 }
537             }
538
539             // We may safely release p here
540             // release() passes the pointer to RCU reclamation cycle
541             p.release();
542             \endcode
543         */
544         template <typename K>
545         bool extract( exempt_ptr& dest, K const& key )
546         {
547             return base_class::extract( dest, key );
548         }
549
550         /// Extracts an item from the map using \p pred predicate for searching
551         /**
552             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_extract "extract(exempt_ptr&, K const&)"
553             but \p pred is used for key comparing.
554             \p Less functor has the interface like \p std::less.
555             \p pred must imply the same element order as the comparator used for building the map.
556         */
557         template <typename K, typename Less>
558         bool extract_with( exempt_ptr& dest, K const& key, Less pred )
559         {
560             return base_class::extract_with( dest, key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
561         }
562
563         /// Finds the key \p key
564         /** \anchor cds_nonintrusive_SplitListMap_rcu_find_cfunc
565
566             The function searches the item with key equal to \p key and calls the functor \p f for item found.
567             The interface of \p Func functor is:
568             \code
569             struct functor {
570                 void operator()( value_type& item );
571             };
572             \endcode
573             where \p item is the item found.
574
575             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
576
577             The functor may change \p item.second. Note that the functor is only guarantee
578             that \p item cannot be disposed during functor is executing.
579             The functor does not serialize simultaneous access to the map's \p item. If such access is
580             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
581
582             The function applies RCU lock internally.
583
584             The function returns \p true if \p key is found, \p false otherwise.
585         */
586         template <typename K, typename Func>
587         bool find( K const& key, Func f )
588         {
589 #   ifdef CDS_CXX11_LAMBDA_SUPPORT
590             return base_class::find( key, [&f](value_type& pair, K const&){ cds::unref(f)( pair ); } );
591 #   else
592             find_functor_wrapper<Func> fw(f);
593             return base_class::find( key, cds::ref(fw) );
594 #   endif
595         }
596
597         /// Finds the key \p key using \p pred predicate for searching
598         /**
599             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_find_cfunc "find(K const&, Func)"
600             but \p pred is used for key comparing.
601             \p Less functor has the interface like \p std::less.
602             \p Less must imply the same element order as the comparator used for building the map.
603         */
604         template <typename K, typename Less, typename Func>
605         bool find_with( K const& key, Less pred, Func f )
606         {
607 #   ifdef CDS_CXX11_LAMBDA_SUPPORT
608             return base_class::find_with( key,
609                 cds::details::predicate_wrapper<value_type, Less, key_accessor>(),
610                 [&f](value_type& pair, K const&){ cds::unref(f)( pair ); } );
611 #   else
612             find_functor_wrapper<Func> fw(f);
613             return base_class::find_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>(), cds::ref(fw) );
614 #   endif
615         }
616
617         /// Finds the key \p key
618         /** \anchor cds_nonintrusive_SplitListMap_rcu_find_val
619
620             The function searches the item with key equal to \p key
621             and returns \p true if it is found, and \p false otherwise.
622
623             The function applies RCU lock internally.
624         */
625         template <typename K>
626         bool find( K const& key )
627         {
628             return base_class::find( key );
629         }
630
631         /// Finds the key \p key using \p pred predicate for searching
632         /**
633             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_find_val "find(K const&)"
634             but \p pred is used for key comparing.
635             \p Less functor has the interface like \p std::less.
636             \p Less must imply the same element order as the comparator used for building the map.
637         */
638         template <typename K, typename Less>
639         bool find_with( K const& key, Less pred )
640         {
641             return base_class::find_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>() );
642         }
643
644         /// Finds \p key and return the item found
645         /** \anchor cds_intrusive_SplitListMap_rcu_get
646             The function searches the item with key equal to \p key and returns the pointer to item found.
647             If \p key is not found it returns \p NULL.
648
649             Note the compare functor should accept a parameter of type \p K that can be not the same as \p value_type.
650
651             RCU should be locked before call of this function.
652             Returned item is valid only while RCU is locked:
653             \code
654             typedef cds::urcu::gc< general_buffered<> > rcu;
655             typedef cds::container::SplitListMap< rcu, int, Foo > splitlist_map;
656             splitlist_map theMap;
657             // ...
658             {
659                 // Lock RCU
660                 typename splitlist_map::rcu_lock lock;
661
662                 typename splitlist_map::value_type * pVal = theMap.get( 5 );
663                 if ( pVal ) {
664                     // Deal with pVal
665                     //...
666                 }
667                 // Unlock RCU by rcu_lock destructor
668                 // pVal can be retired by disposer at any time after RCU has been unlocked
669             }
670             \endcode
671         */
672         template <typename K>
673         value_type * get( K const& key )
674         {
675             return base_class::get( key );
676         }
677
678         /// Finds \p key with predicate specified and return the item found
679         /**
680             The function is an analog of \ref cds_intrusive_SplitListMap_rcu_get "get(K const&)"
681             but \p pred is used for comparing the keys.
682
683             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p K
684             in any order.
685             \p pred must imply the same element order as the comparator used for building the map.
686         */
687         template <typename K, typename Less>
688         value_type * get_with( K const& key, Less pred )
689         {
690             return base_class::get_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
691         }
692
693         /// Clears the map (non-atomic)
694         /**
695             The function unlink all items from the map.
696             The function is not atomic and not lock-free and should be used for debugging only.
697
698             RCU \p synchronize method can be called. RCU should not be locked.
699         */
700         void clear()
701         {
702             base_class::clear();
703         }
704
705         /// Checks if the map is empty
706         /**
707             Emptiness is checked by item counting: if item count is zero then the map is empty.
708             Thus, the correct item counting is an important part of the map implementation.
709         */
710         bool empty() const
711         {
712             return base_class::empty();
713         }
714
715         /// Returns item count in the map
716         size_t size() const
717         {
718             return base_class::size();
719         }
720     };
721
722
723 }} // namespace cds::container
724
725 #endif // #ifndef __CDS_CONTAINER_SPLIT_LIST_MAP_RCU_H