02e886136427b73efc03aa7a52f9283e54a904eb
[libcds.git] / cds / container / michael_map_rcu.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_MICHAEL_MAP_RCU_H
4 #define __CDS_CONTAINER_MICHAEL_MAP_RCU_H
5
6 #include <cds/container/details/michael_map_base.h>
7 #include <cds/details/allocator.h>
8
9 namespace cds { namespace container {
10
11     /// Michael's hash map (template specialization for \ref cds_urcu_desc "RCU")
12     /** @ingroup cds_nonintrusive_map
13         \anchor cds_nonintrusive_MichaelHashMap_rcu
14
15         Source:
16             - [2002] Maged Michael "High performance dynamic lock-free hash tables and list-based sets"
17
18         Michael's hash table algorithm is based on lock-free ordered list and it is very simple.
19         The main structure is an array \p T of size \p M. Each element in \p T is basically a pointer
20         to a hash bucket, implemented as a singly linked list. The array of buckets cannot be dynamically expanded.
21         However, each bucket may contain unbounded number of items.
22
23         Template parameters are:
24         - \p RCU - one of \ref cds_urcu_gc "RCU type"
25         - \p OrderedList - ordered key-value list implementation used as bucket for hash map, for example, MichaelKVList.
26             The ordered list implementation specifies the \p Key and \p Value types stored in the hash-map, the reclamation
27             schema \p GC used by hash-map, the comparison functor for the type \p Key and other features specific for
28             the ordered list.
29         - \p Traits - type traits. See michael_map::type_traits for explanation.
30
31         Instead of defining \p Traits struct you may use option-based syntax with \p michael_map::make_traits metafunction
32         (this metafunction is a synonym for michael_set::make_traits).
33         For \p michael_map::make_traits the following option may be used:
34         - opt::hash - mandatory option, specifies hash functor.
35         - opt::item_counter - optional, specifies item counting policy. See michael_map::type_traits for explanation.
36         - opt::allocator - optional, bucket table allocator. Default is \ref CDS_DEFAULT_ALLOCATOR.
37
38         Many of the class function take a key argument of type \p K that in general is not \ref key_type.
39         \p key_type and an argument of template type \p K must meet the following requirements:
40         - \p key_type should be constructible from value of type \p K;
41         - the hash functor should be able to calculate correct hash value from argument \p key of type \p K:
42             <tt> hash( key_type(key) ) == hash( key ) </tt>
43         - values of type \p key_type and \p K should be comparable
44
45         <b>How to use</b>
46
47         The tips about how to use Michael's map see \ref cds_nonintrusive_MichaelHashMap_how_touse "MichaelHashMap".
48         Remember, that you should include RCU-related header file (for example, <tt>cds/urcu/general_buffered.h</tt>)
49         before including <tt>cds/container/michael_map_rcu.h</tt>.
50     */
51     template <
52         class RCU,
53         class OrderedList,
54 #ifdef CDS_DOXYGEN_INVOKED
55         class Traits = michael_map::type_traits
56 #else
57         class Traits
58 #endif
59     >
60     class MichaelHashMap< cds::urcu::gc< RCU >, OrderedList, Traits >
61     {
62     public:
63         typedef OrderedList bucket_type     ;   ///< type of ordered list used as a bucket implementation
64         typedef Traits      options         ;   ///< Traits template parameters
65
66         typedef typename bucket_type::key_type          key_type        ;   ///< key type
67         typedef typename bucket_type::mapped_type       mapped_type     ;   ///< value type
68         typedef typename bucket_type::value_type        value_type      ;   ///< key/value pair stored in the list
69
70         typedef cds::urcu::gc< RCU >                    gc              ;   ///< RCU used as garbage collector
71         typedef typename bucket_type::key_comparator    key_comparator  ;   ///< key comparison functor
72
73         /// Hash functor for \ref key_type and all its derivatives that you use
74         typedef typename cds::opt::v::hash_selector< typename options::hash >::type   hash;
75         typedef typename options::item_counter          item_counter    ;   ///< Item counter type
76
77         /// Bucket table allocator
78         typedef cds::details::Allocator< bucket_type, typename options::allocator >  bucket_table_allocator;
79
80         typedef typename bucket_type::rcu_lock      rcu_lock   ; ///< RCU scoped lock
81         typedef typename bucket_type::exempt_ptr    exempt_ptr ; ///< pointer to extracted node
82         /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
83         static CDS_CONSTEXPR_CONST bool c_bExtractLockExternal = bucket_type::c_bExtractLockExternal;
84
85     protected:
86         item_counter    m_ItemCounter   ;   ///< Item counter
87         hash            m_HashFunctor   ;   ///< Hash functor
88
89         bucket_type *   m_Buckets       ;   ///< bucket table
90
91     private:
92         //@cond
93         const size_t    m_nHashBitmask;
94         //@endcond
95
96     protected:
97         /// Calculates hash value of \p key
98         template <typename Q>
99         size_t hash_value( Q const& key ) const
100         {
101             return m_HashFunctor( key ) & m_nHashBitmask;
102         }
103
104         /// Returns the bucket (ordered list) for \p key
105         //@{
106         template <typename Q>
107         bucket_type&    bucket( Q const& key )
108         {
109             return m_Buckets[ hash_value( key ) ];
110         }
111         template <typename Q>
112         bucket_type const&    bucket( Q const& key ) const
113         {
114             return m_Buckets[ hash_value( key ) ];
115         }
116         //@}
117     protected:
118         /// Forward iterator
119         /**
120             \p IsConst - constness boolean flag
121
122             The forward iterator for Michael's map is based on \p OrderedList forward iterator and has the following features:
123             - it has no post-increment operator, only pre-increment
124             - it iterates items in unordered fashion
125             - The iterator cannot be moved across thread boundary since it may contain GC's guard that is thread-private GC data.
126             - Iterator ensures thread-safety even if you delete the item that iterator points to. However, in case of concurrent
127               deleting operations it is no guarantee that you iterate all item in the map.
128
129             Therefore, the use of iterators in concurrent environment is not good idea. Use the iterator for the concurrent container
130             for debug purpose only.
131         */
132         template <bool IsConst>
133         class iterator_type: private cds::intrusive::michael_set::details::iterator< bucket_type, IsConst >
134         {
135             //@cond
136             typedef cds::intrusive::michael_set::details::iterator< bucket_type, IsConst >  base_class;
137             friend class MichaelHashMap;
138             //@endcond
139
140         protected:
141             //@cond
142             //typedef typename base_class::bucket_type    bucket_type;
143             typedef typename base_class::bucket_ptr     bucket_ptr;
144             typedef typename base_class::list_iterator  list_iterator;
145
146             //typedef typename bucket_type::key_type      key_type;
147             //@endcond
148
149         public:
150             /// Value pointer type (const for const_iterator)
151             typedef typename cds::details::make_const_type<typename MichaelHashMap::mapped_type, IsConst>::pointer   value_ptr;
152             /// Value reference type (const for const_iterator)
153             typedef typename cds::details::make_const_type<typename MichaelHashMap::mapped_type, IsConst>::reference value_ref;
154
155             /// Key-value pair pointer type (const for const_iterator)
156             typedef typename cds::details::make_const_type<typename MichaelHashMap::value_type, IsConst>::pointer   pair_ptr;
157             /// Key-value pair reference type (const for const_iterator)
158             typedef typename cds::details::make_const_type<typename MichaelHashMap::value_type, IsConst>::reference pair_ref;
159
160         protected:
161             //@cond
162             iterator_type( list_iterator const& it, bucket_ptr pFirst, bucket_ptr pLast )
163                 : base_class( it, pFirst, pLast )
164             {}
165             //@endcond
166
167         public:
168             /// Default ctor
169             iterator_type()
170                 : base_class()
171             {}
172
173             /// Copy ctor
174             iterator_type( const iterator_type& src )
175                 : base_class( src )
176             {}
177
178             /// Dereference operator
179             pair_ptr operator ->() const
180             {
181                 assert( base_class::m_pCurBucket != nullptr );
182                 return base_class::m_itList.operator ->();
183             }
184
185             /// Dereference operator
186             pair_ref operator *() const
187             {
188                 assert( base_class::m_pCurBucket != nullptr );
189                 return base_class::m_itList.operator *();
190             }
191
192             /// Pre-increment
193             iterator_type& operator ++()
194             {
195                 base_class::operator++();
196                 return *this;
197             }
198
199             /// Assignment operator
200             iterator_type& operator = (const iterator_type& src)
201             {
202                 base_class::operator =(src);
203                 return *this;
204             }
205
206             /// Returns current bucket (debug function)
207             bucket_ptr bucket() const
208             {
209                 return base_class::bucket();
210             }
211
212             /// Equality operator
213             template <bool C>
214             bool operator ==(iterator_type<C> const& i )
215             {
216                 return base_class::operator ==( i );
217             }
218             /// Equality operator
219             template <bool C>
220             bool operator !=(iterator_type<C> const& i )
221             {
222                 return !( *this == i );
223             }
224         };
225
226     public:
227         /// Forward iterator
228         typedef iterator_type< false >    iterator;
229
230         /// Const forward iterator
231         typedef iterator_type< true >     const_iterator;
232
233         /// Returns a forward iterator addressing the first element in a map
234         /**
235             For empty map \code begin() == end() \endcode
236         */
237         iterator begin()
238         {
239             return iterator( m_Buckets[0].begin(), m_Buckets, m_Buckets + bucket_count() );
240         }
241
242         /// Returns an iterator that addresses the location succeeding the last element in a map
243         /**
244             Do not use the value returned by <tt>end</tt> function to access any item.
245             The returned value can be used only to control reaching the end of the map.
246             For empty map \code begin() == end() \endcode
247         */
248         iterator end()
249         {
250             return iterator( m_Buckets[bucket_count() - 1].end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() );
251         }
252
253         /// Returns a forward const iterator addressing the first element in a map
254         //@{
255         const_iterator begin() const
256         {
257             return get_const_begin();
258         }
259         const_iterator cbegin()
260         {
261             return get_const_begin();
262         }
263         //@}
264
265         /// Returns an const iterator that addresses the location succeeding the last element in a map
266         //@{
267         const_iterator end() const
268         {
269             return get_const_end();
270         }
271         const_iterator cend()
272         {
273             return get_const_end();
274         }
275         //@}
276
277     private:
278         //@cond
279         const_iterator get_const_begin() const
280         {
281             return const_iterator( const_cast<bucket_type const&>(m_Buckets[0]).begin(), m_Buckets, m_Buckets + bucket_count() );
282         }
283         const_iterator get_const_end() const
284         {
285             return const_iterator( const_cast<bucket_type const&>(m_Buckets[bucket_count() - 1]).end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() );
286         }
287         //@endcond
288
289     public:
290         /// Initializes the map
291         /**
292             The Michael's hash map is non-expandable container. You should point the average count of items \p nMaxItemCount
293             when you create an object.
294             \p nLoadFactor parameter defines average count of items per bucket and it should be small number between 1 and 10.
295             Remember, since the bucket implementation is an ordered list, searching in the bucket is linear [<tt>O(nLoadFactor)</tt>].
296             Note, that many popular STL hash map implementation uses load factor 1.
297
298             The ctor defines hash table size as rounding <tt>nMacItemCount / nLoadFactor</tt> up to nearest power of two.
299         */
300         MichaelHashMap(
301             size_t nMaxItemCount,   ///< estimation of max item count in the hash map
302             size_t nLoadFactor      ///< load factor: estimation of max number of items in the bucket
303         ) : m_nHashBitmask( michael_map::details::init_hash_bitmask( nMaxItemCount, nLoadFactor ))
304         {
305             // GC and OrderedList::gc must be the same
306             static_assert(( std::is_same<gc, typename bucket_type::gc>::value ), "GC and OrderedList::gc must be the same");
307
308             // atomicity::empty_item_counter is not allowed as a item counter
309             static_assert(( !std::is_same<item_counter, atomicity::empty_item_counter>::value ), "atomicity::empty_item_counter is not allowed as a item counter");
310
311             m_Buckets = bucket_table_allocator().NewArray( bucket_count() );
312         }
313
314         /// Clears hash map and destroys it
315         ~MichaelHashMap()
316         {
317             clear();
318             bucket_table_allocator().Delete( m_Buckets, bucket_count() );
319         }
320
321         /// Inserts new node with key and default value
322         /**
323             The function creates a node with \p key and default value, and then inserts the node created into the map.
324
325             Preconditions:
326             - The \ref key_type should be constructible from value of type \p K.
327                 In trivial case, \p K is equal to \ref key_type.
328             - The \ref mapped_type should be default-constructible.
329
330             The function applies RCU lock internally.
331
332             Returns \p true if inserting successful, \p false otherwise.
333         */
334         template <typename K>
335         bool insert( const K& key )
336         {
337             const bool bRet = bucket( key ).insert( key );
338             if ( bRet )
339                 ++m_ItemCounter;
340             return bRet;
341         }
342
343         /// Inserts new node
344         /**
345             The function creates a node with copy of \p val value
346             and then inserts the node created into the map.
347
348             Preconditions:
349             - The \ref key_type should be constructible from \p key of type \p K.
350             - The \ref mapped_type should be constructible from \p val of type \p V.
351
352             The function applies RCU lock internally.
353
354             Returns \p true if \p val is inserted into the map, \p false otherwise.
355         */
356         template <typename K, typename V>
357         bool insert( K const& key, V const& val )
358         {
359             const bool bRet = bucket( key ).insert( key, val );
360             if ( bRet )
361                 ++m_ItemCounter;
362             return bRet;
363         }
364
365         /// Inserts new node and initialize it by a functor
366         /**
367             This function inserts new node with key \p key and if inserting is successful then it calls
368             \p func functor with signature
369             \code
370                 struct functor {
371                     void operator()( value_type& item );
372                 };
373             \endcode
374
375             The argument \p item of user-defined functor \p func is the reference
376             to the map's item inserted:
377                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
378                 - <tt>item.second</tt> is a reference to item's value that may be changed.
379
380             User-defined functor \p func should guarantee that during changing item's value no any other changes
381             could be made on this map's item by concurrent threads.
382             The user-defined functor can be passed by reference using <tt>boost::ref</tt>
383             and it is called only if inserting is successful.
384
385             The key_type should be constructible from value of type \p K.
386
387             The function allows to split creating of new item into two part:
388             - create item from \p key;
389             - insert new item into the map;
390             - if inserting is successful, initialize the value of item by calling \p func functor
391
392             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
393             it is preferable that the initialization should be completed only if inserting is successful.
394
395             The function applies RCU lock internally.
396         */
397         template <typename K, typename Func>
398         bool insert_key( const K& key, Func func )
399         {
400             const bool bRet = bucket( key ).insert_key( key, func );
401             if ( bRet )
402                 ++m_ItemCounter;
403             return bRet;
404         }
405
406
407         /// Ensures that the \p key exists in the map
408         /**
409             The operation performs inserting or changing data with lock-free manner.
410
411             If the \p key not found in the map, then the new item created from \p key
412             is inserted into the map (note that in this case the \ref key_type should be
413             constructible from type \p K).
414             Otherwise, the functor \p func is called with item found.
415             The functor \p Func may be a function with signature:
416             \code
417                 void func( bool bNew, value_type& item );
418             \endcode
419             or a functor:
420             \code
421                 struct my_functor {
422                     void operator()( bool bNew, value_type& item );
423                 };
424             \endcode
425
426             with arguments:
427             - \p bNew - \p true if the item has been inserted, \p false otherwise
428             - \p item - item of the list
429
430             The functor may change any fields of the \p item.second that is \ref mapped_type;
431             however, \p func must guarantee that during changing no any other modifications
432             could be made on this item by concurrent threads.
433
434             You may pass \p func argument by reference using <tt>boost::ref</tt>.
435
436             The function applies RCU lock internally.
437
438             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
439             \p second is true if new item has been added or \p false if the item with \p key
440             already is in the list.
441         */
442         template <typename K, typename Func>
443         std::pair<bool, bool> ensure( K const& key, Func func )
444         {
445             std::pair<bool, bool> bRet = bucket( key ).ensure( key, func );
446             if ( bRet.first && bRet.second )
447                 ++m_ItemCounter;
448             return bRet;
449         }
450
451         /// For key \p key inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
452         /**
453             \p key_type should be constructible from type \p K
454
455             Returns \p true if inserting successful, \p false otherwise.
456         */
457         template <typename K, typename... Args>
458         bool emplace( K&& key, Args&&... args )
459         {
460             const bool bRet = bucket( key ).emplace( std::forward<K>(key), std::forward<Args>(args)... );
461             if ( bRet )
462                 ++m_ItemCounter;
463             return bRet;
464         }
465
466         /// Deletes \p key from the map
467         /** \anchor cds_nonintrusive_MichaelMap_rcu_erase_val
468
469             RCU \p synchronize method can be called. RCU should not be locked.
470
471             Return \p true if \p key is found and deleted, \p false otherwise
472         */
473         template <typename K>
474         bool erase( const K& key )
475         {
476             const bool bRet = bucket( key ).erase( key );
477             if ( bRet )
478                 --m_ItemCounter;
479             return bRet;
480         }
481
482         /// Deletes the item from the map using \p pred predicate for searching
483         /**
484             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_erase_val "erase(K const&)"
485             but \p pred is used for key comparing.
486             \p Less predicate has the interface like \p std::less.
487             \p Less must imply the same element order as the comparator used for building the map.
488         */
489         template <typename K, typename Less>
490         bool erase_with( const K& key, Less pred )
491         {
492             const bool bRet = bucket( key ).erase_with( key, pred );
493             if ( bRet )
494                 --m_ItemCounter;
495             return bRet;
496         }
497
498         /// Deletes \p key from the map
499         /** \anchor cds_nonintrusive_MichaelMap_rcu_erase_func
500
501             The function searches an item with key \p key, calls \p f functor
502             and deletes the item. If \p key is not found, the functor is not called.
503
504             The functor \p Func interface:
505             \code
506             struct extractor {
507                 void operator()(value_type& item) { ... }
508             };
509             \endcode
510             The functor may be passed by reference using <tt>boost:ref</tt>
511
512             RCU \p synchronize method can be called. RCU should not be locked.
513
514             Return \p true if key is found and deleted, \p false otherwise
515         */
516         template <typename K, typename Func>
517         bool erase( const K& key, Func f )
518         {
519             const bool bRet = bucket( key ).erase( key, f );
520             if ( bRet )
521                 --m_ItemCounter;
522             return bRet;
523         }
524
525         /// Deletes the item from the map using \p pred predicate for searching
526         /**
527             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_erase_func "erase(K const&, Func)"
528             but \p pred is used for key comparing.
529             \p Less functor has the interface like \p std::less.
530             \p Less must imply the same element order as the comparator used for building the map.
531         */
532         template <typename K, typename Less, typename Func>
533         bool erase_with( const K& key, Less pred, Func f )
534         {
535             const bool bRet = bucket( key ).erase_with( key, pred, f );
536             if ( bRet )
537                 --m_ItemCounter;
538             return bRet;
539         }
540
541         /// Extracts an item from the map
542         /** \anchor cds_nonintrusive_MichaelHashMap_rcu_extract
543             The function searches an item with key equal to \p key,
544             unlinks it from the map, places item pointer into \p dest argument, and returns \p true.
545             If the item is not found the function return \p false.
546
547             @note The function does NOT call RCU read-side lock or synchronization,
548             and does NOT dispose the item found. It just excludes the item from the map
549             and returns a pointer to item found.
550             You should lock RCU before calling of the function, and you should synchronize RCU
551             outside the RCU lock to free extracted item
552
553             \code
554             #include <cds/urcu/general_buffered.h>
555             #include <cds/container/michael_kvlist_rcu.h>
556             #include <cds/container/michael_map_rcu.h>
557
558             typedef cds::urcu::gc< general_buffered<> > rcu;
559             typedef cds::container::MichaelKVList< rcu, int, Foo > rcu_michael_list;
560             typedef cds::container::MichaelHashMap< rcu, rcu_michael_list, foo_traits > rcu_michael_map;
561
562             rcu_michael_map theMap;
563             // ...
564
565             rcu_michael_map::exempt_ptr p;
566             {
567                 // first, we should lock RCU
568                 rcu_michael_map::rcu_lock lock;
569
570                 // Now, you can apply extract function
571                 // Note that you must not delete the item found inside the RCU lock
572                 if ( theMap.extract( p, 10 )) {
573                     // do something with p
574                     ...
575                 }
576             }
577
578             // We may safely release p here
579             // release() passes the pointer to RCU reclamation cycle
580             p.release();
581             \endcode
582         */
583         template <typename K>
584         bool extract( exempt_ptr& dest, K const& key )
585         {
586             if ( bucket( key ).extract( dest, key )) {
587                 --m_ItemCounter;
588                 return true;
589             }
590             return false;
591         }
592
593         /// Extracts an item from the map using \p pred predicate for searching
594         /**
595             The function is an analog of \ref cds_nonintrusive_MichaelHashMap_rcu_extract "extract(exempt_ptr&, K const&)"
596             but \p pred is used for key comparing.
597             \p Less functor has the interface like \p std::less.
598             \p pred must imply the same element order as the comparator used for building the map.
599         */
600         template <typename K, typename Less>
601         bool extract_with( exempt_ptr& dest, K const& key, Less pred )
602         {
603             if ( bucket( key ).extract_with( dest, key, pred )) {
604                 --m_ItemCounter;
605                 return true;
606             }
607             return false;
608         }
609
610         /// Finds the key \p key
611         /** \anchor cds_nonintrusive_MichaelMap_rcu_find_cfunc
612
613             The function searches the item with key equal to \p key and calls the functor \p f for item found.
614             The interface of \p Func functor is:
615             \code
616             struct functor {
617                 void operator()( value_type& item );
618             };
619             \endcode
620             where \p item is the item found.
621
622             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
623
624             The functor may change \p item.second. Note that the functor is only guarantee
625             that \p item cannot be disposed during functor is executing.
626             The functor does not serialize simultaneous access to the map's \p item. If such access is
627             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
628
629             The function applies RCU lock internally.
630
631             The function returns \p true if \p key is found, \p false otherwise.
632         */
633         template <typename K, typename Func>
634         bool find( K const& key, Func f ) const
635         {
636             return bucket( key ).find( key, f );
637         }
638
639         /// Finds the key \p val using \p pred predicate for searching
640         /**
641             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_find_cfunc "find(K const&, Func)"
642             but \p pred is used for key comparing.
643             \p Less functor has the interface like \p std::less.
644             \p Less must imply the same element order as the comparator used for building the map.
645         */
646         template <typename K, typename Less, typename Func>
647         bool find_with( K const& key, Less pred, Func f ) const
648         {
649             return bucket( key ).find_with( key, pred, f );
650         }
651
652         /// Finds the key \p key
653         /** \anchor cds_nonintrusive_MichaelMap_rcu_find_val
654
655             The function searches the item with key equal to \p key
656             and returns \p true if it is found, and \p false otherwise.
657
658             The function applies RCU lock internally.
659         */
660         template <typename K>
661         bool find( K const& key ) const
662         {
663             return bucket( key ).find( key );
664         }
665
666         /// Finds the key \p val using \p pred predicate for searching
667         /**
668             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_find_val "find(K const&)"
669             but \p pred is used for key comparing.
670             \p Less functor has the interface like \p std::less.
671             \p Less must imply the same element order as the comparator used for building the map.
672         */
673         template <typename K, typename Less>
674         bool find_with( K const& key, Less pred ) const
675         {
676             return bucket( key ).find_with( key, pred );
677         }
678
679         /// Finds \p key and return the item found
680         /** \anchor cds_nonintrusive_MichaelHashMap_rcu_get
681             The function searches the item with key equal to \p key and returns the pointer to item found.
682             If \p key is not found it returns \p nullptr.
683
684             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
685
686             RCU should be locked before call of this function.
687             Returned item is valid only while RCU is locked:
688             \code
689             typedef cds::container::MichaelHashMap< your_template_parameters > hash_map;
690             hash_map theMap;
691             // ...
692             {
693                 // Lock RCU
694                 hash_map::rcu_lock lock;
695
696                 hash_map::value_type * = theMap.get( 5 );
697                 if ( pVal ) {
698                     // Deal with pVal
699                     //...
700                 }
701                 // Unlock RCU by rcu_lock destructor
702                 // pVal can be freed at any time after RCU has been unlocked
703             }
704             \endcode
705         */
706         template <typename K>
707         value_type * get( K const& key ) const
708         {
709             return bucket( key ).get( key );
710         }
711
712         /// Finds \p key and return the item found
713         /**
714             The function is an analog of \ref cds_nonintrusive_MichaelHashMap_rcu_get "get(K const&)"
715             but \p pred is used for comparing the keys.
716
717             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
718             in any order.
719             \p pred must imply the same element order as the comparator used for building the map.
720         */
721         template <typename K, typename Less>
722         value_type * get_with( K const& key, Less pred ) const
723         {
724             return bucket( key ).get_with( key, pred );
725         }
726
727         /// Clears the map (non-atomic)
728         /**
729             The function erases all items from the map.
730
731             The function is not atomic. It cleans up each bucket and then resets the item counter to zero.
732             If there are a thread that performs insertion while \p clear is working the result is undefined in general case:
733             <tt> empty() </tt> may return \p true but the map may contain item(s).
734             Therefore, \p clear may be used only for debugging purposes.
735
736             RCU \p synchronize method can be called. RCU should not be locked.
737         */
738         void clear()
739         {
740             for ( size_t i = 0; i < bucket_count(); ++i )
741                 m_Buckets[i].clear();
742             m_ItemCounter.reset();
743         }
744
745         /// Checks if the map is empty
746         /**
747             Emptiness is checked by item counting: if item count is zero then the map is empty.
748             Thus, the correct item counting is an important part of the map implementation.
749         */
750         bool empty() const
751         {
752             return size() == 0;
753         }
754
755         /// Returns item count in the map
756         size_t size() const
757         {
758             return m_ItemCounter;
759         }
760
761         /// Returns the size of hash table
762         /**
763             Since MichaelHashMap cannot dynamically extend the hash table size,
764             the value returned is an constant depending on object initialization parameters;
765             see MichaelHashMap::MichaelHashMap for explanation.
766         */
767         size_t bucket_count() const
768         {
769             return m_nHashBitmask + 1;
770         }
771     };
772 }}  // namespace cds::container
773
774 #endif // ifndef __CDS_CONTAINER_MICHAEL_MAP_RCU_H