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