Modified Hazard Pointer SMR to conform C++11 memory model more strictly
[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
440             //@cond
441             /// Initializes guarded pointer with \p p
442             explicit guarded_ptr( guarded_type * p ) CDS_NOEXCEPT
443             {
444                 alloc_guard();
445                 assert( m_pGuard );
446                 m_pGuard->set(p);
447             }
448             explicit guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
449                 : m_pGuard( nullptr )
450             {}
451             //@endcond
452
453             /// Move ctor
454             guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
455                 : m_pGuard( gp.m_pGuard )
456             {
457                 gp.m_pGuard = nullptr;
458             }
459
460             /// The guarded pointer is not copy-constructible
461             guarded_ptr( guarded_ptr const& gp ) = delete;
462
463             /// Clears the guarded pointer
464             /**
465                 \ref release is called if guarded pointer is not \ref empty
466             */
467             ~guarded_ptr() CDS_NOEXCEPT
468             {
469                 free_guard();
470             }
471
472             /// Move-assignment operator
473             guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
474             {
475                 // Hazard Pointer array is organized as a stack
476                 if ( m_pGuard && m_pGuard > gp.m_pGuard ) {
477                     m_pGuard->set( gp.m_pGuard->get(atomics::memory_order_relaxed) );
478                     gp.free_guard();
479                 }
480                 else {
481                     free_guard();
482                     m_pGuard = gp.m_pGuard;
483                     gp.m_pGuard = nullptr;
484                 }
485                 return *this;
486             }
487
488             /// The guarded pointer is not copy-assignable
489             guarded_ptr& operator=(guarded_ptr const& gp) = delete;
490
491             /// Returns a pointer to guarded value
492             value_type * operator ->() const CDS_NOEXCEPT
493             {
494                 assert( !empty() );
495                 return value_cast()( reinterpret_cast<guarded_type *>(m_pGuard->get()));
496             }
497
498             /// Returns a reference to guarded value
499             value_type& operator *() CDS_NOEXCEPT
500             {
501                 assert( !empty());
502                 return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
503             }
504
505             /// Returns const reference to guarded value
506             value_type const& operator *() const CDS_NOEXCEPT
507             {
508                 assert( !empty() );
509                 return *value_cast()(reinterpret_cast<guarded_type *>(m_pGuard->get()));
510             }
511
512             /// Checks if the guarded pointer is \p nullptr
513             bool empty() const CDS_NOEXCEPT
514             {
515                 return !m_pGuard || m_pGuard->get( atomics::memory_order_relaxed ) == nullptr;
516             }
517
518             /// \p bool operator returns <tt>!empty()</tt>
519             explicit operator bool() const CDS_NOEXCEPT
520             {
521                 return !empty();
522             }
523
524             /// Clears guarded pointer
525             /**
526                 If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
527                 Dereferncing the guarded pointer after \p release() is dangerous.
528             */
529             void release() CDS_NOEXCEPT
530             {
531                 free_guard();
532             }
533
534             //@cond
535             // For internal use only!!!
536             native_guard& guard() CDS_NOEXCEPT
537             {
538                 alloc_guard();
539                 assert( m_pGuard );
540                 return *m_pGuard;
541             }
542             //@endcond
543
544         private:
545             //@cond
546             void alloc_guard()
547             {
548                 if ( !m_pGuard )
549                     m_pGuard = &thread_gc::alloc_guard();
550             }
551
552             void free_guard()
553             {
554                 if ( m_pGuard ) {
555                     thread_gc::free_guard( *m_pGuard );
556                     m_pGuard = nullptr;
557                 }
558             }
559             //@endcond
560         };
561
562     public:
563         /// \p scan() type
564         enum class scan_type {
565             classic = hp::classic,    ///< classic scan as described in Michael's papers
566             inplace = hp::inplace     ///< inplace scan without allocation
567         };
568         /// Initializes %HP singleton
569         /**
570             The constructor initializes GC singleton with passed parameters.
571             If GC instance is not exist then the function creates the instance.
572             Otherwise it does nothing.
573
574             The Michael's %HP reclamation schema depends of three parameters:
575             - \p nHazardPtrCount - hazard pointer count per thread. Usually it is small number (up to 10) depending from
576                 the data structure algorithms. By default, if \p nHazardPtrCount = 0, the function
577                 uses maximum of the hazard pointer count for CDS library.
578             - \p nMaxThreadCount - max count of thread with using Hazard Pointer GC in your application. Default is 100.
579             - \p nMaxRetiredPtrCount - capacity of array of retired pointers for each thread. Must be greater than
580                 <tt> nHazardPtrCount * nMaxThreadCount </tt>. Default is <tt>2 * nHazardPtrCount * nMaxThreadCount </tt>.
581         */
582         HP(
583             size_t nHazardPtrCount = 0,     ///< Hazard pointer count per thread
584             size_t nMaxThreadCount = 0,     ///< Max count of simultaneous working thread in your application
585             size_t nMaxRetiredPtrCount = 0, ///< Capacity of the array of retired objects for the thread
586             scan_type nScanType = scan_type::inplace   ///< Scan type (see \p scan_type enum)
587         )
588         {
589             hp::GarbageCollector::Construct(
590                 nHazardPtrCount,
591                 nMaxThreadCount,
592                 nMaxRetiredPtrCount,
593                 static_cast<hp::scan_type>(nScanType)
594             );
595         }
596
597         /// Terminates GC singleton
598         /**
599             The destructor destroys %HP global object. After calling of this function you may \b NOT
600             use CDS data structures based on \p %cds::gc::HP. 
601             Usually, %HP object is destroyed at the end of your \p main().
602         */
603         ~HP()
604         {
605             hp::GarbageCollector::Destruct( true );
606         }
607
608         /// Checks if count of hazard pointer is no less than \p nCountNeeded
609         /**
610             If \p bRaiseException is \p true (that is the default), the function raises
611             an \p std::overflow_error exception "Too few hazard pointers"
612             if \p nCountNeeded is more than the count of hazard pointer per thread.
613         */
614         static bool check_available_guards( size_t nCountNeeded, bool bRaiseException = true )
615         {
616             if ( hp::GarbageCollector::instance().getHazardPointerCount() < nCountNeeded ) {
617                 if ( bRaiseException )
618                     throw std::overflow_error( "Too few hazard pointers" );
619                 return false;
620             }
621             return true;
622         }
623
624         /// Returns max Hazard Pointer count
625         static size_t max_hazard_count()
626         {
627             return hp::GarbageCollector::instance().getHazardPointerCount();
628         }
629
630         /// Returns max count of thread
631         static size_t max_thread_count()
632         {
633             return hp::GarbageCollector::instance().getMaxThreadCount();
634         }
635
636         /// Returns capacity of retired pointer array
637         static size_t retired_array_capacity()
638         {
639             return hp::GarbageCollector::instance().getMaxRetiredPtrCount();
640         }
641
642         /// Retire pointer \p p with function \p pFunc
643         /**
644             The function places pointer \p p to array of pointers ready for removing.
645             (so called retired pointer array). The pointer can be safely removed when no hazard pointer points to it.
646             Deleting the pointer is the function \p pFunc call.
647         */
648         template <typename T>
649         static void retire( T * p, void (* pFunc)(T *) );   // inline in hp_impl.h
650
651         /// Retire pointer \p p with functor of type \p Disposer
652         /**
653             The function places pointer \p p to array of pointers ready for removing.
654             (so called retired pointer array). The pointer can be safely removed when no hazard pointer points to it.
655
656             Deleting the pointer is an invocation of some object of type \p Disposer; the interface of \p Disposer is:
657             \code
658             template <typename T>
659             struct disposer {
660                 void operator()( T * p )    ;   // disposing operator
661             };
662             \endcode
663             Since the functor call can happen at any time after \p retire call, additional restrictions are imposed to \p Disposer type:
664             - it should be stateless functor
665             - it should be default-constructible
666             - the result of functor call with argument \p p should not depend on where the functor will be called.
667
668             \par Examples:
669             Operator \p delete functor:
670             \code
671             template <typename T>
672             struct disposer {
673                 void operator ()( T * p ) {
674                     delete p;
675                 }
676             };
677
678             // How to call GC::retire method
679             int * p = new int;
680
681             // ... use p in lock-free manner
682
683             cds::gc::HP::retire<disposer>( p ) ;   // place p to retired pointer array of HP GC
684             \endcode
685
686             Functor based on \p std::allocator :
687             \code
688             template <typename ALLOC = std::allocator<int> >
689             struct disposer {
690                 template <typename T>
691                 void operator()( T * p ) {
692                     typedef typename ALLOC::templare rebind<T>::other   alloc_t;
693                     alloc_t a;
694                     a.destroy( p );
695                     a.deallocate( p, 1 );
696                 }
697             };
698             \endcode
699         */
700         template <class Disposer, typename T>
701         static void retire( T * p );   // inline in hp_impl.h
702
703         /// Get current scan strategy
704         static scan_type getScanType()
705         {
706             return static_cast<scan_type>( hp::GarbageCollector::instance().getScanType());
707         }
708
709         /// Set current scan strategy
710         static void setScanType(
711             scan_type nScanType     ///< new scan strategy
712         )
713         {
714             hp::GarbageCollector::instance().setScanType( static_cast<hp::scan_type>(nScanType) );
715         }
716
717         /// Checks if Hazard Pointer GC is constructed and may be used
718         static bool isUsed()
719         {
720             return hp::GarbageCollector::isUsed();
721         }
722
723         /// Forced GC cycle call for current thread
724         /**
725             Usually, this function should not be called directly.
726         */
727         static void scan()  ;   // inline in hp_impl.h
728
729         /// Synonym for \ref scan()
730         static void force_dispose()
731         {
732             scan();
733         }
734     };
735 }}  // namespace cds::gc
736
737 #endif  // #ifndef CDSLIB_GC_IMPL_HP_DECL_H