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