2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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.
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.
31 #ifndef CDSLIB_CONTAINER_MICHAEL_MAP_H
32 #define CDSLIB_CONTAINER_MICHAEL_MAP_H
34 #include <cds/container/details/michael_map_base.h>
35 #include <cds/details/allocator.h>
37 namespace cds { namespace container {
39 /// Michael's hash map
40 /** @ingroup cds_nonintrusive_map
41 \anchor cds_nonintrusive_MichaelHashMap_hp
44 - [2002] Maged Michael "High performance dynamic lock-free hash tables and list-based sets"
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.
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.
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
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>".
75 \anchor cds_nonintrusive_MichaelHashMap_how_touse
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.
81 #include <cds/container/michael_kvlist_hp.h> // MichaelKVList for gc::HP
82 #include <cds/container/michael_map.h> // MichaelHashMap
84 // List traits based on std::less predicate
85 struct list_traits: public cds::container::michael_list::traits
87 typedef std::less<int> less;
91 typedef cds::container::MichaelKVList< cds::gc::HP, int, int, list_traits> int2int_list;
94 struct map_traits: public cds::container::michael_map::traits
97 size_t operator()( int i ) const
99 return cds::opt::v::hash<int>()( i );
105 typedef cds::container::MichaelHashMap< cds::gc::HP, int2int_list, map_traits > int2int_map;
107 // Now you can use int2int_map class
113 theMap.insert( 100 );
118 You may use option-based declaration:
120 #include <cds/container/michael_kvlist_hp.h> // MichaelKVList for gc::HP
121 #include <cds/container/michael_map.h> // MichaelHashMap
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
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> >
141 #ifdef CDS_DOXYGEN_INVOKED
142 class Traits = michael_map::traits
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
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
158 typedef typename bucket_type::key_comparator key_comparator; ///< key compare functor
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
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
168 static CDS_CONSTEXPR const size_t c_nHazardPtrCount = bucket_type::c_nHazardPtrCount; ///< Count of hazard pointer required
171 item_counter m_ItemCounter; ///< Item counter
172 hash m_HashFunctor; ///< Hash functor
173 bucket_type * m_Buckets; ///< bucket table
177 const size_t m_nHashBitmask;
182 /// Calculates hash value of \p key
183 template <typename Q>
184 size_t hash_value( Q const& key ) const
186 return m_HashFunctor( key ) & m_nHashBitmask;
189 /// Returns the bucket (ordered list) for \p key
190 template <typename Q>
191 bucket_type& bucket( Q const& key )
193 return m_Buckets[ hash_value( key ) ];
200 template <bool IsConst>
201 class iterator_type: private cds::intrusive::michael_set::details::iterator< bucket_type, IsConst >
203 typedef cds::intrusive::michael_set::details::iterator< bucket_type, IsConst > base_class;
204 friend class MichaelHashMap;
207 typedef typename base_class::bucket_ptr bucket_ptr;
208 typedef typename base_class::list_iterator list_iterator;
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;
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;
222 iterator_type( list_iterator const& it, bucket_ptr pFirst, bucket_ptr pLast )
223 : base_class( it, pFirst, pLast )
233 iterator_type( const iterator_type& src )
237 /// Dereference operator
238 pair_ptr operator ->() const
240 assert( base_class::m_pCurBucket != nullptr );
241 return base_class::m_itList.operator ->();
244 /// Dereference operator
245 pair_ref operator *() const
247 assert( base_class::m_pCurBucket != nullptr );
248 return base_class::m_itList.operator *();
252 iterator_type& operator ++()
254 base_class::operator++();
258 /// Assignment operator
259 iterator_type& operator = (const iterator_type& src)
261 base_class::operator =(src);
265 /// Returns current bucket (debug function)
266 bucket_ptr bucket() const
268 return base_class::bucket();
271 /// Equality operator
273 bool operator ==(iterator_type<C> const& i )
275 return base_class::operator ==( i );
277 /// Equality operator
279 bool operator !=(iterator_type<C> const& i )
281 return !( *this == i );
287 ///@name Forward iterators (only for debugging purpose)
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.
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.
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).
305 The iterator class supports the following minimalistic interface:
312 iterator( iterator const& s);
314 value_type * operator ->() const;
315 value_type& operator *() const;
318 iterator& operator ++();
321 iterator& operator = (iterator const& src);
323 bool operator ==(iterator const& i ) const;
324 bool operator !=(iterator const& i ) const;
328 @note The iterator object returned by \p end(), \p cend() member functions points to \p nullptr and should not be dereferenced.
330 typedef iterator_type< false > iterator;
332 /// Const forward iterator
333 typedef iterator_type< true > const_iterator;
335 /// Returns a forward iterator addressing the first element in a map
337 For empty map \code begin() == end() \endcode
341 return iterator( m_Buckets[0].begin(), m_Buckets, m_Buckets + bucket_count() );
344 /// Returns an iterator that addresses the location succeeding the last element in a map
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
352 return iterator( m_Buckets[bucket_count() - 1].end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() );
355 /// Returns a forward const iterator addressing the first element in a map
356 const_iterator begin() const
358 return get_const_begin();
360 /// Returns a forward const iterator addressing the first element in a map
361 const_iterator cbegin() const
363 return get_const_begin();
366 /// Returns an const iterator that addresses the location succeeding the last element in a map
367 const_iterator end() const
369 return get_const_end();
371 /// Returns an const iterator that addresses the location succeeding the last element in a map
372 const_iterator cend() const
374 return get_const_end();
380 const_iterator get_const_begin() const
382 return const_iterator( const_cast<bucket_type const&>(m_Buckets[0]).begin(), m_Buckets, m_Buckets + bucket_count() );
384 const_iterator get_const_end() const
386 return const_iterator( const_cast<bucket_type const&>(m_Buckets[bucket_count() - 1]).end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() );
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.
399 The ctor defines hash table size as rounding <tt>nMacItemCount / nLoadFactor</tt> up to nearest power of two.
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 ))
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");
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");
413 m_Buckets = bucket_table_allocator().NewArray( bucket_count() );
416 /// Clears hash map and destroys it
420 bucket_table_allocator().Delete( m_Buckets, bucket_count() );
423 /// Inserts new node with key and default value
425 The function creates a node with \p key and default value, and then inserts the node created into the map.
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.
432 Returns \p true if inserting successful, \p false otherwise.
434 template <typename K>
435 bool insert( const K& key )
437 const bool bRet = bucket( key ).insert( key );
445 The function creates a node with copy of \p val value
446 and then inserts the node created into the map.
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.
452 Returns \p true if \p val is inserted into the map, \p false otherwise.
454 template <typename K, typename V>
455 bool insert( K const& key, V const& val )
457 const bool bRet = bucket( key ).insert( key, val );
463 /// Inserts new node and initialize it by a functor
465 This function inserts new node with key \p key and if inserting is successful then it calls
466 \p func functor with signature
469 void operator()( value_type& item );
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.
478 The user-defined functor is called only if inserting is successful.
480 The \p key_type should be constructible from value of type \p K.
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
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.
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
494 template <typename K, typename Func>
495 bool insert_with( const K& key, Func func )
497 const bool bRet = bucket( key ).insert_with( key, func );
503 /// Updates data by \p key
505 The operation performs inserting or replacing the element with lock-free manner.
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.
512 The functor \p Func signature is:
515 void operator()( bool bNew, value_type& item );
519 - \p bNew - \p true if the item has been inserted, \p false otherwise
520 - \p item - the item found or inserted
522 The functor may change any fields of the \p item.second that is \p mapped_type.
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
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
532 template <typename K, typename Func >
533 std::pair<bool, bool> update( K const& key, Func func, bool bAllowInsert = true )
535 std::pair<bool, bool> bRet = bucket( key ).update( key, func, bAllowInsert );
536 if ( bRet.first && bRet.second )
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 )
545 std::pair<bool, bool> bRet = bucket( key ).update( key, func, true );
546 if ( bRet.first && bRet.second )
552 /// For key \p key inserts data of type \p mapped_type created from \p args
554 \p key_type should be constructible from type \p K
556 Returns \p true if inserting successful, \p false otherwise.
558 template <typename K, typename... Args>
559 bool emplace( K&& key, Args&&... args )
561 const bool bRet = bucket( key ).emplace( std::forward<K>(key), std::forward<Args>(args)... );
567 /// Deletes \p key from the map
568 /** \anchor cds_nonintrusive_MichaelMap_erase_val
570 Return \p true if \p key is found and deleted, \p false otherwise
572 template <typename K>
573 bool erase( K const& key )
575 const bool bRet = bucket( key ).erase( key );
581 /// Deletes the item from the map using \p pred predicate for searching
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.
588 template <typename K, typename Less>
589 bool erase_with( K const& key, Less pred )
591 const bool bRet = bucket( key ).erase_with( key, pred );
597 /// Deletes \p key from the map
598 /** \anchor cds_nonintrusive_MichaelMap_erase_func
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.
603 The functor \p Func interface:
606 void operator()(value_type& item) { ... }
610 Return \p true if key is found and deleted, \p false otherwise
612 template <typename K, typename Func>
613 bool erase( K const& key, Func f )
615 const bool bRet = bucket( key ).erase( key, f );
621 /// Deletes the item from the map using \p pred predicate for searching
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.
628 template <typename K, typename Less, typename Func>
629 bool erase_with( K const& key, Less pred, Func f )
631 const bool bRet = bucket( key ).erase_with( key, pred, f );
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.
643 Note the compare functor should accept a parameter of type \p K that may be not the same as \p key_type.
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.
650 typedef cds::container::MichaelHashMap< your_template_args > michael_map;
654 michael_map::guarded_ptr gp( theMap.extract( 5 ));
659 // Destructor of gp releases internal HP guard
663 template <typename K>
664 guarded_ptr extract( K const& key )
666 guarded_ptr gp( bucket( key ).extract( key ));
672 /// Extracts the item using compare functor \p pred
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.
677 \p Less functor has the semantics like \p std::less but should take arguments of type \p key_type and \p K
679 \p pred must imply the same element order as the comparator used for building the map.
681 template <typename K, typename Less>
682 guarded_ptr extract_with( K const& key, Less pred )
684 guarded_ptr gp( bucket( key ).extract_with( key, pred ));
690 /// Finds the key \p key
691 /** \anchor cds_nonintrusive_MichaelMap_find_cfunc
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:
697 void operator()( value_type& item );
700 where \p item is the item found.
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.
707 The function returns \p true if \p key is found, \p false otherwise.
709 template <typename K, typename Func>
710 bool find( K const& key, Func f )
712 return bucket( key ).find( key, f );
715 /// Finds the key \p val using \p pred predicate for searching
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.
722 template <typename K, typename Less, typename Func>
723 bool find_with( K const& key, Less pred, Func f )
725 return bucket( key ).find_with( key, pred, f );
728 /// Checks whether the map contains \p key
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.
733 template <typename K>
734 bool contains( K const& key )
736 return bucket( key ).contains( key );
739 template <typename K>
740 CDS_DEPRECATED("deprecated, use contains()")
741 bool find( K const& key )
743 return bucket( key ).contains( key );
747 /// Checks whether the map contains \p key using \p pred predicate for searching
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.
753 template <typename K, typename Less>
754 bool contains( K const& key, Less pred )
756 return bucket( key ).contains( key, pred );
759 template <typename K, typename Less>
760 CDS_DEPRECATED("deprecated, use contains()")
761 bool find_with( K const& key, Less pred )
763 return bucket( key ).contains( key, pred );
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,
773 @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
777 typedef cds::container::MichaeHashMap< your_template_params > michael_map;
781 michael_map::guarded_ptr gp( theMap.get( 5 ));
786 // Destructor of guarded_ptr releases internal HP guard
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.
793 template <typename K>
794 guarded_ptr get( K const& key )
796 return bucket( key ).get( key );
799 /// Finds \p key and return the item found
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.
804 \p Less functor has the semantics like \p std::less but should take arguments of type \p key_type and \p K
806 \p pred must imply the same element order as the comparator used for building the map.
808 template <typename K, typename Less>
809 guarded_ptr get_with( K const& key, Less pred )
811 return bucket( key ).get_with( key, pred );
814 /// Clears the map (not atomic)
817 for ( size_t i = 0; i < bucket_count(); ++i )
818 m_Buckets[i].clear();
819 m_ItemCounter.reset();
822 /// Checks if the map is empty
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.
832 /// Returns item count in the map
835 return m_ItemCounter;
838 /// Returns the size of hash table
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.
844 size_t bucket_count() const
846 return m_nHashBitmask + 1;
849 }} // namespace cds::container
851 #endif // ifndef CDSLIB_CONTAINER_MICHAEL_MAP_H