3 #ifndef __CDS_GC_DHP_DHP_DECL_H
4 #define __CDS_GC_DHP_DHP_DECL_H
6 #include <cds/gc/dhp/dhp.h>
7 #include <cds/details/marked_ptr.h>
8 #include <cds/details/static_functor.h>
10 namespace cds { namespace gc {
12 /// Pass-the-Buck garbage collector
13 /** @ingroup cds_garbage_collector
14 @headerfile cds/gc/dhp.h
15 This class is a wrapper for Pass-the-Buck garbage collector internal implementation.
18 - [2002] M. Herlihy, V. Luchangco, and M. Moir. The repeat offender problem: A mechanism for supporting
19 dynamic-sized lockfree data structures. Technical Report TR-2002-112, Sun Microsystems Laboratories, 2002
20 - [2002] M. Herlihy, V. Luchangco, P. Martin, and M. Moir. Dynamic-sized Lockfree Data Structures.
21 Technical Report TR-2002-110, Sun Microsystems Laboratories, 2002
22 - [2005] M. Herlihy, V. Luchangco, P. Martin, and M. Moir. Nonblocking Memory Management Support
23 for Dynamic_Sized Data Structures. ACM Transactions on Computer Systems, Vol.23, No.2, May 2005
25 See \ref cds_how_to_use "How to use" section for details of garbage collector applying.
30 /// Native guarded pointer type
31 typedef void * guarded_pointer;
35 @headerfile cds/gc/dhp.h
37 template <typename T> using atomic_ref = atomics::atomic<T *>;
41 @headerfile cds/gc/dhp.h
43 template <typename T> using atomic_type = atomics::atomic<T>;
45 /// Atomic marked pointer
47 @headerfile cds/gc/dhp.h
49 template <typename MarkedPtr> using atomic_marked_ptr = atomics::atomic<MarkedPtr>;
51 /// Thread GC implementation for internal usage
52 typedef ptb::ThreadGC thread_gc_impl;
54 /// Wrapper for ptb::ThreadGC class
56 @headerfile cds/gc/dhp.h
57 This class performs automatically attaching/detaching Pass-the-Buck GC
58 for the current thread.
60 class thread_gc: public thread_gc_impl
68 The constructor attaches the current thread to the Pass-the-Buck GC
69 if it is not yet attached.
70 The \p bPersistent parameter specifies attachment persistence:
71 - \p true - the class destructor will not detach the thread from Pass-the-Buck GC.
72 - \p false (default) - the class destructor will detach the thread from Pass-the-Buck GC.
75 bool bPersistent = false
76 ) ; // inline in ptb_impl.h
80 If the object has been created in persistent mode, the destructor does nothing.
81 Otherwise it detaches the current thread from Pass-the-Buck GC.
83 ~thread_gc() ; // inline in ptb_impl.h
87 /// Pass-the-Buck guard
89 @headerfile cds/gc/dhp.h
90 This class is a wrapper for ptb::Guard.
92 class Guard: public ptb::Guard
95 typedef ptb::Guard base_class;
100 Guard() ; // inline in ptb_impl.h
103 /// Protects a pointer of type <tt> atomic<T*> </tt>
105 Return the value of \p toGuard
107 The function tries to load \p toGuard and to store it
108 to the HP slot repeatedly until the guard's value equals \p toGuard
110 template <typename T>
111 T protect( atomics::atomic<T> const& toGuard )
113 T pCur = toGuard.load(atomics::memory_order_relaxed);
116 pRet = assign( pCur );
117 pCur = toGuard.load(atomics::memory_order_acquire);
118 } while ( pRet != pCur );
122 /// Protects a converted pointer of type <tt> atomic<T*> </tt>
124 Return the value of \p toGuard
126 The function tries to load \p toGuard and to store result of \p f functor
127 to the HP slot repeatedly until the guard's value equals \p toGuard.
129 The function is useful for intrusive containers when \p toGuard is a node pointer
130 that should be converted to a pointer to the value type before guarding.
131 The parameter \p f of type Func is a functor that makes this conversion:
134 value_type * operator()( T * p );
137 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
139 template <typename T, class Func>
140 T protect( atomics::atomic<T> const& toGuard, Func f )
142 T pCur = toGuard.load(atomics::memory_order_relaxed);
147 pCur = toGuard.load(atomics::memory_order_acquire);
148 } while ( pRet != pCur );
152 /// Store \p p to the guard
154 The function equals to a simple assignment, no loop is performed.
155 Can be used for a pointer that cannot be changed concurrently.
157 template <typename T>
160 return base_class::operator =(p);
164 std::nullptr_t assign( std::nullptr_t )
166 return base_class::operator =(nullptr);
170 /// Store marked pointer \p p to the guard
172 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
173 Can be used for a marked pointer that cannot be changed concurrently.
175 template <typename T, int BITMASK>
176 T * assign( cds::details::marked_ptr<T, BITMASK> p )
178 return base_class::operator =( p.ptr() );
181 /// Copy from \p src guard to \p this guard
182 void copy( Guard const& src )
184 assign( src.get_native() );
187 /// Clear value of the guard
193 /// Get the value currently protected (relaxed read)
194 template <typename T>
197 return reinterpret_cast<T *>( get_native() );
200 /// Get native guarded pointer stored
201 guarded_pointer get_native() const
203 return base_class::get_guard()->pPost.load(atomics::memory_order_relaxed);
208 /// Array of Pass-the-Buck guards
210 @headerfile cds/gc/dhp.h
211 This class is a wrapper for ptb::GuardArray template.
212 Template parameter \p Count defines the size of PTB array.
214 template <size_t Count>
215 class GuardArray: public ptb::GuardArray<Count>
218 typedef ptb::GuardArray<Count> base_class;
221 /// Rebind array for other size \p COUNT2
222 template <size_t OtherCount>
224 typedef GuardArray<OtherCount> other ; ///< rebinding result
229 GuardArray() ; // inline in ptb_impl.h
232 /// Protects a pointer of type \p atomic<T*>
234 Return the value of \p toGuard
236 The function tries to load \p toGuard and to store it
237 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
239 template <typename T>
240 T protect(size_t nIndex, atomics::atomic<T> const& toGuard )
244 pRet = assign( nIndex, toGuard.load(atomics::memory_order_relaxed) );
245 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
250 /// Protects a pointer of type \p atomic<T*>
252 Return the value of \p toGuard
254 The function tries to load \p toGuard and to store it
255 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
257 The function is useful for intrusive containers when \p toGuard is a node pointer
258 that should be converted to a pointer to the value type before guarding.
259 The parameter \p f of type Func is a functor that makes this conversion:
262 value_type * operator()( T * p );
265 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
267 template <typename T, class Func>
268 T protect(size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
272 assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_relaxed) ));
273 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
278 /// Store \p to the slot \p nIndex
280 The function equals to a simple assignment, no loop is performed.
282 template <typename T>
283 T * assign( size_t nIndex, T * p )
285 base_class::set(nIndex, p);
289 /// Store marked pointer \p p to the guard
291 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
292 Can be used for a marked pointer that cannot be changed concurrently.
294 template <typename T, int Bitmask>
295 T * assign( size_t nIndex, cds::details::marked_ptr<T, Bitmask> p )
297 return assign( nIndex, p.ptr() );
300 /// Copy guarded value from \p src guard to slot at index \p nIndex
301 void copy( size_t nIndex, Guard const& src )
303 assign( nIndex, src.get_native() );
306 /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
307 void copy( size_t nDestIndex, size_t nSrcIndex )
309 assign( nDestIndex, get_native( nSrcIndex ));
312 /// Clear value of the slot \p nIndex
313 void clear( size_t nIndex)
315 base_class::clear( nIndex );
318 /// Get current value of slot \p nIndex
319 template <typename T>
320 T * get( size_t nIndex) const
322 return reinterpret_cast<T *>( get_native( nIndex ) );
325 /// Get native guarded pointer stored
326 guarded_pointer get_native( size_t nIndex ) const
328 return base_class::operator[](nIndex).get_guard()->pPost.load(atomics::memory_order_relaxed);
331 /// Capacity of the guard array
332 static CDS_CONSTEXPR size_t capacity()
339 /// Initializes ptb::GarbageCollector singleton
341 The constructor calls GarbageCollector::Construct with passed parameters.
342 See ptb::GarbageCollector::Construct for explanation of parameters meaning.
345 size_t nLiberateThreshold = 1024
346 , size_t nInitialThreadGuardCount = 8
349 ptb::GarbageCollector::Construct(
351 nInitialThreadGuardCount
355 /// Terminates ptb::GarbageCollector singleton
357 The destructor calls \code ptb::GarbageCollector::Destruct() \endcode
361 ptb::GarbageCollector::Destruct();
364 /// Checks if count of hazard pointer is no less than \p nCountNeeded
366 The function always returns \p true since the guard count is unlimited for
367 PTB garbage collector.
369 static bool check_available_guards( size_t nCountNeeded, bool /*bRaiseException*/ = true )
371 CDS_UNUSED( nCountNeeded );
375 /// Retire pointer \p p with function \p pFunc
377 The function places pointer \p p to array of pointers ready for removing.
378 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
379 Deleting the pointer is the function \p pFunc call.
381 template <typename T>
382 static void retire( T * p, void (* pFunc)(T *) )
384 ptb::GarbageCollector::instance().retirePtr( p, pFunc );
387 /// Retire pointer \p p with functor of type \p Disposer
389 The function places pointer \p p to array of pointers ready for removing.
390 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
392 See gc::HP::retire for \p Disposer requirements.
394 template <class Disposer, typename T>
395 static void retire( T * p )
397 retire( p, cds::details::static_functor<Disposer, T>::call );
400 /// Checks if Pass-the-Buck GC is constructed and may be used
403 return ptb::GarbageCollector::isUsed();
406 /// Forced GC cycle call for current thread
408 Usually, this function should not be called directly.
410 static void scan() ; // inline in ptb_impl.h
412 /// Synonym for \ref scan()
413 static void force_dispose()
419 }} // namespace cds::gc
421 #endif // #ifndef __CDS_GC_DHP_DHP_DECL_H