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