3 #ifndef __CDS_GC_DHP_DHP_DECL_H
4 #define __CDS_GC_DHP_DHP_DECL_H
6 #include <cds/gc/details/dhp.h>
7 #include <cds/details/marked_ptr.h>
8 #include <cds/details/static_functor.h>
10 namespace cds { namespace gc {
12 /// Dynamic Hazard Pointer garbage collector
13 /** @ingroup cds_garbage_collector
14 @headerfile cds/gc/dhp.h
15 This class is a wrapper for Dynamic Hazard Pointer garbage collector internal implementation.
17 See \ref cds_how_to_use "How to use" section for details of garbage collector applying.
22 /// Native guarded pointer type
23 typedef void * guarded_pointer;
27 @headerfile cds/gc/dhp.h
29 template <typename T> using atomic_ref = atomics::atomic<T *>;
33 @headerfile cds/gc/dhp.h
35 template <typename T> using atomic_type = atomics::atomic<T>;
37 /// Atomic marked pointer
39 @headerfile cds/gc/dhp.h
41 template <typename MarkedPtr> using atomic_marked_ptr = atomics::atomic<MarkedPtr>;
43 /// Thread GC implementation for internal usage
44 typedef dhp::ThreadGC thread_gc_impl;
46 /// Wrapper for dhp::ThreadGC class
48 @headerfile cds/gc/dhp.h
49 This class performs automatically attaching/detaching Dynamic Hazard Pointer GC
50 for the current thread.
52 class thread_gc: public thread_gc_impl
60 The constructor attaches the current thread to the Dynamic Hazard Pointer GC
61 if it is not yet attached.
62 The \p bPersistent parameter specifies attachment persistence:
63 - \p true - the class destructor will not detach the thread from Dynamic Hazard Pointer GC.
64 - \p false (default) - the class destructor will detach the thread from Dynamic Hazard Pointer GC.
67 bool bPersistent = false
68 ) ; // inline in dhp_impl.h
72 If the object has been created in persistent mode, the destructor does nothing.
73 Otherwise it detaches the current thread from Dynamic Hazard Pointer GC.
75 ~thread_gc() ; // inline in dhp_impl.h
79 /// Dynamic Hazard Pointer guard
81 @headerfile cds/gc/dhp.h
82 This class is a wrapper for dhp::Guard.
84 class Guard: public dhp::Guard
87 typedef dhp::Guard base_class;
92 Guard() ; // inline in dhp_impl.h
95 /// Protects a pointer of type <tt> atomic<T*> </tt>
97 Return the value of \p toGuard
99 The function tries to load \p toGuard and to store it
100 to the HP slot repeatedly until the guard's value equals \p toGuard
102 template <typename T>
103 T protect( atomics::atomic<T> const& toGuard )
105 T pCur = toGuard.load(atomics::memory_order_relaxed);
108 pRet = assign( pCur );
109 pCur = toGuard.load(atomics::memory_order_acquire);
110 } while ( pRet != pCur );
114 /// Protects a converted pointer of type <tt> atomic<T*> </tt>
116 Return the value of \p toGuard
118 The function tries to load \p toGuard and to store result of \p f functor
119 to the HP slot repeatedly until the guard's value equals \p toGuard.
121 The function is useful for intrusive containers when \p toGuard is a node pointer
122 that should be converted to a pointer to the value type before guarding.
123 The parameter \p f of type Func is a functor that makes this conversion:
126 value_type * operator()( T * p );
129 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
131 template <typename T, class Func>
132 T protect( atomics::atomic<T> const& toGuard, Func f )
134 T pCur = toGuard.load(atomics::memory_order_relaxed);
139 pCur = toGuard.load(atomics::memory_order_acquire);
140 } while ( pRet != pCur );
144 /// Store \p p to the guard
146 The function equals to a simple assignment, no loop is performed.
147 Can be used for a pointer that cannot be changed concurrently.
149 template <typename T>
152 return base_class::operator =(p);
156 std::nullptr_t assign( std::nullptr_t )
158 return base_class::operator =(nullptr);
162 /// Store marked pointer \p p to the guard
164 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
165 Can be used for a marked pointer that cannot be changed concurrently.
167 template <typename T, int BITMASK>
168 T * assign( cds::details::marked_ptr<T, BITMASK> p )
170 return base_class::operator =( p.ptr() );
173 /// Copy from \p src guard to \p this guard
174 void copy( Guard const& src )
176 assign( src.get_native() );
179 /// Clear value of the guard
185 /// Get the value currently protected (relaxed read)
186 template <typename T>
189 return reinterpret_cast<T *>( get_native() );
192 /// Get native guarded pointer stored
193 guarded_pointer get_native() const
195 return base_class::get_guard()->pPost.load(atomics::memory_order_relaxed);
200 /// Array of Dynamic Hazard Pointer guards
202 @headerfile cds/gc/dhp.h
203 This class is a wrapper for dhp::GuardArray template.
204 Template parameter \p Count defines the size of DHP array.
206 template <size_t Count>
207 class GuardArray: public dhp::GuardArray<Count>
210 typedef dhp::GuardArray<Count> base_class;
213 /// Rebind array for other size \p COUNT2
214 template <size_t OtherCount>
216 typedef GuardArray<OtherCount> other ; ///< rebinding result
221 GuardArray() ; // inline in dhp_impl.h
224 /// Protects a pointer of type \p atomic<T*>
226 Return the value of \p toGuard
228 The function tries to load \p toGuard and to store it
229 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
231 template <typename T>
232 T protect(size_t nIndex, atomics::atomic<T> const& toGuard )
236 pRet = assign( nIndex, toGuard.load(atomics::memory_order_relaxed) );
237 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
242 /// Protects a pointer of type \p atomic<T*>
244 Return the value of \p toGuard
246 The function tries to load \p toGuard and to store it
247 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
249 The function is useful for intrusive containers when \p toGuard is a node pointer
250 that should be converted to a pointer to the value type before guarding.
251 The parameter \p f of type Func is a functor that makes this conversion:
254 value_type * operator()( T * p );
257 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
259 template <typename T, class Func>
260 T protect(size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
264 assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_relaxed) ));
265 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
270 /// Store \p to the slot \p nIndex
272 The function equals to a simple assignment, no loop is performed.
274 template <typename T>
275 T * assign( size_t nIndex, T * p )
277 base_class::set(nIndex, p);
281 /// Store marked pointer \p p to the guard
283 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
284 Can be used for a marked pointer that cannot be changed concurrently.
286 template <typename T, int Bitmask>
287 T * assign( size_t nIndex, cds::details::marked_ptr<T, Bitmask> p )
289 return assign( nIndex, p.ptr() );
292 /// Copy guarded value from \p src guard to slot at index \p nIndex
293 void copy( size_t nIndex, Guard const& src )
295 assign( nIndex, src.get_native() );
298 /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
299 void copy( size_t nDestIndex, size_t nSrcIndex )
301 assign( nDestIndex, get_native( nSrcIndex ));
304 /// Clear value of the slot \p nIndex
305 void clear( size_t nIndex)
307 base_class::clear( nIndex );
310 /// Get current value of slot \p nIndex
311 template <typename T>
312 T * get( size_t nIndex) const
314 return reinterpret_cast<T *>( get_native( nIndex ) );
317 /// Get native guarded pointer stored
318 guarded_pointer get_native( size_t nIndex ) const
320 return base_class::operator[](nIndex).get_guard()->pPost.load(atomics::memory_order_relaxed);
323 /// Capacity of the guard array
324 static CDS_CONSTEXPR size_t capacity()
331 /// Initializes dhp::GarbageCollector singleton
333 The constructor calls GarbageCollector::Construct with passed parameters.
334 See dhp::GarbageCollector::Construct for explanation of parameters meaning.
337 size_t nLiberateThreshold = 1024
338 , size_t nInitialThreadGuardCount = 8
341 dhp::GarbageCollector::Construct(
343 nInitialThreadGuardCount
347 /// Terminates dhp::GarbageCollector singleton
349 The destructor calls \code dhp::GarbageCollector::Destruct() \endcode
353 dhp::GarbageCollector::Destruct();
356 /// Checks if count of hazard pointer is no less than \p nCountNeeded
358 The function always returns \p true since the guard count is unlimited for
359 DHP garbage collector.
361 static bool check_available_guards( size_t nCountNeeded, bool /*bRaiseException*/ = true )
363 CDS_UNUSED( nCountNeeded );
367 /// Retire pointer \p p with function \p pFunc
369 The function places pointer \p p to array of pointers ready for removing.
370 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
371 Deleting the pointer is the function \p pFunc call.
373 template <typename T>
374 static void retire( T * p, void (* pFunc)(T *) )
376 dhp::GarbageCollector::instance().retirePtr( p, pFunc );
379 /// Retire pointer \p p with functor of type \p Disposer
381 The function places pointer \p p to array of pointers ready for removing.
382 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
384 See gc::HP::retire for \p Disposer requirements.
386 template <class Disposer, typename T>
387 static void retire( T * p )
389 retire( p, cds::details::static_functor<Disposer, T>::call );
392 /// Checks if Dynamic Hazard Pointer GC is constructed and may be used
395 return dhp::GarbageCollector::isUsed();
398 /// Forced GC cycle call for current thread
400 Usually, this function should not be called directly.
402 static void scan() ; // inline in dhp_impl.h
404 /// Synonym for \ref scan()
405 static void force_dispose()
411 }} // namespace cds::gc
413 #endif // #ifndef __CDS_GC_DHP_DHP_DECL_H