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