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