Added copyright and license
[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-2016
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             //TODO: pass arguments by reference (make_pair makes copy)
303             return base_class::insert( std::make_pair( key, mapped_type() ) );
304         }
305
306         /// Inserts new node
307         /**
308             The function creates a node with copy of \p val value
309             and then inserts the node into the map.
310
311             Preconditions:
312             - The \p key_type should be constructible from \p key of type \p K.
313             - The \p mapped_type should be constructible from \p val of type \p V.
314
315             The function applies RCU lock internally.
316
317             Returns \p true if \p val is inserted into the map, \p false otherwise.
318         */
319         template <typename K, typename V>
320         bool insert( K const& key, V const& val )
321         {
322             //TODO: pass arguments by reference (make_pair makes copy)
323             return base_class::insert( std::make_pair(key, val) );
324         }
325
326         /// Inserts new node and initialize it by a functor
327         /**
328             This function inserts new node with key \p key and if inserting is successful then it calls
329             \p func functor with signature
330             \code
331                 struct functor {
332                     void operator()( value_type& item );
333                 };
334             \endcode
335
336             The argument \p item of user-defined functor \p func is the reference
337             to the map's item inserted:
338                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
339                 - <tt>item.second</tt> is a reference to item's value that may be changed.
340
341             It should be keep in mind that concurrent modifications of \p <tt>item.second</tt> in \p func body
342             should be careful. You shouldf guarantee that during changing item's value in \p func no any other changes
343             could be made on this \p item by concurrent threads.
344
345             \p func is called only if inserting is successful.
346
347             The function allows to split creating of new item into two part:
348             - create item from \p key;
349             - insert new item into the map;
350             - if inserting is successful, initialize the value of item by calling \p func functor
351
352             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
353             it is preferable that the initialization should be completed only if inserting is successful.
354
355             The function applies RCU lock internally.
356         */
357         template <typename K, typename Func>
358         bool insert_with( K const& key, Func func )
359         {
360             //TODO: pass arguments by reference (make_pair makes copy)
361             return base_class::insert( std::make_pair( key, mapped_type() ), func );
362         }
363
364         /// For key \p key inserts data of type \p mapped_type created in-place from \p args
365         /**
366             \p key_type should be constructible from type \p K
367
368             The function applies RCU lock internally.
369
370             Returns \p true if inserting successful, \p false otherwise.
371         */
372         template <typename K, typename... Args>
373         bool emplace( K&& key, Args&&... args )
374         {
375             return base_class::emplace( std::forward<K>(key), std::move(mapped_type(std::forward<Args>(args)...)));
376         }
377
378         /// Updates data by \p key
379         /**
380             The operation performs inserting or replacing the element with lock-free manner.
381
382             If the \p key not found in the map, then the new item created from \p key
383             will be inserted into the map iff \p bAllowInsert is \p true.
384             (note that in this case the \ref key_type should be constructible from type \p K).
385             Otherwise, if \p key is found, the functor \p func is called with item found.
386
387             The functor \p Func signature is:
388             \code
389                 struct my_functor {
390                     void operator()( bool bNew, value_type& item );
391                 };
392             \endcode
393             with arguments:
394             - \p bNew - \p true if the item has been inserted, \p false otherwise
395             - \p item - the item found or inserted
396
397             The functor may change any fields of the \p item.second that is \p mapped_type.
398
399             The function applies RCU lock internally.
400
401             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
402             \p second is true if new item has been added or \p false if the item with \p key
403             already exists.
404
405             @warning For \ref cds_nonintrusive_MichaelKVList_gc "MichaelKVList" as the ordered list see \ref cds_intrusive_item_creating "insert item troubleshooting".
406             \ref cds_nonintrusive_LazyKVList_gc "LazyKVList" provides exclusive access to inserted item and does not require any node-level
407             synchronization.
408         */
409         template <typename K, typename Func>
410         std::pair<bool, bool> update( K const& key, Func func, bool bAllowInsert = true )
411         {
412             //TODO: pass arguments by reference (make_pair makes copy)
413             return base_class::update( std::make_pair( key, mapped_type() ),
414                 [&func](bool bNew, value_type& item, value_type const& /*val*/) {
415                     func( bNew, item );
416                 },
417                 bAllowInsert );
418         }
419         //@cond
420         template <typename K, typename Func>
421         CDS_DEPRECATED("ensure() is deprecated, use update()")
422         std::pair<bool, bool> ensure( K const& key, Func func )
423         {
424             return update( key, func, true );
425         }
426         //@endcond
427
428         /// Deletes \p key from the map
429         /** \anchor cds_nonintrusive_SplitListMap_rcu_erase_val
430
431             RCU \p synchronize method can be called. RCU should not be locked.
432
433             Return \p true if \p key is found and deleted, \p false otherwise
434         */
435         template <typename K>
436         bool erase( K const& key )
437         {
438             return base_class::erase( key );
439         }
440
441         /// Deletes the item from the map using \p pred predicate for searching
442         /**
443             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_erase_val "erase(K const&)"
444             but \p pred is used for key comparing.
445             \p Less functor has the interface like \p std::less.
446             \p Less must imply the same element order as the comparator used for building the map.
447         */
448         template <typename K, typename Less>
449         bool erase_with( K const& key, Less pred )
450         {
451             CDS_UNUSED( pred );
452             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>() );
453         }
454
455         /// Deletes \p key from the map
456         /** \anchor cds_nonintrusive_SplitListMap_rcu_erase_func
457
458             The function searches an item with key \p key, calls \p f functor
459             and deletes the item. If \p key is not found, the functor is not called.
460
461             The functor \p Func interface is:
462             \code
463             struct extractor {
464                 void operator()(value_type& item) { ... }
465             };
466             \endcode
467
468             RCU \p synchronize method can be called. RCU should not be locked.
469
470             Return \p true if key is found and deleted, \p false otherwise
471         */
472         template <typename K, typename Func>
473         bool erase( K const& key, Func f )
474         {
475             return base_class::erase( key, f );
476         }
477
478         /// Deletes the item from the map using \p pred predicate for searching
479         /**
480             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_erase_func "erase(K const&, Func)"
481             but \p pred is used for key comparing.
482             \p Less functor has the interface like \p std::less.
483             \p Less must imply the same element order as the comparator used for building the map.
484         */
485         template <typename K, typename Less, typename Func>
486         bool erase_with( K const& key, Less pred, Func f )
487         {
488             CDS_UNUSED( pred );
489             return base_class::erase_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>(), f );
490         }
491
492         /// Extracts an item from the map
493         /** \anchor cds_nonintrusive_SplitListMap_rcu_extract
494             The function searches an item with key equal to \p key in the map,
495             unlinks it from the map, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
496             If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr.
497
498             Depends on ordered list you should or should not lock RCU before calling of this function:
499             - for the set based on \ref cds_intrusive_MichaelList_rcu "MichaelList" RCU should not be locked
500             - for the set based on \ref cds_intrusive_LazyList_rcu "LazyList" RCU should be locked
501             See ordered list implementation for details.
502
503             \code
504             typedef cds::urcu::gc< general_buffered<> > rcu;
505
506             // Split-list set based on MichaelList by default
507             typedef cds::container::SplitListMap< rcu, int, Foo > splitlist_map;
508
509             splitlist_map theMap;
510             // ...
511
512             typename splitlist_map::exempt_ptr p;
513
514             // For MichaelList we should not lock RCU
515
516             // Now, you can apply extract function
517             p = theMap.extract( 10 )
518             if ( p ) {
519                 // do something with p
520                 ...
521             }
522
523             // We may safely release p here
524             // release() passes the pointer to RCU reclamation cycle
525             p.release();
526             \endcode
527         */
528         template <typename K>
529         exempt_ptr extract( K const& key )
530         {
531             return base_class::extract( key );
532         }
533
534         /// Extracts an item from the map using \p pred predicate for searching
535         /**
536             The function is an analog of \p extract(K const&) but \p pred is used for key comparing.
537             \p Less functor has the interface like \p std::less.
538             \p pred must imply the same element order as the comparator used for building the map.
539         */
540         template <typename K, typename Less>
541         exempt_ptr extract_with( K const& key, Less pred )
542         {
543             CDS_UNUSED( pred );
544             return base_class::extract_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
545         }
546
547         /// Finds the key \p key
548         /** \anchor cds_nonintrusive_SplitListMap_rcu_find_cfunc
549
550             The function searches the item with key equal to \p key and calls the functor \p f for item found.
551             The interface of \p Func functor is:
552             \code
553             struct functor {
554                 void operator()( value_type& item );
555             };
556             \endcode
557             where \p item is the item found.
558
559             The functor may change \p item.second. Note that the functor is only guarantee
560             that \p item cannot be disposed during functor is executing.
561             The functor does not serialize simultaneous access to the map's \p item. If such access is
562             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
563
564             The function applies RCU lock internally.
565
566             The function returns \p true if \p key is found, \p false otherwise.
567         */
568         template <typename K, typename Func>
569         bool find( K const& key, Func f )
570         {
571             return base_class::find( key, [&f](value_type& pair, K const&){ f( pair ); } );
572         }
573
574         /// Finds the key \p key using \p pred predicate for searching
575         /**
576             The function is an analog of \ref cds_nonintrusive_SplitListMap_rcu_find_cfunc "find(K const&, Func)"
577             but \p pred is used for key comparing.
578             \p Less functor has the interface like \p std::less.
579             \p Less must imply the same element order as the comparator used for building the map.
580         */
581         template <typename K, typename Less, typename Func>
582         bool find_with( K const& key, Less pred, Func f )
583         {
584             CDS_UNUSED( pred );
585             return base_class::find_with( key,
586                 cds::details::predicate_wrapper<value_type, Less, key_accessor>(),
587                 [&f](value_type& pair, K const&){ f( pair ); } );
588         }
589
590         /// Checks whether the map contains \p key
591         /**
592             The function searches the item with key equal to \p key
593             and returns \p true if it is found, and \p false otherwise.
594
595             The function applies RCU lock internally.
596         */
597         template <typename K>
598         bool contains( K const& key )
599         {
600             return base_class::contains( key );
601         }
602         //@cond
603         template <typename K>
604         CDS_DEPRECATED("deprecated, use contains()")
605         bool find( K const& key )
606         {
607             return base_class::find( key );
608         }
609         //@endcond
610
611         /// Checks whether the map contains \p key using \p pred predicate for searching
612         /**
613             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
614             \p Less functor has the interface like \p std::less.
615             \p Less must imply the same element order as the comparator used for building the map.
616         */
617         template <typename K, typename Less>
618         bool contains( K const& key, Less pred )
619         {
620             CDS_UNUSED( pred );
621             return base_class::contains( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>() );
622         }
623         //@cond
624         template <typename K, typename Less>
625         CDS_DEPRECATED("deprecated, use contains()")
626         bool find_with( K const& key, Less pred )
627         {
628             return contains( key, pred );
629         }
630         //@endcond
631
632         /// Finds \p key and return the item found
633         /** \anchor cds_intrusive_SplitListMap_rcu_get
634             The function searches the item with key equal to \p key and returns the pointer to item found.
635             If \p key is not found it returns empty \p raw_ptr.
636
637             Note the compare functor should accept a parameter of type \p K that can be not the same as \p value_type.
638
639             RCU should be locked before call of this function.
640             Returned item is valid only while RCU is locked:
641             \code
642             typedef cds::urcu::gc< general_buffered<> > rcu;
643             typedef cds::container::SplitListMap< rcu, int, Foo > splitlist_map;
644             splitlist_map theMap;
645             // ...
646             {
647                 // Lock RCU
648                 typename splitlist_map::rcu_lock lock;
649
650                 typename splitlist_map::raw_ptr pVal = theMap.get( 5 );
651                 if ( pVal ) {
652                     // Deal with pVal
653                     //...
654                 }
655                 // Unlock RCU by rcu_lock destructor
656                 // pVal can be retired by disposer at any time after RCU has been unlocked
657             }
658             \endcode
659         */
660         template <typename K>
661         raw_ptr get( K const& key )
662         {
663             return base_class::get( key );
664         }
665
666         /// Finds \p key with predicate specified and return the item found
667         /**
668             The function is an analog of \ref cds_intrusive_SplitListMap_rcu_get "get(K const&)"
669             but \p pred is used for comparing the keys.
670
671             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p K
672             in any order.
673             \p pred must imply the same element order as the comparator used for building the map.
674         */
675         template <typename K, typename Less>
676         raw_ptr get_with( K const& key, Less pred )
677         {
678             CDS_UNUSED( pred );
679             return base_class::get_with( key, cds::details::predicate_wrapper<value_type, Less, key_accessor>());
680         }
681
682         /// Clears the map (not atomic)
683         void clear()
684         {
685             base_class::clear();
686         }
687
688         /// Checks if the map is empty
689         /**
690             Emptiness is checked by item counting: if item count is zero then the map is empty.
691             Thus, the correct item counting is an important part of the map implementation.
692         */
693         bool empty() const
694         {
695             return base_class::empty();
696         }
697
698         /// Returns item count in the map
699         size_t size() const
700         {
701             return base_class::size();
702         }
703
704         /// Returns internal statistics
705         stat const& statistics() const
706         {
707             return base_class::statistics();
708         }
709     };
710
711 }} // namespace cds::container
712
713 #endif // #ifndef CDSLIB_CONTAINER_SPLIT_LIST_MAP_RCU_H