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