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