4af31da7bb913320a006c262a2e458854a97d1b0
[libcds.git] / cds / container / michael_map.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_CONTAINER_MICHAEL_MAP_H
4 #define CDSLIB_CONTAINER_MICHAEL_MAP_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
12     /** @ingroup cds_nonintrusive_map
13         \anchor cds_nonintrusive_MichaelHashMap_hp
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 GC - Garbage collector used. You may use any \ref cds_garbage_collector "Garbage collector"
25             from the \p libcds library.
26             Note the \p GC must be the same as the GC used for \p OrderedList
27         - \p OrderedList - ordered key-value list implementation used as bucket for hash map, for example, \p MichaelKVList
28             or \p LazyKVList. The ordered list implementation specifies the \p Key and \p Value types stored in the hash-map,
29             the reclamation schema \p GC used by hash-map, the comparison functor for the type \p Key and other features
30             specific for the ordered list.
31         - \p Traits - map traits, default is \p michael_map::traits.
32             Instead of defining \p Traits struct you may use option-based syntax with \p michael_map::make_traits metafunction.
33
34         Many of the class function take a key argument of type \p K that in general is not \p key_type.
35         \p key_type and an argument of template type \p K must meet the following requirements:
36         - \p key_type should be constructible from value of type \p K;
37         - the hash functor should be able to calculate correct hash value from argument \p key of type \p K:
38             <tt> hash( key_type(key) ) == hash( key ) </tt>
39         - values of type \p key_type and \p K should be comparable
40
41         There are the specializations:
42         - for \ref cds_urcu_desc "RCU" - declared in <tt>cds/container/michael_map_rcu.h</tt>,
43             see \ref cds_nonintrusive_MichaelHashMap_rcu "MichaelHashMap<RCU>".
44         - for \p cds::gc::nogc declared in <tt>cds/container/michael_map_nogc.h</tt>,
45             see \ref cds_nonintrusive_MichaelHashMap_nogc "MichaelHashMap<gc::nogc>".
46
47         <b>Iterators</b>
48
49         The class supports a forward iterator (\ref iterator and \ref const_iterator).
50         The iteration is unordered.
51         The iterator object is thread-safe: the element pointed by the iterator object is guarded,
52         so, the element cannot be reclaimed while the iterator object is alive.
53         However, passing an iterator object between threads is dangerous.
54
55         @warning Due to concurrent nature of Michael's set it is not guarantee that you can iterate
56         all elements in the set: any concurrent deletion can exclude the element
57         pointed by the iterator from the set, and your iteration can be terminated
58         before end of the set. Therefore, such iteration is more suitable for debugging purpose only
59
60         Remember, each iterator object requires an additional hazard pointer, that may be
61         a limited resource for \p GC like \p gc::HP (for \p gc::DHP the count of
62         guards is unlimited).
63
64         The iterator class supports the following minimalistic interface:
65         \code
66         struct iterator {
67         // Default ctor
68         iterator();
69
70         // Copy ctor
71         iterator( iterator const& s);
72
73         value_type * operator ->() const;
74         value_type& operator *() const;
75
76         // Pre-increment
77         iterator& operator ++();
78
79         // Copy assignment
80         iterator& operator = (const iterator& src);
81
82         bool operator ==(iterator const& i ) const;
83         bool operator !=(iterator const& i ) const;
84         };
85         \endcode
86         Note, the iterator object returned by \ref end, \p cend member functions points to \p nullptr and should not be dereferenced.
87
88         \anchor cds_nonintrusive_MichaelHashMap_how_touse
89         <b>How to use</b>
90
91         Suppose, you want to make \p int to \p int map for Hazard Pointer garbage collector. You should
92         choose suitable ordered list class that will be used as a bucket for the map; it may be \p MichaelKVList.
93         \code
94         #include <cds/container/michael_kvlist_hp.h>    // MichaelKVList for gc::HP
95         #include <cds/container/michael_map.h>          // MichaelHashMap
96
97         // List traits based on std::less predicate
98         struct list_traits: public cds::container::michael_list::traits
99         {
100             typedef std::less<int>      less;
101         };
102
103         // Ordered list
104         typedef cds::container::MichaelKVList< cds::gc::HP, int, int, list_traits> int2int_list;
105
106         // Map traits
107         struct map_traits: public cds::container::michael_map::traits
108         {
109             struct hash {
110                 size_t operator()( int i ) const
111                 {
112                     return cds::opt::v::hash<int>()( i );
113                 }
114             }
115         };
116
117         // Your map
118         typedef cds::container::MichaelHashMap< cds::gc::HP, int2int_list, map_traits > int2int_map;
119
120         // Now you can use int2int_map class
121
122         int main()
123         {
124             int2int_map theMap;
125
126             theMap.insert( 100 );
127             ...
128         }
129         \endcode
130
131         You may use option-based declaration:
132         \code
133         #include <cds/container/michael_kvlist_hp.h>    // MichaelKVList for gc::HP
134         #include <cds/container/michael_map.h>          // MichaelHashMap
135
136         // Ordered list
137         typedef cds::container::MichaelKVList< cds::gc::HP, int, int,
138             typename cds::container::michael_list::make_traits<
139                 cds::container::opt::less< std::less<int> >     // item comparator option
140             >::type
141         >  int2int_list;
142
143         // Map
144         typedef cds::container::MichaelHashMap< cds::gc::HP, int2int_list,
145             cds::container::michael_map::make_traits<
146                 cc::opt::hash< cds::opt::v::hash<int> >
147             >
148         > int2int_map;
149         \endcode
150     */
151     template <
152         class GC,
153         class OrderedList,
154 #ifdef CDS_DOXYGEN_INVOKED
155         class Traits = michael_map::traits
156 #else
157         class Traits
158 #endif
159     >
160     class MichaelHashMap
161     {
162     public:
163         typedef GC          gc;          ///< Garbage collector
164         typedef OrderedList bucket_type; ///< type of ordered list to be used as a bucket
165         typedef Traits      traits;      ///< Map traits
166
167         typedef typename bucket_type::key_type    key_type;    ///< key type
168         typedef typename bucket_type::mapped_type mapped_type; ///< value type
169         typedef typename bucket_type::value_type  value_type;  ///< key/value pair stored in the map
170
171         typedef typename bucket_type::key_comparator key_comparator;  ///< key compare functor
172
173         /// Hash functor for \ref key_type and all its derivatives that you use
174         typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash;
175         typedef typename traits::item_counter  item_counter;   ///< Item counter type
176
177         /// Bucket table allocator
178         typedef cds::details::Allocator< bucket_type, typename traits::allocator >  bucket_table_allocator;
179         typedef typename bucket_type::guarded_ptr  guarded_ptr; ///< Guarded pointer
180
181     protected:
182         item_counter    m_ItemCounter; ///< Item counter
183         hash            m_HashFunctor; ///< Hash functor
184         bucket_type *   m_Buckets;     ///< bucket table
185
186     private:
187         //@cond
188         const size_t    m_nHashBitmask;
189         //@endcond
190
191     protected:
192         //@cond
193         /// Calculates hash value of \p key
194         template <typename Q>
195         size_t hash_value( Q const& key ) const
196         {
197             return m_HashFunctor( key ) & m_nHashBitmask;
198         }
199
200         /// Returns the bucket (ordered list) for \p key
201         template <typename Q>
202         bucket_type&    bucket( Q const& key )
203         {
204             return m_Buckets[ hash_value( key ) ];
205         }
206         //@endcond
207
208     protected:
209         //@cond
210         /// Forward iterator
211         template <bool IsConst>
212         class iterator_type: private cds::intrusive::michael_set::details::iterator< bucket_type, IsConst >
213         {
214             typedef cds::intrusive::michael_set::details::iterator< bucket_type, IsConst >  base_class;
215             friend class MichaelHashMap;
216
217         protected:
218             typedef typename base_class::bucket_ptr     bucket_ptr;
219             typedef typename base_class::list_iterator  list_iterator;
220
221         public:
222             /// Value pointer type (const for const_iterator)
223             typedef typename cds::details::make_const_type<typename MichaelHashMap::mapped_type, IsConst>::pointer   value_ptr;
224             /// Value reference type (const for const_iterator)
225             typedef typename cds::details::make_const_type<typename MichaelHashMap::mapped_type, IsConst>::reference value_ref;
226
227             /// Key-value pair pointer type (const for const_iterator)
228             typedef typename cds::details::make_const_type<typename MichaelHashMap::value_type, IsConst>::pointer   pair_ptr;
229             /// Key-value pair reference type (const for const_iterator)
230             typedef typename cds::details::make_const_type<typename MichaelHashMap::value_type, IsConst>::reference pair_ref;
231
232         protected:
233             iterator_type( list_iterator const& it, bucket_ptr pFirst, bucket_ptr pLast )
234                 : base_class( it, pFirst, pLast )
235             {}
236
237         public:
238             /// Default ctor
239             iterator_type()
240                 : base_class()
241             {}
242
243             /// Copy ctor
244             iterator_type( const iterator_type& src )
245                 : base_class( src )
246             {}
247
248             /// Dereference operator
249             pair_ptr operator ->() const
250             {
251                 assert( base_class::m_pCurBucket != nullptr );
252                 return base_class::m_itList.operator ->();
253             }
254
255             /// Dereference operator
256             pair_ref operator *() const
257             {
258                 assert( base_class::m_pCurBucket != nullptr );
259                 return base_class::m_itList.operator *();
260             }
261
262             /// Pre-increment
263             iterator_type& operator ++()
264             {
265                 base_class::operator++();
266                 return *this;
267             }
268
269             /// Assignment operator
270             iterator_type& operator = (const iterator_type& src)
271             {
272                 base_class::operator =(src);
273                 return *this;
274             }
275
276             /// Returns current bucket (debug function)
277             bucket_ptr bucket() const
278             {
279                 return base_class::bucket();
280             }
281
282             /// Equality operator
283             template <bool C>
284             bool operator ==(iterator_type<C> const& i )
285             {
286                 return base_class::operator ==( i );
287             }
288             /// Equality operator
289             template <bool C>
290             bool operator !=(iterator_type<C> const& i )
291             {
292                 return !( *this == i );
293             }
294         };
295         //@endcond
296
297     public:
298         /// Forward iterator
299         typedef iterator_type< false >    iterator;
300
301         /// Const forward iterator
302         typedef iterator_type< true >     const_iterator;
303
304         /// Returns a forward iterator addressing the first element in a map
305         /**
306             For empty map \code begin() == end() \endcode
307         */
308         iterator begin()
309         {
310             return iterator( m_Buckets[0].begin(), m_Buckets, m_Buckets + bucket_count() );
311         }
312
313         /// Returns an iterator that addresses the location succeeding the last element in a map
314         /**
315             Do not use the value returned by <tt>end</tt> function to access any item.
316             The returned value can be used only to control reaching the end of the map.
317             For empty map \code begin() == end() \endcode
318         */
319         iterator end()
320         {
321             return iterator( m_Buckets[bucket_count() - 1].end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() );
322         }
323
324         /// Returns a forward const iterator addressing the first element in a map
325         //@{
326         const_iterator begin() const
327         {
328             return get_const_begin();
329         }
330         const_iterator cbegin() const
331         {
332             return get_const_begin();
333         }
334         //@}
335
336         /// Returns an const iterator that addresses the location succeeding the last element in a map
337         //@{
338         const_iterator end() const
339         {
340             return get_const_end();
341         }
342         const_iterator cend() const
343         {
344             return get_const_end();
345         }
346         //@}
347
348     private:
349         //@cond
350         const_iterator get_const_begin() const
351         {
352             return const_iterator( const_cast<bucket_type const&>(m_Buckets[0]).begin(), m_Buckets, m_Buckets + bucket_count() );
353         }
354         const_iterator get_const_end() const
355         {
356             return const_iterator( const_cast<bucket_type const&>(m_Buckets[bucket_count() - 1]).end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() );
357         }
358         //@endcond
359
360     public:
361         /// Initializes the map
362         /** @anchor cds_nonintrusive_MichaelHashMap_hp_ctor
363             The Michael's hash map is non-expandable container. You should point the average count of items \p nMaxItemCount
364             when you create an object.
365             \p nLoadFactor parameter defines average count of items per bucket and it should be small number between 1 and 10.
366             Remember, since the bucket implementation is an ordered list, searching in the bucket is linear [<tt>O(nLoadFactor)</tt>].
367             Note, that many popular STL hash map implementation uses load factor 1.
368
369             The ctor defines hash table size as rounding <tt>nMacItemCount / nLoadFactor</tt> up to nearest power of two.
370         */
371         MichaelHashMap(
372             size_t nMaxItemCount,   ///< estimation of max item count in the hash map
373             size_t nLoadFactor      ///< load factor: estimation of max number of items in the bucket
374         ) : m_nHashBitmask( michael_map::details::init_hash_bitmask( nMaxItemCount, nLoadFactor ))
375         {
376             // GC and OrderedList::gc must be the same
377             static_assert( std::is_same<gc, typename bucket_type::gc>::value, "GC and OrderedList::gc must be the same");
378
379             // atomicity::empty_item_counter is not allowed as a item counter
380             static_assert( !std::is_same<item_counter, atomicity::empty_item_counter>::value,
381                            "atomicity::empty_item_counter is not allowed as a item counter");
382
383             m_Buckets = bucket_table_allocator().NewArray( bucket_count() );
384         }
385
386         /// Clears hash map and destroys it
387         ~MichaelHashMap()
388         {
389             clear();
390             bucket_table_allocator().Delete( m_Buckets, bucket_count() );
391         }
392
393         /// Inserts new node with key and default value
394         /**
395             The function creates a node with \p key and default value, and then inserts the node created into the map.
396
397             Preconditions:
398             - The \p key_type should be constructible from value of type \p K.
399                 In trivial case, \p K is equal to \p key_type.
400             - The \p mapped_type should be default-constructible.
401
402             Returns \p true if inserting successful, \p false otherwise.
403         */
404         template <typename K>
405         bool insert( const K& key )
406         {
407             const bool bRet = bucket( key ).insert( key );
408             if ( bRet )
409                 ++m_ItemCounter;
410             return bRet;
411         }
412
413         /// Inserts new node
414         /**
415             The function creates a node with copy of \p val value
416             and then inserts the node created into the map.
417
418             Preconditions:
419             - The \p key_type should be constructible from \p key of type \p K.
420             - The \p mapped_type should be constructible from \p val of type \p V.
421
422             Returns \p true if \p val is inserted into the map, \p false otherwise.
423         */
424         template <typename K, typename V>
425         bool insert( K const& key, V const& val )
426         {
427             const bool bRet = bucket( key ).insert( key, val );
428             if ( bRet )
429                 ++m_ItemCounter;
430             return bRet;
431         }
432
433         /// Inserts new node and initialize it by a functor
434         /**
435             This function inserts new node with key \p key and if inserting is successful then it calls
436             \p func functor with signature
437             \code
438                 struct functor {
439                     void operator()( value_type& item );
440                 };
441             \endcode
442
443             The argument \p item of user-defined functor \p func is the reference
444             to the map's item inserted:
445                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
446                 - <tt>item.second</tt> is a reference to item's value that may be changed.
447
448             The user-defined functor is called only if inserting is successful.
449
450             The \p key_type should be constructible from value of type \p K.
451
452             The function allows to split creating of new item into two part:
453             - create item from \p key;
454             - insert new item into the map;
455             - if inserting is successful, initialize the value of item by calling \p func functor
456
457             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
458             it is preferable that the initialization should be completed only if inserting is successful.
459
460             @warning For \ref cds_nonintrusive_MichaelKVList_gc "MichaelKVList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
461             \ref cds_nonintrusive_LazyKVList_gc "LazyKVList" provides exclusive access to inserted item and does not require any node-level
462             synchronization.
463         */
464         template <typename K, typename Func>
465         bool insert_with( const K& key, Func func )
466         {
467             const bool bRet = bucket( key ).insert_with( key, func );
468             if ( bRet )
469                 ++m_ItemCounter;
470             return bRet;
471         }
472
473         /// Updates data by \p key
474         /**
475             The operation performs inserting or replacing the element with lock-free manner.
476
477             If the \p key not found in the map, then the new item created from \p key
478             will be inserted into the map iff \p bAllowInsert is \p true.
479             (note that in this case the \ref key_type should be constructible from type \p K).
480             Otherwise, if \p key is found, the functor \p func is called with item found.
481
482             The functor \p Func signature is:
483             \code
484                 struct my_functor {
485                     void operator()( bool bNew, value_type& item );
486                 };
487             \endcode
488             with arguments:
489             - \p bNew - \p true if the item has been inserted, \p false otherwise
490             - \p item - the item found or inserted
491
492             The functor may change any fields of the \p item.second that is \p mapped_type.
493
494             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
495             \p second is true if new item has been added or \p false if the item with \p key
496             already exists.
497
498             @warning For \ref cds_nonintrusive_MichaelKVList_gc "MichaelKVList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting".
499             \ref cds_nonintrusive_LazyKVList_gc "LazyKVList" provides exclusive access to inserted item and does not require any node-level
500             synchronization.
501         */
502         template <typename K, typename Func >
503         std::pair<bool, bool> update( K const& key, Func func, bool bAllowInsert = true )
504         {
505             std::pair<bool, bool> bRet = bucket( key ).update( key, func, bAllowInsert );
506             if ( bRet.first && bRet.second )
507                 ++m_ItemCounter;
508             return bRet;
509         }
510         //@cond
511         template <typename K, typename Func>
512         CDS_DEPRECATED("ensure() is deprecated, use update()")
513         std::pair<bool, bool> ensure( K const& key, Func func )
514         {
515             std::pair<bool, bool> bRet = bucket( key ).update( key, func, true );
516             if ( bRet.first && bRet.second )
517                 ++m_ItemCounter;
518             return bRet;
519         }
520         //@endcond
521
522         /// For key \p key inserts data of type \p mapped_type created from \p args
523         /**
524             \p key_type should be constructible from type \p K
525
526             Returns \p true if inserting successful, \p false otherwise.
527         */
528         template <typename K, typename... Args>
529         bool emplace( K&& key, Args&&... args )
530         {
531             const bool bRet = bucket( key ).emplace( std::forward<K>(key), std::forward<Args>(args)... );
532             if ( bRet )
533                 ++m_ItemCounter;
534             return bRet;
535         }
536
537         /// Deletes \p key from the map
538         /** \anchor cds_nonintrusive_MichaelMap_erase_val
539
540             Return \p true if \p key is found and deleted, \p false otherwise
541         */
542         template <typename K>
543         bool erase( K const& key )
544         {
545             const bool bRet = bucket( key ).erase( key );
546             if ( bRet )
547                 --m_ItemCounter;
548             return bRet;
549         }
550
551         /// Deletes the item from the map using \p pred predicate for searching
552         /**
553             The function is an analog of \ref cds_nonintrusive_MichaelMap_erase_val "erase(K const&)"
554             but \p pred is used for key comparing.
555             \p Less functor has the interface like \p std::less.
556             \p Less must imply the same element order as the comparator used for building the map.
557         */
558         template <typename K, typename Less>
559         bool erase_with( K const& key, Less pred )
560         {
561             const bool bRet = bucket( key ).erase_with( key, pred );
562             if ( bRet )
563                 --m_ItemCounter;
564             return bRet;
565         }
566
567         /// Deletes \p key from the map
568         /** \anchor cds_nonintrusive_MichaelMap_erase_func
569
570             The function searches an item with key \p key, calls \p f functor
571             and deletes the item. If \p key is not found, the functor is not called.
572
573             The functor \p Func interface:
574             \code
575             struct extractor {
576                 void operator()(value_type& item) { ... }
577             };
578             \endcode
579
580             Return \p true if key is found and deleted, \p false otherwise
581         */
582         template <typename K, typename Func>
583         bool erase( K const& key, Func f )
584         {
585             const bool bRet = bucket( key ).erase( key, f );
586             if ( bRet )
587                 --m_ItemCounter;
588             return bRet;
589         }
590
591         /// Deletes the item from the map using \p pred predicate for searching
592         /**
593             The function is an analog of \ref cds_nonintrusive_MichaelMap_erase_func "erase(K const&, Func)"
594             but \p pred is used for key comparing.
595             \p Less functor has the interface like \p std::less.
596             \p Less must imply the same element order as the comparator used for building the map.
597         */
598         template <typename K, typename Less, typename Func>
599         bool erase_with( K const& key, Less pred, Func f )
600         {
601             const bool bRet = bucket( key ).erase_with( key, pred, f );
602             if ( bRet )
603                 --m_ItemCounter;
604             return bRet;
605         }
606
607         /// Extracts the item with specified \p key
608         /** \anchor cds_nonintrusive_MichaelHashMap_hp_extract
609             The function searches an item with key equal to \p key,
610             unlinks it from the set, and returns it as \p guarded_ptr.
611             If \p key is not found the function returns an empty guarded pointer.
612
613             Note the compare functor should accept a parameter of type \p K that may be not the same as \p key_type.
614
615             The extracted item is freed automatically when returned \p guarded_ptr object will be destroyed or released.
616             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
617
618             Usage:
619             \code
620             typedef cds::container::MichaelHashMap< your_template_args > michael_map;
621             michael_map theMap;
622             // ...
623             {
624                 michael_map::guarded_ptr gp( theMap.extract( 5 ));
625                 if ( gp ) {
626                     // Deal with gp
627                     // ...
628                 }
629                 // Destructor of gp releases internal HP guard
630             }
631             \endcode
632         */
633         template <typename K>
634         guarded_ptr extract( K const& key )
635         {
636             guarded_ptr gp( bucket( key ).extract( key ));
637             if ( gp )
638                 --m_ItemCounter;
639             return gp;
640         }
641
642         /// Extracts the item using compare functor \p pred
643         /**
644             The function is an analog of \ref cds_nonintrusive_MichaelHashMap_hp_extract "extract(K const&)"
645             but \p pred predicate is used for key comparing.
646
647             \p Less functor has the semantics like \p std::less but should take arguments of type \p key_type and \p K
648             in any order.
649             \p pred must imply the same element order as the comparator used for building the map.
650         */
651         template <typename K, typename Less>
652         guarded_ptr extract_with( K const& key, Less pred )
653         {
654             guarded_ptr gp( bucket( key ).extract_with( key, pred ));
655             if ( gp )
656                 --m_ItemCounter;
657             return gp;
658         }
659
660         /// Finds the key \p key
661         /** \anchor cds_nonintrusive_MichaelMap_find_cfunc
662
663             The function searches the item with key equal to \p key and calls the functor \p f for item found.
664             The interface of \p Func functor is:
665             \code
666             struct functor {
667                 void operator()( value_type& item );
668             };
669             \endcode
670             where \p item is the item found.
671
672             The functor may change \p item.second. Note that the functor is only guarantee
673             that \p item cannot be disposed during functor is executing.
674             The functor does not serialize simultaneous access to the map's \p item. If such access is
675             possible you must provide your own synchronization schema on item level to exclude unsafe item modifications.
676
677             The function returns \p true if \p key is found, \p false otherwise.
678         */
679         template <typename K, typename Func>
680         bool find( K const& key, Func f )
681         {
682             return bucket( key ).find( key, f );
683         }
684
685         /// Finds the key \p val using \p pred predicate for searching
686         /**
687             The function is an analog of \ref cds_nonintrusive_MichaelMap_find_cfunc "find(K const&, Func)"
688             but \p pred is used for key comparing.
689             \p Less functor has the interface like \p std::less.
690             \p Less must imply the same element order as the comparator used for building the map.
691         */
692         template <typename K, typename Less, typename Func>
693         bool find_with( K const& key, Less pred, Func f )
694         {
695             return bucket( key ).find_with( key, pred, f );
696         }
697
698         /// Checks whether the map contains \p key
699         /**
700             The function searches the item with key equal to \p key
701             and returns \p true if it is found, and \p false otherwise.
702         */
703         template <typename K>
704         bool contains( K const& key )
705         {
706             return bucket( key ).contains( key );
707         }
708         //@cond
709         template <typename K>
710         CDS_DEPRECATED("deprecated, use contains()")
711         bool find( K const& key )
712         {
713             return bucket( key ).contains( key );
714         }
715         //@endcond
716
717         /// Checks whether the map contains \p key using \p pred predicate for searching
718         /**
719             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
720             \p Less functor has the interface like \p std::less.
721             \p Less must imply the same element order as the comparator used for building the map.
722         */
723         template <typename K, typename Less>
724         bool contains( K const& key, Less pred )
725         {
726             return bucket( key ).contains( key, pred );
727         }
728         //@cond
729         template <typename K, typename Less>
730         CDS_DEPRECATED("deprecated, use contains()")
731         bool find_with( K const& key, Less pred )
732         {
733             return bucket( key ).contains( key, pred );
734         }
735         //@endcond
736
737         /// Finds \p key and return the item found
738         /** \anchor cds_nonintrusive_MichaelHashMap_hp_get
739             The function searches the item with key equal to \p key
740             and returns the guarded pointer to the item found.
741             If \p key is not found the function returns an empty guarded pointer,
742
743             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
744
745             Usage:
746             \code
747             typedef cds::container::MichaeHashMap< your_template_params >  michael_map;
748             michael_map theMap;
749             // ...
750             {
751                 michael_map::guarded_ptr gp( theMap.get( 5 ));
752                 if ( gp ) {
753                     // Deal with gp
754                     //...
755                 }
756                 // Destructor of guarded_ptr releases internal HP guard
757             }
758             \endcode
759
760             Note the compare functor specified for \p OrderedList template parameter
761             should accept a parameter of type \p K that can be not the same as \p key_type.
762         */
763         template <typename K>
764         guarded_ptr get( K const& key )
765         {
766             return bucket( key ).get( key );
767         }
768
769         /// Finds \p key and return the item found
770         /**
771             The function is an analog of \ref cds_nonintrusive_MichaelHashMap_hp_get "get( K const&)"
772             but \p pred is used for comparing the keys.
773
774             \p Less functor has the semantics like \p std::less but should take arguments of type \p key_type and \p K
775             in any order.
776             \p pred must imply the same element order as the comparator used for building the map.
777         */
778         template <typename K, typename Less>
779         guarded_ptr get_with( K const& key, Less pred )
780         {
781             return bucket( key ).get_with( key, pred );
782         }
783
784         /// Clears the map (not atomic)
785         void clear()
786         {
787             for ( size_t i = 0; i < bucket_count(); ++i )
788                 m_Buckets[i].clear();
789             m_ItemCounter.reset();
790         }
791
792         /// Checks if the map is empty
793         /**
794             Emptiness is checked by item counting: if item count is zero then the map is empty.
795             Thus, the correct item counting is an important part of the map implementation.
796         */
797         bool empty() const
798         {
799             return size() == 0;
800         }
801
802         /// Returns item count in the map
803         size_t size() const
804         {
805             return m_ItemCounter;
806         }
807
808         /// Returns the size of hash table
809         /**
810             Since \p %MichaelHashMap cannot dynamically extend the hash table size,
811             the value returned is an constant depending on object initialization parameters;
812             see \p MichaelHashMap::MichaelHashMap for explanation.
813         */
814         size_t bucket_count() const
815         {
816             return m_nHashBitmask + 1;
817         }
818     };
819 }}  // namespace cds::container
820
821 #endif // ifndef CDSLIB_CONTAINER_MICHAEL_MAP_H