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