intrusive MultiLevelHashSet:
[libcds.git] / cds / gc / impl / hp_decl.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_GC_IMPL_HP_DECL_H
4 #define CDSLIB_GC_IMPL_HP_DECL_H
5
6 #include <stdexcept>    // overflow_error
7 #include <cds/gc/details/hp.h>
8 #include <cds/details/marked_ptr.h>
9
10 namespace cds { namespace gc {
11     /// @defgroup cds_garbage_collector Garbage collectors
12
13     /// Hazard Pointer garbage collector
14     /**  @ingroup cds_garbage_collector
15         @headerfile cds/gc/hp.h
16
17         Implementation of classic Hazard Pointer garbage collector.
18
19         Sources:
20             - [2002] Maged M.Michael "Safe memory reclamation for dynamic lock-freeobjects using atomic reads and writes"
21             - [2003] Maged M.Michael "Hazard Pointers: Safe memory reclamation for lock-free objects"
22             - [2004] Andrei Alexandrescy, Maged Michael "Lock-free Data Structures with Hazard Pointers"
23
24         Hazard Pointer garbage collector is a singleton. The main user-level part of Hazard Pointer schema is
25         GC class \p %cds::gc::HP and its nested classes. Before use any HP-related class you must initialize HP garbage collector
26         by contructing \p %cds::gc::HP object in beginning of your \p main().
27         See \ref cds_how_to_use "How to use" section for details how to apply garbage collector.
28     */
29     class HP
30     {
31     public:
32         /// Native guarded pointer type
33         /**
34             @headerfile cds/gc/hp.h
35         */
36         typedef gc::hp::hazard_pointer guarded_pointer;
37
38         /// Atomic reference
39         /**
40             @headerfile cds/gc/hp.h
41         */
42         template <typename T> using atomic_ref = atomics::atomic<T *>;
43
44         /// Atomic marked pointer
45         /**
46             @headerfile cds/gc/hp.h
47         */
48         template <typename MarkedPtr> using atomic_marked_ptr = atomics::atomic<MarkedPtr>;
49
50         /// Atomic type
51         /**
52             @headerfile cds/gc/hp.h
53         */
54         template <typename T> using atomic_type = atomics::atomic<T>;
55
56         /// Thread GC implementation for internal usage
57         /**
58             @headerfile cds/gc/hp.h
59         */
60         typedef hp::ThreadGC   thread_gc_impl;
61
62         /// Wrapper for hp::ThreadGC class
63         /**
64             @headerfile cds/gc/hp.h
65             This class performs automatically attaching/detaching Hazard Pointer GC
66             for the current thread.
67         */
68         class thread_gc: public thread_gc_impl
69         {
70             //@cond
71             bool    m_bPersistent;
72             //@endcond
73         public:
74
75             /// Constructor
76             /**
77                 The constructor attaches the current thread to the Hazard Pointer GC
78                 if it is not yet attached.
79                 The \p bPersistent parameter specifies attachment persistence:
80                 - \p true - the class destructor will not detach the thread from Hazard Pointer GC.
81                 - \p false (default) - the class destructor will detach the thread from Hazard Pointer GC.
82             */
83             thread_gc(
84                 bool    bPersistent = false
85             ) ;     //inline in hp_impl.h
86
87             /// Destructor
88             /**
89                 If the object has been created in persistent mode, the destructor does nothing.
90                 Otherwise it detaches the current thread from Hazard Pointer GC.
91             */
92             ~thread_gc() ;  // inline in hp_impl.h
93
94         public: // for internal use only!!!
95             //@cond
96             static cds::gc::hp::details::hp_guard& alloc_guard(); // inline in hp_impl.h
97             static void free_guard( cds::gc::hp::details::hp_guard& g ); // inline in hp_impl.h
98             //@endcond
99         };
100
101         /// Hazard Pointer guard
102         /**
103             @headerfile cds/gc/hp.h
104
105             A guard is the hazard pointer.
106             Additionally, the \p %Guard class manages allocation and deallocation of the hazard pointer
107
108             A \p %Guard object is not copy- and move-constructible
109             and not copy- and move-assignable.
110         */
111         class Guard : public hp::guard
112         {
113             //@cond
114             typedef hp::guard base_class;
115             //@endcond
116
117         public:
118             /// Default ctor
119             Guard()
120             {}
121
122             //@cond
123             Guard( Guard const& ) = delete;
124             Guard( Guard&& s ) = delete;
125             Guard& operator=(Guard const&) = delete;
126             Guard& operator=(Guard&&) = delete;
127             //@endcond
128
129             /// Protects a pointer of type \p atomic<T*>
130             /**
131                 Return the value of \p toGuard
132
133                 The function tries to load \p toGuard and to store it
134                 to the HP slot repeatedly until the guard's value equals \p toGuard
135             */
136             template <typename T>
137             T protect( atomics::atomic<T> const& toGuard )
138             {
139                 T pCur = toGuard.load(atomics::memory_order_acquire);
140                 T pRet;
141                 do {
142                     pRet = assign( pCur );
143                     pCur = toGuard.load(atomics::memory_order_acquire);
144                 } while ( pRet != pCur );
145                 return pCur;
146             }
147
148             /// Protects a converted pointer of type \p atomic<T*>
149             /**
150                 Return the value of \p toGuard
151
152                 The function tries to load \p toGuard and to store result of \p f functor
153                 to the HP slot repeatedly until the guard's value equals \p toGuard.
154
155                 The function is useful for intrusive containers when \p toGuard is a node pointer
156                 that should be converted to a pointer to the value before protecting.
157                 The parameter \p f of type Func is a functor that makes this conversion:
158                 \code
159                     struct functor {
160                         value_type * operator()( T * p );
161                     };
162                 \endcode
163                 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
164             */
165             template <typename T, class Func>
166             T protect( atomics::atomic<T> const& toGuard, Func f )
167             {
168                 T pCur = toGuard.load(atomics::memory_order_acquire);
169                 T pRet;
170                 do {
171                     pRet = pCur;
172                     assign( f( pCur ) );
173                     pCur = toGuard.load(atomics::memory_order_acquire);
174                 } while ( pRet != pCur );
175                 return pCur;
176             }
177
178             /// Store \p p to the guard
179             /**
180                 The function equals to a simple assignment the value \p p to guard, no loop is performed.
181                 Can be used for a pointer that cannot be changed concurrently
182             */
183             template <typename T>
184             T * assign( T * p );    // inline in hp_impl.h
185
186             //@cond
187             std::nullptr_t assign( std::nullptr_t )
188             {
189                 return base_class::operator =(nullptr);
190             }
191             //@endcond
192
193             /// Copy from \p src guard to \p this guard
194             void copy( Guard const& src )
195             {
196                 assign( src.get_native() );
197             }
198
199             /// Store marked pointer \p p to the guard
200             /**
201                 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
202                 Can be used for a marked pointer that cannot be changed concurrently.
203             */
204             template <typename T, int BITMASK>
205             T * assign( cds::details::marked_ptr<T, BITMASK> p )
206             {
207                 return base_class::operator =( p.ptr() );
208             }
209
210             /// Clear value of the guard
211             void clear()
212             {
213                 assign( nullptr );
214             }
215
216             /// Get the value currently protected
217             template <typename T>
218             T * get() const
219             {
220                 return reinterpret_cast<T *>( get_native() );
221             }
222
223             /// Get native hazard pointer stored
224             guarded_pointer get_native() const
225             {
226                 return base_class::get();
227             }
228         };
229
230         /// Array of Hazard Pointer guards
231         /**
232             @headerfile cds/gc/hp.h
233             The class is intended for allocating an array of hazard pointer guards.
234             Template parameter \p Count defines the size of the array.
235
236             A \p %GuardArray object is not copy- and move-constructible
237             and not copy- and move-assignable.
238         */
239         template <size_t Count>
240         class GuardArray : public hp::array<Count>
241         {
242             //@cond
243             typedef hp::array<Count> base_class;
244             //@endcond
245         public:
246             /// Rebind array for other size \p Count2
247             template <size_t Count2>
248             struct rebind {
249                 typedef GuardArray<Count2>  other   ;   ///< rebinding result
250             };
251
252         public:
253             /// Default ctor
254             GuardArray()
255             {}
256
257             //@cond
258             GuardArray( GuardArray const& ) = delete;
259             GuardArray( GuardArray&& ) = delete;
260             GuardArray& operator=(GuardArray const&) = delete;
261             GuardArray& operator=(GuardArray&&) = delete;
262             //@endcond
263
264             /// Protects a pointer of type \p atomic<T*>
265             /**
266                 Return the value of \p toGuard
267
268                 The function tries to load \p toGuard and to store it
269                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
270             */
271             template <typename T>
272             T protect( size_t nIndex, atomics::atomic<T> const& toGuard )
273             {
274                 T pRet;
275                 do {
276                     pRet = assign( nIndex, toGuard.load(atomics::memory_order_acquire) );
277                 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
278
279                 return pRet;
280             }
281
282             /// Protects a pointer of type \p atomic<T*>
283             /**
284                 Return the value of \p toGuard
285
286                 The function tries to load \p toGuard and to store it
287                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
288
289                 The function is useful for intrusive containers when \p toGuard is a node pointer
290                 that should be converted to a pointer to the value type before guarding.
291                 The parameter \p f of type Func is a functor that makes this conversion:
292                 \code
293                     struct functor {
294                         value_type * operator()( T * p );
295                     };
296                 \endcode
297                 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
298             */
299             template <typename T, class Func>
300             T protect( size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
301             {
302                 T pRet;
303                 do {
304                     assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_acquire) ));
305                 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
306
307                 return pRet;
308             }
309
310             /// Store \p to the slot \p nIndex
311             /**
312                 The function equals to a simple assignment, no loop is performed.
313             */
314             template <typename T>
315             T * assign( size_t nIndex, T * p ); // inline in hp_impl.h
316
317             /// Store marked pointer \p p to the guard
318             /**
319                 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
320                 Can be used for a marked pointer that cannot be changed concurrently.
321             */
322             template <typename T, int BITMASK>
323             T * assign( size_t nIndex, cds::details::marked_ptr<T, BITMASK> p )
324             {
325                 return assign( nIndex, p.ptr() );
326             }
327
328             /// Copy guarded value from \p src guard to slot at index \p nIndex
329             void copy( size_t nIndex, Guard const& src )
330             {
331                 assign( nIndex, src.get_native() );
332             }
333
334             /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
335             void copy( size_t nDestIndex, size_t nSrcIndex )
336             {
337                 assign( nDestIndex, get_native( nSrcIndex ));
338             }
339
340             /// Clear value of the slot \p nIndex
341             void clear( size_t nIndex )
342             {
343                 base_class::clear( nIndex );
344             }
345
346             /// Get current value of slot \p nIndex
347             template <typename T>
348             T * get( size_t nIndex ) const
349             {
350                 return reinterpret_cast<T *>( get_native( nIndex ) );
351             }
352
353             /// Get native hazard pointer stored
354             guarded_pointer get_native( size_t nIndex ) const
355             {
356                 return base_class::operator[](nIndex).get();
357             }
358
359             /// Capacity of the guard array
360             static CDS_CONSTEXPR size_t capacity()
361             {
362                 return Count;
363             }
364         };
365
366         /// Guarded pointer
367         /**
368             A guarded pointer is a pair of a pointer and GC's guard.
369             Usually, it is used for returning a pointer to the item from an lock-free container.
370             The guard prevents the pointer to be early disposed (freed) by GC.
371             After destructing \p %guarded_ptr object the pointer can be disposed (freed) automatically at any time.
372
373             Template arguments:
374             - \p GuardedType - a type which the guard stores
375             - \p ValueType - a value type
376             - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
377
378             For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
379             In such case the \p %guarded_ptr is:
380             @code
381             typedef cds::gc::HP::guarded_ptr< foo > intrusive_guarded_ptr;
382             @endcode
383
384             For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
385             For example:
386             @code
387             struct foo {
388                 int const   key;
389                 std::string value;
390             };
391
392             struct value_accessor {
393                 std::string* operator()( foo* pFoo ) const
394                 {
395                     return &(pFoo->value);
396                 }
397             };
398
399             // Guarded ptr
400             typedef cds::gc::HP::guarded_ptr< Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
401             @endcode
402
403             You don't need use this class directly.
404             All set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
405         */
406         template <typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
407         class guarded_ptr
408         {
409             //@cond
410             struct trivial_cast {
411                 ValueType * operator()( GuardedType * p ) const
412                 {
413                     return p;
414                 }
415             };
416             //@endcond
417
418         public:
419             typedef GuardedType guarded_type; ///< Guarded type
420             typedef ValueType   value_type;   ///< Value type
421
422             /// Functor for casting \p guarded_type to \p value_type
423             typedef typename std::conditional< std::is_same<Cast, void>::value, trivial_cast, Cast >::type value_cast;
424
425             //@cond
426             typedef cds::gc::hp::details::hp_guard native_guard;
427             //@endcond
428
429         private:
430             //@cond
431             native_guard *  m_pGuard;
432             //@endcond
433
434         public:
435             /// Creates empty guarded pointer
436             guarded_ptr() CDS_NOEXCEPT
437                 : m_pGuard(nullptr)
438             {
439                 alloc_guard();
440             }
441
442             //@cond
443             /// Initializes guarded pointer with \p p
444             explicit guarded_ptr( guarded_type * p ) CDS_NOEXCEPT
445                 : m_pGuard( nullptr )
446             {
447                 reset(p);
448             }
449             explicit guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
450                 : m_pGuard( nullptr )
451             {}
452             //@endcond
453
454             /// Move ctor
455             guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
456                 : m_pGuard( gp.m_pGuard )
457             {
458                 gp.m_pGuard = nullptr;
459             }
460
461             /// The guarded pointer is not copy-constructible
462             guarded_ptr( guarded_ptr const& gp ) = delete;
463
464             /// Clears the guarded pointer
465             /**
466                 \ref release is called if guarded pointer is not \ref empty
467             */
468             ~guarded_ptr() CDS_NOEXCEPT
469             {
470                 free_guard();
471             }
472
473             /// Move-assignment operator
474             guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
475             {
476                 // Hazard Pointer array is organized as a stack
477                 if ( m_pGuard && m_pGuard > gp.m_pGuard ) {
478                     m_pGuard->set( gp.m_pGuard->get(atomics::memory_order_relaxed) );
479                     gp.free_guard();
480                 }
481                 else {
482                     free_guard();
483                     m_pGuard = gp.m_pGuard;
484                     gp.m_pGuard = nullptr;
485                 }
486                 return *this;
487             }
488
489             /// The guarded pointer is not copy-assignable
490             guarded_ptr& operator=(guarded_ptr const& gp) = delete;
491
492             /// Returns a pointer to guarded value
493             value_type * operator ->() const CDS_NOEXCEPT
494             {
495                 assert( !empty() );
496                 return value_cast()( reinterpret_cast<guarded_type *>(m_pGuard->get()));
497             }
498
499             /// Returns a reference to guarded value
500             value_type& operator *() CDS_NOEXCEPT
501             {
502                 assert( !empty());
503                 return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
504             }
505
506             /// Returns const reference to guarded value
507             value_type const& operator *() const CDS_NOEXCEPT
508             {
509                 assert( !empty() );
510                 return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
511             }
512
513             /// Checks if the guarded pointer is \p nullptr
514             bool empty() const CDS_NOEXCEPT
515             {
516                 return !m_pGuard || m_pGuard->get( atomics::memory_order_relaxed ) == nullptr;
517             }
518
519             /// \p bool operator returns <tt>!empty()</tt>
520             explicit operator bool() const CDS_NOEXCEPT
521             {
522                 return !empty();
523             }
524
525             /// Clears guarded pointer
526             /**
527                 If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
528                 Dereferncing the guarded pointer after \p release() is dangerous.
529             */
530             void release() CDS_NOEXCEPT
531             {
532                 free_guard();
533             }
534
535             //@cond
536             // For internal use only!!!
537             native_guard& guard() CDS_NOEXCEPT
538             {
539                 alloc_guard();
540                 assert( m_pGuard );
541                 return *m_pGuard;
542             }
543
544             void reset(guarded_type * p) CDS_NOEXCEPT
545             {
546                 alloc_guard();
547                 assert( m_pGuard );
548                 m_pGuard->set(p);
549             }
550             //@endcond
551
552         private:
553             //@cond
554             void alloc_guard()
555             {
556                 if ( !m_pGuard )
557                     m_pGuard = &thread_gc::alloc_guard();
558             }
559
560             void free_guard()
561             {
562                 if ( m_pGuard ) {
563                     thread_gc::free_guard( *m_pGuard );
564                     m_pGuard = nullptr;
565                 }
566             }
567             //@endcond
568         };
569
570     public:
571         /// \p scan() type
572         enum class scan_type {
573             classic = hp::classic,    ///< classic scan as described in Michael's papers
574             inplace = hp::inplace     ///< inplace scan without allocation
575         };
576         /// Initializes %HP singleton
577         /**
578             The constructor initializes GC singleton with passed parameters.
579             If GC instance is not exist then the function creates the instance.
580             Otherwise it does nothing.
581
582             The Michael's %HP reclamation schema depends of three parameters:
583             - \p nHazardPtrCount - hazard pointer count per thread. Usually it is small number (up to 10) depending from
584                 the data structure algorithms. By default, if \p nHazardPtrCount = 0, the function
585                 uses maximum of the hazard pointer count for CDS library.
586             - \p nMaxThreadCount - max count of thread with using Hazard Pointer GC in your application. Default is 100.
587             - \p nMaxRetiredPtrCount - capacity of array of retired pointers for each thread. Must be greater than
588                 <tt> nHazardPtrCount * nMaxThreadCount </tt>. Default is <tt>2 * nHazardPtrCount * nMaxThreadCount </tt>.
589         */
590         HP(
591             size_t nHazardPtrCount = 0,     ///< Hazard pointer count per thread
592             size_t nMaxThreadCount = 0,     ///< Max count of simultaneous working thread in your application
593             size_t nMaxRetiredPtrCount = 0, ///< Capacity of the array of retired objects for the thread
594             scan_type nScanType = scan_type::inplace   ///< Scan type (see \p scan_type enum)
595         )
596         {
597             hp::GarbageCollector::Construct(
598                 nHazardPtrCount,
599                 nMaxThreadCount,
600                 nMaxRetiredPtrCount,
601                 static_cast<hp::scan_type>(nScanType)
602             );
603         }
604
605         /// Terminates GC singleton
606         /**
607             The destructor destroys %HP global object. After calling of this function you may \b NOT
608             use CDS data structures based on \p %cds::gc::HP. 
609             Usually, %HP object is destroyed at the end of your \p main().
610         */
611         ~HP()
612         {
613             hp::GarbageCollector::Destruct( true );
614         }
615
616         /// Checks if count of hazard pointer is no less than \p nCountNeeded
617         /**
618             If \p bRaiseException is \p true (that is the default), the function raises
619             an \p std::overflow_error exception "Too few hazard pointers"
620             if \p nCountNeeded is more than the count of hazard pointer per thread.
621         */
622         static bool check_available_guards( size_t nCountNeeded, bool bRaiseException = true )
623         {
624             if ( hp::GarbageCollector::instance().getHazardPointerCount() < nCountNeeded ) {
625                 if ( bRaiseException )
626                     throw std::overflow_error( "Too few hazard pointers" );
627                 return false;
628             }
629             return true;
630         }
631
632         /// Returns max Hazard Pointer count
633         static size_t max_hazard_count()
634         {
635             return hp::GarbageCollector::instance().getHazardPointerCount();
636         }
637
638         /// Returns max count of thread
639         static size_t max_thread_count()
640         {
641             return hp::GarbageCollector::instance().getMaxThreadCount();
642         }
643
644         /// Returns capacity of retired pointer array
645         static size_t retired_array_capacity()
646         {
647             return hp::GarbageCollector::instance().getMaxRetiredPtrCount();
648         }
649
650         /// Retire pointer \p p with function \p pFunc
651         /**
652             The function places pointer \p p to array of pointers ready for removing.
653             (so called retired pointer array). The pointer can be safely removed when no hazard pointer points to it.
654             Deleting the pointer is the function \p pFunc call.
655         */
656         template <typename T>
657         static void retire( T * p, void (* pFunc)(T *) );   // inline in hp_impl.h
658
659         /// Retire pointer \p p with functor of type \p Disposer
660         /**
661             The function places pointer \p p to array of pointers ready for removing.
662             (so called retired pointer array). The pointer can be safely removed when no hazard pointer points to it.
663
664             Deleting the pointer is an invocation of some object of type \p Disposer; the interface of \p Disposer is:
665             \code
666             template <typename T>
667             struct disposer {
668                 void operator()( T * p )    ;   // disposing operator
669             };
670             \endcode
671             Since the functor call can happen at any time after \p retire call, additional restrictions are imposed to \p Disposer type:
672             - it should be stateless functor
673             - it should be default-constructible
674             - the result of functor call with argument \p p should not depend on where the functor will be called.
675
676             \par Examples:
677             Operator \p delete functor:
678             \code
679             template <typename T>
680             struct disposer {
681                 void operator ()( T * p ) {
682                     delete p;
683                 }
684             };
685
686             // How to call GC::retire method
687             int * p = new int;
688
689             // ... use p in lock-free manner
690
691             cds::gc::HP::retire<disposer>( p ) ;   // place p to retired pointer array of HP GC
692             \endcode
693
694             Functor based on \p std::allocator :
695             \code
696             template <typename ALLOC = std::allocator<int> >
697             struct disposer {
698                 template <typename T>
699                 void operator()( T * p ) {
700                     typedef typename ALLOC::templare rebind<T>::other   alloc_t;
701                     alloc_t a;
702                     a.destroy( p );
703                     a.deallocate( p, 1 );
704                 }
705             };
706             \endcode
707         */
708         template <class Disposer, typename T>
709         static void retire( T * p );   // inline in hp_impl.h
710
711         /// Get current scan strategy
712         static scan_type getScanType()
713         {
714             return static_cast<scan_type>( hp::GarbageCollector::instance().getScanType());
715         }
716
717         /// Set current scan strategy
718         static void setScanType(
719             scan_type nScanType     ///< new scan strategy
720         )
721         {
722             hp::GarbageCollector::instance().setScanType( static_cast<hp::scan_type>(nScanType) );
723         }
724
725         /// Checks if Hazard Pointer GC is constructed and may be used
726         static bool isUsed()
727         {
728             return hp::GarbageCollector::isUsed();
729         }
730
731         /// Forced GC cycle call for current thread
732         /**
733             Usually, this function should not be called directly.
734         */
735         static void scan()  ;   // inline in hp_impl.h
736
737         /// Synonym for \ref scan()
738         static void force_dispose()
739         {
740             scan();
741         }
742     };
743 }}  // namespace cds::gc
744
745 #endif  // #ifndef CDSLIB_GC_IMPL_HP_DECL_H