eaabe3979b13a50c9cda7360ec1dabbb2b34dc8e
[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/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 != null_ptr<bucket_ptr>() );
182                 return base_class::m_itList.operator ->();
183             }
184
185             /// Dereference operator
186             pair_ref operator *() const
187             {
188                 assert( base_class::m_pCurBucket != null_ptr<bucket_ptr>() );
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 #   ifdef CDS_EMPLACE_SUPPORT
452         /// For key \p key inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
453         /**
454             \p key_type should be constructible from type \p K
455
456             Returns \p true if inserting successful, \p false otherwise.
457
458             The function applies RCU lock internally.
459
460             @note This function is available only for compiler that supports
461             variadic template and move semantics
462         */
463         template <typename K, typename... Args>
464         bool emplace( K&& key, Args&&... args )
465         {
466             const bool bRet = bucket( key ).emplace( std::forward<K>(key), std::forward<Args>(args)... );
467             if ( bRet )
468                 ++m_ItemCounter;
469             return bRet;
470         }
471 #   endif
472
473         /// Deletes \p key from the map
474         /** \anchor cds_nonintrusive_MichaelMap_rcu_erase_val
475
476             RCU \p synchronize method can be called. RCU should not be locked.
477
478             Return \p true if \p key is found and deleted, \p false otherwise
479         */
480         template <typename K>
481         bool erase( const K& key )
482         {
483             const bool bRet = bucket( key ).erase( key );
484             if ( bRet )
485                 --m_ItemCounter;
486             return bRet;
487         }
488
489         /// Deletes the item from the map using \p pred predicate for searching
490         /**
491             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_erase_val "erase(K const&)"
492             but \p pred is used for key comparing.
493             \p Less predicate has the interface like \p std::less.
494             \p Less must imply the same element order as the comparator used for building the map.
495         */
496         template <typename K, typename Less>
497         bool erase_with( const K& key, Less pred )
498         {
499             const bool bRet = bucket( key ).erase_with( key, pred );
500             if ( bRet )
501                 --m_ItemCounter;
502             return bRet;
503         }
504
505         /// Deletes \p key from the map
506         /** \anchor cds_nonintrusive_MichaelMap_rcu_erase_func
507
508             The function searches an item with key \p key, calls \p f functor
509             and deletes the item. If \p key is not found, the functor is not called.
510
511             The functor \p Func interface:
512             \code
513             struct extractor {
514                 void operator()(value_type& item) { ... }
515             };
516             \endcode
517             The functor may be passed by reference using <tt>boost:ref</tt>
518
519             RCU \p synchronize method can be called. RCU should not be locked.
520
521             Return \p true if key is found and deleted, \p false otherwise
522         */
523         template <typename K, typename Func>
524         bool erase( const K& key, Func f )
525         {
526             const bool bRet = bucket( key ).erase( key, f );
527             if ( bRet )
528                 --m_ItemCounter;
529             return bRet;
530         }
531
532         /// Deletes the item from the map using \p pred predicate for searching
533         /**
534             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_erase_func "erase(K const&, Func)"
535             but \p pred is used for key comparing.
536             \p Less functor has the interface like \p std::less.
537             \p Less must imply the same element order as the comparator used for building the map.
538         */
539         template <typename K, typename Less, typename Func>
540         bool erase_with( const K& key, Less pred, Func f )
541         {
542             const bool bRet = bucket( key ).erase_with( key, pred, f );
543             if ( bRet )
544                 --m_ItemCounter;
545             return bRet;
546         }
547
548         /// Extracts an item from the map
549         /** \anchor cds_nonintrusive_MichaelHashMap_rcu_extract
550             The function searches an item with key equal to \p key,
551             unlinks it from the map, places item pointer into \p dest argument, and returns \p true.
552             If the item is not found the function return \p false.
553
554             @note The function does NOT call RCU read-side lock or synchronization,
555             and does NOT dispose the item found. It just excludes the item from the map
556             and returns a pointer to item found.
557             You should lock RCU before calling of the function, and you should synchronize RCU
558             outside the RCU lock to free extracted item
559
560             \code
561             #include <cds/urcu/general_buffered.h>
562             #include <cds/container/michael_kvlist_rcu.h>
563             #include <cds/container/michael_map_rcu.h>
564
565             typedef cds::urcu::gc< general_buffered<> > rcu;
566             typedef cds::container::MichaelKVList< rcu, int, Foo > rcu_michael_list;
567             typedef cds::container::MichaelHashMap< rcu, rcu_michael_list, foo_traits > rcu_michael_map;
568
569             rcu_michael_map theMap;
570             // ...
571
572             rcu_michael_map::exempt_ptr p;
573             {
574                 // first, we should lock RCU
575                 rcu_michael_map::rcu_lock lock;
576
577                 // Now, you can apply extract function
578                 // Note that you must not delete the item found inside the RCU lock
579                 if ( theMap.extract( p, 10 )) {
580                     // do something with p
581                     ...
582                 }
583             }
584
585             // We may safely release p here
586             // release() passes the pointer to RCU reclamation cycle
587             p.release();
588             \endcode
589         */
590         template <typename K>
591         bool extract( exempt_ptr& dest, K const& key )
592         {
593             if ( bucket( key ).extract( dest, key )) {
594                 --m_ItemCounter;
595                 return true;
596             }
597             return false;
598         }
599
600         /// Extracts an item from the map using \p pred predicate for searching
601         /**
602             The function is an analog of \ref cds_nonintrusive_MichaelHashMap_rcu_extract "extract(exempt_ptr&, K const&)"
603             but \p pred is used for key comparing.
604             \p Less functor has the interface like \p std::less.
605             \p pred must imply the same element order as the comparator used for building the map.
606         */
607         template <typename K, typename Less>
608         bool extract_with( exempt_ptr& dest, K const& key, Less pred )
609         {
610             if ( bucket( key ).extract_with( dest, key, pred )) {
611                 --m_ItemCounter;
612                 return true;
613             }
614             return false;
615         }
616
617         /// Finds the key \p key
618         /** \anchor cds_nonintrusive_MichaelMap_rcu_find_cfunc
619
620             The function searches the item with key equal to \p key and calls the functor \p f for item found.
621             The interface of \p Func functor is:
622             \code
623             struct functor {
624                 void operator()( value_type& item );
625             };
626             \endcode
627             where \p item is the item found.
628
629             You may pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
630
631             The functor may change \p item.second. Note that the functor is only guarantee
632             that \p item cannot be disposed during functor is executing.
633             The functor does not serialize simultaneous access to the map's \p item. If such access is
634             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
635
636             The function applies RCU lock internally.
637
638             The function returns \p true if \p key is found, \p false otherwise.
639         */
640         template <typename K, typename Func>
641         bool find( K const& key, Func f ) const
642         {
643             return bucket( key ).find( key, f );
644         }
645
646         /// Finds the key \p val using \p pred predicate for searching
647         /**
648             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_find_cfunc "find(K const&, Func)"
649             but \p pred is used for key comparing.
650             \p Less functor has the interface like \p std::less.
651             \p Less must imply the same element order as the comparator used for building the map.
652         */
653         template <typename K, typename Less, typename Func>
654         bool find_with( K const& key, Less pred, Func f ) const
655         {
656             return bucket( key ).find_with( key, pred, f );
657         }
658
659         /// Finds the key \p key
660         /** \anchor cds_nonintrusive_MichaelMap_rcu_find_val
661
662             The function searches the item with key equal to \p key
663             and returns \p true if it is found, and \p false otherwise.
664
665             The function applies RCU lock internally.
666         */
667         template <typename K>
668         bool find( K const& key ) const
669         {
670             return bucket( key ).find( key );
671         }
672
673         /// Finds the key \p val using \p pred predicate for searching
674         /**
675             The function is an analog of \ref cds_nonintrusive_MichaelMap_rcu_find_val "find(K const&)"
676             but \p pred is used for key comparing.
677             \p Less functor has the interface like \p std::less.
678             \p Less must imply the same element order as the comparator used for building the map.
679         */
680         template <typename K, typename Less>
681         bool find_with( K const& key, Less pred ) const
682         {
683             return bucket( key ).find_with( key, pred );
684         }
685
686         /// Finds \p key and return the item found
687         /** \anchor cds_nonintrusive_MichaelHashMap_rcu_get
688             The function searches the item with key equal to \p key and returns the pointer to item found.
689             If \p key is not found it returns \p NULL.
690
691             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
692
693             RCU should be locked before call of this function.
694             Returned item is valid only while RCU is locked:
695             \code
696             typedef cds::container::MichaelHashMap< your_template_parameters > hash_map;
697             hash_map theMap;
698             // ...
699             {
700                 // Lock RCU
701                 hash_map::rcu_lock lock;
702
703                 hash_map::value_type * = theMap.get( 5 );
704                 if ( pVal ) {
705                     // Deal with pVal
706                     //...
707                 }
708                 // Unlock RCU by rcu_lock destructor
709                 // pVal can be freed at any time after RCU has been unlocked
710             }
711             \endcode
712         */
713         template <typename K>
714         value_type * get( K const& key ) const
715         {
716             return bucket( key ).get( key );
717         }
718
719         /// Finds \p key and return the item found
720         /**
721             The function is an analog of \ref cds_nonintrusive_MichaelHashMap_rcu_get "get(K const&)"
722             but \p pred is used for comparing the keys.
723
724             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
725             in any order.
726             \p pred must imply the same element order as the comparator used for building the map.
727         */
728         template <typename K, typename Less>
729         value_type * get_with( K const& key, Less pred ) const
730         {
731             return bucket( key ).get_with( key, pred );
732         }
733
734         /// Clears the map (non-atomic)
735         /**
736             The function erases all items from the map.
737
738             The function is not atomic. It cleans up each bucket and then resets the item counter to zero.
739             If there are a thread that performs insertion while \p clear is working the result is undefined in general case:
740             <tt> empty() </tt> may return \p true but the map may contain item(s).
741             Therefore, \p clear may be used only for debugging purposes.
742
743             RCU \p synchronize method can be called. RCU should not be locked.
744         */
745         void clear()
746         {
747             for ( size_t i = 0; i < bucket_count(); ++i )
748                 m_Buckets[i].clear();
749             m_ItemCounter.reset();
750         }
751
752         /// Checks if the map is empty
753         /**
754             Emptiness is checked by item counting: if item count is zero then the map is empty.
755             Thus, the correct item counting is an important part of the map implementation.
756         */
757         bool empty() const
758         {
759             return size() == 0;
760         }
761
762         /// Returns item count in the map
763         size_t size() const
764         {
765             return m_ItemCounter;
766         }
767
768         /// Returns the size of hash table
769         /**
770             Since MichaelHashMap cannot dynamically extend the hash table size,
771             the value returned is an constant depending on object initialization parameters;
772             see MichaelHashMap::MichaelHashMap for explanation.
773         */
774         size_t bucket_count() const
775         {
776             return m_nHashBitmask + 1;
777         }
778     };
779 }}  // namespace cds::container
780
781 #endif // ifndef __CDS_CONTAINER_MICHAEL_MAP_RCU_H