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