b2b6e77a43b992296cddbb877df8ed99d645c766
[libcds.git] / cds / gc / impl / dhp_decl.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8     
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
29 */
30
31 #ifndef CDSLIB_GC_IMPL_DHP_DECL_H
32 #define CDSLIB_GC_IMPL_DHP_DECL_H
33
34 #include <cds/gc/details/dhp.h>
35 #include <cds/details/marked_ptr.h>
36 #include <cds/details/static_functor.h>
37
38 namespace cds { namespace gc {
39
40     /// Dynamic Hazard Pointer garbage collector
41     /**  @ingroup cds_garbage_collector
42         @headerfile cds/gc/dhp.h
43
44         Implementation of Dynamic Hazard Pointer garbage collector.
45
46         Sources:
47             - [2002] Maged M.Michael "Safe memory reclamation for dynamic lock-freeobjects using atomic reads and writes"
48             - [2003] Maged M.Michael "Hazard Pointers: Safe memory reclamation for lock-free objects"
49             - [2004] Andrei Alexandrescy, Maged Michael "Lock-free Data Structures with Hazard Pointers"
50
51         Dynamic Hazard Pointers SMR (safe memory reclamation) provides an unbounded number of hazard pointer per thread
52         despite of classic Hazard Pointer SMR in which the count of the hazard pointef per thread is limited.
53
54         See \ref cds_how_to_use "How to use" section for details how to apply garbage collector.
55     */
56     class DHP
57     {
58     public:
59         /// Native guarded pointer type
60         /**
61             @headerfile cds/gc/dhp.h
62         */
63         typedef void * guarded_pointer;
64
65         /// Atomic reference
66         /**
67             @headerfile cds/gc/dhp.h
68         */
69         template <typename T> using atomic_ref = atomics::atomic<T *>;
70
71         /// Atomic type
72         /**
73             @headerfile cds/gc/dhp.h
74         */
75         template <typename T> using atomic_type = atomics::atomic<T>;
76
77         /// Atomic marked pointer
78         /**
79             @headerfile cds/gc/dhp.h
80         */
81         template <typename MarkedPtr> using atomic_marked_ptr = atomics::atomic<MarkedPtr>;
82
83         /// Thread GC implementation for internal usage
84         /**
85             @headerfile cds/gc/dhp.h
86         */
87         typedef dhp::ThreadGC   thread_gc_impl;
88
89         /// Thread-level garbage collector
90         /**
91             @headerfile cds/gc/dhp.h
92             This class performs automatically attaching/detaching Dynamic Hazard Pointer GC
93             for the current thread.
94         */
95         class thread_gc: public thread_gc_impl
96         {
97             //@cond
98             bool    m_bPersistent;
99             //@endcond
100         public:
101             /// Constructor
102             /**
103                 The constructor attaches the current thread to the Dynamic Hazard Pointer GC
104                 if it is not yet attached.
105                 The \p bPersistent parameter specifies attachment persistence:
106                 - \p true - the class destructor will not detach the thread from Dynamic Hazard Pointer GC.
107                 - \p false (default) - the class destructor will detach the thread from Dynamic Hazard Pointer GC.
108             */
109             thread_gc(
110                 bool    bPersistent = false
111             )   ;   // inline in dhp_impl.h
112
113             /// Destructor
114             /**
115                 If the object has been created in persistent mode, the destructor does nothing.
116                 Otherwise it detaches the current thread from Dynamic Hazard Pointer GC.
117             */
118             ~thread_gc()    ;   // inline in dhp_impl.h
119
120         public: // for internal use only!!!
121             //@cond
122             static void alloc_guard( cds::gc::dhp::details::guard& g ); // inline in dhp_impl.h
123             static void free_guard( cds::gc::dhp::details::guard& g ); // inline in dhp_impl.h
124             //@endcond
125         };
126
127
128         /// Dynamic Hazard Pointer guard
129         /**
130             @headerfile cds/gc/dhp.h
131
132             A guard is the hazard pointer.
133             Additionally, the \p %Guard class manages allocation and deallocation of the hazard pointer
134
135             A \p %Guard object is not copy- and move-constructible
136             and not copy- and move-assignable.
137         */
138         class Guard: public dhp::Guard
139         {
140             //@cond
141             typedef dhp::Guard base_class;
142             //@endcond
143
144         public: // for internal use only
145             //@cond
146             typedef cds::gc::dhp::details::guard native_guard;
147             //@endcond
148
149         public:
150             // Default ctor
151             Guard()
152             {}
153
154             //@cond
155             Guard( Guard const& ) = delete;
156             Guard( Guard&& s ) = delete;
157             Guard& operator=(Guard const&) = delete;
158             Guard& operator=(Guard&&) = delete;
159             //@endcond
160
161             /// Protects a pointer of type <tt> atomic<T*> </tt>
162             /**
163                 Return the value of \p toGuard
164
165                 The function tries to load \p toGuard and to store it
166                 to the HP slot repeatedly until the guard's value equals \p toGuard
167             */
168             template <typename T>
169             T protect( atomics::atomic<T> const& toGuard )
170             {
171                 T pCur = toGuard.load(atomics::memory_order_acquire);
172                 T pRet;
173                 do {
174                     pRet = assign( pCur );
175                     pCur = toGuard.load(atomics::memory_order_acquire);
176                 } while ( pRet != pCur );
177                 return pCur;
178             }
179
180             /// Protects a converted pointer of type <tt> atomic<T*> </tt>
181             /**
182                 Return the value of \p toGuard
183
184                 The function tries to load \p toGuard and to store result of \p f functor
185                 to the HP slot repeatedly until the guard's value equals \p toGuard.
186
187                 The function is useful for intrusive containers when \p toGuard is a node pointer
188                 that should be converted to a pointer to the value type before guarding.
189                 The parameter \p f of type Func is a functor that makes this conversion:
190                 \code
191                     struct functor {
192                         value_type * operator()( T * p );
193                     };
194                 \endcode
195                 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
196             */
197             template <typename T, class Func>
198             T protect( atomics::atomic<T> const& toGuard, Func f )
199             {
200                 T pCur = toGuard.load(atomics::memory_order_acquire);
201                 T pRet;
202                 do {
203                     pRet = pCur;
204                     assign( f( pCur ) );
205                     pCur = toGuard.load(atomics::memory_order_acquire);
206                 } while ( pRet != pCur );
207                 return pCur;
208             }
209
210             /// Store \p p to the guard
211             /**
212                 The function is just an assignment, no loop is performed.
213                 Can be used for a pointer that cannot be changed concurrently
214                 or for already guarded pointer.
215             */
216             template <typename T>
217             T * assign( T * p )
218             {
219                 return base_class::operator =(p);
220             }
221
222             //@cond
223             std::nullptr_t assign( std::nullptr_t )
224             {
225                 return base_class::operator =(nullptr);
226             }
227             //@endcond
228
229             /// Store marked pointer \p p to the guard
230             /**
231                 The function is just an assignment of <tt>p.ptr()</tt>, no loop is performed.
232                 Can be used for a marked pointer that cannot be changed concurrently
233                 or for already guarded pointer.
234             */
235             template <typename T, int BITMASK>
236             T * assign( cds::details::marked_ptr<T, BITMASK> p )
237             {
238                 return base_class::operator =( p.ptr() );
239             }
240
241             /// Copy from \p src guard to \p this guard
242             void copy( Guard const& src )
243             {
244                 assign( src.get_native() );
245             }
246
247             /// Clears value of the guard
248             void clear()
249             {
250                 base_class::clear();
251             }
252
253             /// Gets the value currently protected (relaxed read)
254             template <typename T>
255             T * get() const
256             {
257                 return reinterpret_cast<T *>( get_native() );
258             }
259
260             /// Gets native guarded pointer stored
261             guarded_pointer get_native() const
262             {
263                 return base_class::get_guard()->pPost.load(atomics::memory_order_relaxed);
264             }
265         };
266
267         /// Array of Dynamic Hazard Pointer guards
268         /**
269             @headerfile cds/gc/dhp.h
270             The class is intended for allocating an array of hazard pointer guards.
271             Template parameter \p Count defines the size of the array.
272
273             A \p %GuardArray object is not copy- and move-constructible
274             and not copy- and move-assignable.
275         */
276         template <size_t Count>
277         class GuardArray: public dhp::GuardArray<Count>
278         {
279             //@cond
280             typedef dhp::GuardArray<Count> base_class;
281             //@endcond
282         public:
283             /// Rebind array for other size \p OtherCount
284             template <size_t OtherCount>
285             struct rebind {
286                 typedef GuardArray<OtherCount>  other   ;   ///< rebinding result
287             };
288
289         public:
290             // Default ctor
291             GuardArray()
292             {}
293
294             //@cond
295             GuardArray( GuardArray const& ) = delete;
296             GuardArray( GuardArray&& ) = delete;
297             GuardArray& operator=(GuardArray const&) = delete;
298             GuardArray& operator-(GuardArray&&) = delete;
299             //@endcond
300
301             /// Protects a pointer of type \p atomic<T*>
302             /**
303                 Return the value of \p toGuard
304
305                 The function tries to load \p toGuard and to store it
306                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
307             */
308             template <typename T>
309             T protect( size_t nIndex, atomics::atomic<T> const& toGuard )
310             {
311                 T pRet;
312                 do {
313                     pRet = assign( nIndex, toGuard.load(atomics::memory_order_acquire) );
314                 } while ( pRet != toGuard.load(atomics::memory_order_relaxed));
315
316                 return pRet;
317             }
318
319             /// Protects a pointer of type \p atomic<T*>
320             /**
321                 Return the value of \p toGuard
322
323                 The function tries to load \p toGuard and to store it
324                 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
325
326                 The function is useful for intrusive containers when \p toGuard is a node pointer
327                 that should be converted to a pointer to the value type before guarding.
328                 The parameter \p f of type Func is a functor to make that conversion:
329                 \code
330                     struct functor {
331                         value_type * operator()( T * p );
332                     };
333                 \endcode
334                 Actually, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
335             */
336             template <typename T, class Func>
337             T protect( size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
338             {
339                 T pRet;
340                 do {
341                     assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_acquire) ));
342                 } while ( pRet != toGuard.load(atomics::memory_order_relaxed));
343
344                 return pRet;
345             }
346
347             /// Store \p p to the slot \p nIndex
348             /**
349                 The function is just an assignment, no loop is performed.
350             */
351             template <typename T>
352             T * assign( size_t nIndex, T * p )
353             {
354                 base_class::set(nIndex, p);
355                 return p;
356             }
357
358             /// Store marked pointer \p p to the guard
359             /**
360                 The function is just an assignment of <tt>p.ptr()</tt>, no loop is performed.
361                 Can be used for a marked pointer that cannot be changed concurrently
362                 or for already guarded pointer.
363             */
364             template <typename T, int Bitmask>
365             T * assign( size_t nIndex, cds::details::marked_ptr<T, Bitmask> p )
366             {
367                 return assign( nIndex, p.ptr() );
368             }
369
370             /// Copy guarded value from \p src guard to slot at index \p nIndex
371             void copy( size_t nIndex, Guard const& src )
372             {
373                 assign( nIndex, src.get_native() );
374             }
375
376             /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
377             void copy( size_t nDestIndex, size_t nSrcIndex )
378             {
379                 assign( nDestIndex, get_native( nSrcIndex ));
380             }
381
382             /// Clear value of the slot \p nIndex
383             void clear( size_t nIndex )
384             {
385                 base_class::clear( nIndex );
386             }
387
388             /// Get current value of slot \p nIndex
389             template <typename T>
390             T * get( size_t nIndex ) const
391             {
392                 return reinterpret_cast<T *>( get_native( nIndex ) );
393             }
394
395             /// Get native guarded pointer stored
396             guarded_pointer get_native( size_t nIndex ) const
397             {
398                 return base_class::operator[](nIndex).get_guard()->pPost.load(atomics::memory_order_relaxed);
399             }
400
401             /// Capacity of the guard array
402             static CDS_CONSTEXPR size_t capacity()
403             {
404                 return Count;
405             }
406         };
407
408         /// Guarded pointer
409         /**
410             A guarded pointer is a pair of a pointer and GC's guard.
411             Usually, it is used for returning a pointer to the item from an lock-free container.
412             The guard prevents the pointer to be early disposed (freed) by GC.
413             After destructing \p %guarded_ptr object the pointer can be disposed (freed) automatically at any time.
414
415             Template arguments:
416             - \p GuardedType - a type which the guard stores
417             - \p ValueType - a value type
418             - \p Cast - a functor for converting <tt>GuardedType*</tt> to <tt>ValueType*</tt>. Default is \p void (no casting).
419
420             For intrusive containers, \p GuardedType is the same as \p ValueType and no casting is needed.
421             In such case the \p %guarded_ptr is:
422             @code
423             typedef cds::gc::DHP::guarded_ptr< foo > intrusive_guarded_ptr;
424             @endcode
425
426             For standard (non-intrusive) containers \p GuardedType is not the same as \p ValueType and casting is needed.
427             For example:
428             @code
429             struct foo {
430                 int const   key;
431                 std::string value;
432             };
433
434             struct value_accessor {
435                 std::string* operator()( foo* pFoo ) const
436                 {
437                     return &(pFoo->value);
438                 }
439             };
440
441             // Guarded ptr
442             typedef cds::gc::DHP::guarded_ptr< Foo, std::string, value_accessor > nonintrusive_guarded_ptr;
443             @endcode
444
445             You don't need use this class directly.
446             All set/map container classes from \p libcds declare the typedef for \p %guarded_ptr with appropriate casting functor.
447         */
448         template <typename GuardedType, typename ValueType=GuardedType, typename Cast=void >
449         class guarded_ptr
450         {
451             //@cond
452             struct trivial_cast {
453                 ValueType * operator()( GuardedType * p ) const
454                 {
455                     return p;
456                 }
457             };
458             //@endcond
459
460         public:
461             typedef GuardedType guarded_type; ///< Guarded type
462             typedef ValueType   value_type;   ///< Value type
463
464             /// Functor for casting \p guarded_type to \p value_type
465             typedef typename std::conditional< std::is_same<Cast, void>::value, trivial_cast, Cast >::type value_cast;
466
467             //@cond
468             typedef cds::gc::dhp::details::guard native_guard;
469             //@endcond
470
471         private:
472             //@cond
473             native_guard    m_guard;
474             //@endcond
475
476         public:
477             /// Creates empty guarded pointer
478             guarded_ptr() CDS_NOEXCEPT
479             {}
480
481             //@cond
482             /// Initializes guarded pointer with \p p
483             explicit guarded_ptr( guarded_type * p ) CDS_NOEXCEPT
484             {
485                 alloc_guard();
486                 assert( m_guard.is_initialized() );
487                 m_guard.set( p );
488             }
489             explicit guarded_ptr( std::nullptr_t ) CDS_NOEXCEPT
490             {}
491             //@endcond
492
493             /// Move ctor
494             guarded_ptr( guarded_ptr&& gp ) CDS_NOEXCEPT
495             {
496                 m_guard.set_guard( gp.m_guard.release_guard() );
497             }
498
499             /// The guarded pointer is not copy-constructible
500             guarded_ptr( guarded_ptr const& gp ) = delete;
501
502             /// Clears the guarded pointer
503             /**
504                 \ref release is called if guarded pointer is not \ref empty
505             */
506             ~guarded_ptr() CDS_NOEXCEPT
507             {
508                 free_guard();
509             }
510
511             /// Move-assignment operator
512             guarded_ptr& operator=( guarded_ptr&& gp ) CDS_NOEXCEPT
513             {
514                 free_guard();
515                 m_guard.set_guard( gp.m_guard.release_guard() );
516                 return *this;
517             }
518
519             /// The guarded pointer is not copy-assignable
520             guarded_ptr& operator=(guarded_ptr const& gp) = delete;
521
522             /// Returns a pointer to guarded value
523             value_type * operator ->() const CDS_NOEXCEPT
524             {
525                 assert( !empty() );
526                 return value_cast()( reinterpret_cast<guarded_type *>(m_guard.get()));
527             }
528
529             /// Returns a reference to guarded value
530             value_type& operator *() CDS_NOEXCEPT
531             {
532                 assert( !empty());
533                 return *value_cast()(reinterpret_cast<guarded_type *>(m_guard.get()));
534             }
535
536             /// Returns const reference to guarded value
537             value_type const& operator *() const CDS_NOEXCEPT
538             {
539                 assert( !empty() );
540                 return *value_cast()(reinterpret_cast<guarded_type *>(m_guard.get()));
541             }
542
543             /// Checks if the guarded pointer is \p nullptr
544             bool empty() const CDS_NOEXCEPT
545             {
546                 return !m_guard.is_initialized() || m_guard.get( atomics::memory_order_relaxed ) == nullptr;
547             }
548
549             /// \p bool operator returns <tt>!empty()</tt>
550             explicit operator bool() const CDS_NOEXCEPT
551             {
552                 return !empty();
553             }
554
555             /// Clears guarded pointer
556             /**
557                 If the guarded pointer has been released, the pointer can be disposed (freed) at any time.
558                 Dereferncing the guarded pointer after \p release() is dangerous.
559             */
560             void release() CDS_NOEXCEPT
561             {
562                 free_guard();
563             }
564
565             //@cond
566             // For internal use only!!!
567             native_guard& guard() CDS_NOEXCEPT
568             {
569                 alloc_guard();
570                 assert( m_guard.is_initialized() );
571                 return m_guard;
572             }
573
574             void reset(guarded_type * p) CDS_NOEXCEPT
575             {
576                 alloc_guard();
577                 assert( m_guard.is_initialized() );
578                 m_guard.set(p);
579             }
580
581             //@endcond
582
583         private:
584             //@cond
585             void alloc_guard()
586             {
587                 if ( !m_guard.is_initialized() )
588                     thread_gc::alloc_guard( m_guard );
589             }
590
591             void free_guard()
592             {
593                 if ( m_guard.is_initialized() )
594                     thread_gc::free_guard( m_guard );
595             }
596             //@endcond
597         };
598
599     public:
600         /// Initializes %DHP memory manager singleton
601         /**
602             Constructor creates and initializes %DHP global object.
603             %DHP object should be created before using CDS data structure based on \p %cds::gc::DHP GC. Usually,
604             it is created in the \p main() function.
605             After creating of global object you may use CDS data structures based on \p %cds::gc::DHP.
606
607             \par Parameters
608             - \p nLiberateThreshold - \p scan() threshold. When count of retired pointers reaches this value,
609                 the \p scan() member function would be called for freeing retired pointers.
610             - \p nInitialThreadGuardCount - initial count of guard allocated for each thread.
611                 When a thread is initialized the GC allocates local guard pool for the thread from common guard pool.
612                 By perforce the local thread's guard pool is grown automatically from common pool.
613                 When the thread terminated its guard pool is backed to common GC's pool.
614             - \p nEpochCount: internally, DHP memory manager uses epoch-based schema to solve
615                 ABA problem for internal data. \p nEpochCount specifies the epoch count,
616                 i.e. the count of simultaneously working threads that remove the elements
617                 of DHP-based concurrent data structure. Default value is 16.
618         */
619         DHP(
620             size_t nLiberateThreshold = 1024
621             , size_t nInitialThreadGuardCount = 8
622             , size_t nEpochCount = 16
623         )
624         {
625             dhp::GarbageCollector::Construct( nLiberateThreshold, nInitialThreadGuardCount, nEpochCount );
626         }
627
628         /// Destroys %DHP memory manager
629         /**
630             The destructor destroys %DHP global object. After calling of this function you may \b NOT
631             use CDS data structures based on \p %cds::gc::DHP.
632             Usually, %DHP object is destroyed at the end of your \p main().
633         */
634         ~DHP()
635         {
636             dhp::GarbageCollector::Destruct();
637         }
638
639         /// Checks if count of hazard pointer is no less than \p nCountNeeded
640         /**
641             The function always returns \p true since the guard count is unlimited for
642             \p %gc::DHP garbage collector.
643         */
644         static CDS_CONSTEXPR bool check_available_guards(
645 #ifdef CDS_DOXYGEN_INVOKED
646             size_t nCountNeeded,
647 #else
648             size_t,
649 #endif
650             bool /*bRaiseException*/ = true )
651         {
652             return true;
653         }
654
655         /// Retire pointer \p p with function \p pFunc
656         /**
657             The function places pointer \p p to array of pointers ready for removing.
658             (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
659             Deleting the pointer is the function \p pFunc call.
660         */
661         template <typename T>
662         static void retire( T * p, void (* pFunc)(T *) )
663         {
664             dhp::GarbageCollector::instance().retirePtr( p, pFunc );
665         }
666
667         /// Retire pointer \p p with functor of type \p Disposer
668         /**
669             The function places pointer \p p to array of pointers ready for removing.
670             (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
671
672             See \p gc::HP::retire for \p Disposer requirements.
673         */
674         template <class Disposer, typename T>
675         static void retire( T * p )
676         {
677             retire( p, cds::details::static_functor<Disposer, T>::call );
678         }
679
680         /// Checks if Dynamic Hazard Pointer GC is constructed and may be used
681         static bool isUsed()
682         {
683             return dhp::GarbageCollector::isUsed();
684         }
685
686         /// Forced GC cycle call for current thread
687         /**
688             Usually, this function should not be called directly.
689         */
690         static void scan()  ;   // inline in dhp_impl.h
691
692         /// Synonym for \ref scan()
693         static void force_dispose()
694         {
695             scan();
696         }
697     };
698
699 }} // namespace cds::gc
700
701 #endif // #ifndef CDSLIB_GC_IMPL_DHP_DECL_H