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