3 #ifndef __CDS_GC_PTB_DECL_H
4 #define __CDS_GC_PTB_DECL_H
6 #include <cds/gc/ptb/ptb.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/ptb.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/ptb.h
37 template <typename T> using atomic_ref = atomics::atomic<T *>;
41 @headerfile cds/gc/ptb.h
43 template <typename T> using atomic_type = atomics::atomic<T>;
45 /// Atomic marked pointer
47 @headerfile cds/gc/ptb.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/ptb.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
86 /// Base for container node
88 @headerfile cds/gc/ptb.h
89 This struct is empty for Pass-the-Buck GC
95 /// Pass-the-Buck guard
97 @headerfile cds/gc/ptb.h
98 This class is a wrapper for ptb::Guard.
100 class Guard: public ptb::Guard
103 typedef ptb::Guard base_class;
108 Guard() ; // inline in ptb_impl.h
111 /// Protects a pointer of type <tt> atomic<T*> </tt>
113 Return the value of \p toGuard
115 The function tries to load \p toGuard and to store it
116 to the HP slot repeatedly until the guard's value equals \p toGuard
118 template <typename T>
119 T protect( atomics::atomic<T> const& toGuard )
121 T pCur = toGuard.load(atomics::memory_order_relaxed);
124 pRet = assign( pCur );
125 pCur = toGuard.load(atomics::memory_order_acquire);
126 } while ( pRet != pCur );
130 /// Protects a converted pointer of type <tt> atomic<T*> </tt>
132 Return the value of \p toGuard
134 The function tries to load \p toGuard and to store result of \p f functor
135 to the HP slot repeatedly until the guard's value equals \p toGuard.
137 The function is useful for intrusive containers when \p toGuard is a node pointer
138 that should be converted to a pointer to the value type before guarding.
139 The parameter \p f of type Func is a functor that makes this conversion:
142 value_type * operator()( T * p );
145 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
147 template <typename T, class Func>
148 T protect( atomics::atomic<T> const& toGuard, Func f )
150 T pCur = toGuard.load(atomics::memory_order_relaxed);
155 pCur = toGuard.load(atomics::memory_order_acquire);
156 } while ( pRet != pCur );
160 /// Store \p p to the guard
162 The function equals to a simple assignment, no loop is performed.
163 Can be used for a pointer that cannot be changed concurrently.
165 template <typename T>
168 return base_class::operator =(p);
172 std::nullptr_t assign( std::nullptr_t )
174 return base_class::operator =(nullptr);
178 /// Store marked pointer \p p to the guard
180 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
181 Can be used for a marked pointer that cannot be changed concurrently.
183 template <typename T, int BITMASK>
184 T * assign( cds::details::marked_ptr<T, BITMASK> p )
186 return base_class::operator =( p.ptr() );
189 /// Copy from \p src guard to \p this guard
190 void copy( Guard const& src )
192 assign( src.get_native() );
195 /// Clear value of the guard
201 /// Get the value currently protected (relaxed read)
202 template <typename T>
205 return reinterpret_cast<T *>( get_native() );
208 /// Get native guarded pointer stored
209 guarded_pointer get_native() const
211 return base_class::get_guard()->pPost.load(atomics::memory_order_relaxed);
216 /// Array of Pass-the-Buck guards
218 @headerfile cds/gc/ptb.h
219 This class is a wrapper for ptb::GuardArray template.
220 Template parameter \p Count defines the size of PTB array.
222 template <size_t Count>
223 class GuardArray: public ptb::GuardArray<Count>
226 typedef ptb::GuardArray<Count> base_class;
229 /// Rebind array for other size \p COUNT2
230 template <size_t OtherCount>
232 typedef GuardArray<OtherCount> other ; ///< rebinding result
237 GuardArray() ; // inline in ptb_impl.h
240 /// Protects a pointer of type \p atomic<T*>
242 Return the value of \p toGuard
244 The function tries to load \p toGuard and to store it
245 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
247 template <typename T>
248 T protect(size_t nIndex, atomics::atomic<T> const& toGuard )
252 pRet = assign( nIndex, toGuard.load(atomics::memory_order_relaxed) );
253 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
258 /// Protects a pointer of type \p atomic<T*>
260 Return the value of \p toGuard
262 The function tries to load \p toGuard and to store it
263 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
265 The function is useful for intrusive containers when \p toGuard is a node pointer
266 that should be converted to a pointer to the value type before guarding.
267 The parameter \p f of type Func is a functor that makes this conversion:
270 value_type * operator()( T * p );
273 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
275 template <typename T, class Func>
276 T protect(size_t nIndex, atomics::atomic<T> const& toGuard, Func f )
280 assign( nIndex, f( pRet = toGuard.load(atomics::memory_order_relaxed) ));
281 } while ( pRet != toGuard.load(atomics::memory_order_acquire));
286 /// Store \p to the slot \p nIndex
288 The function equals to a simple assignment, no loop is performed.
290 template <typename T>
291 T * assign( size_t nIndex, T * p )
293 base_class::set(nIndex, p);
297 /// Store marked pointer \p p to the guard
299 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
300 Can be used for a marked pointer that cannot be changed concurrently.
302 template <typename T, int Bitmask>
303 T * assign( size_t nIndex, cds::details::marked_ptr<T, Bitmask> p )
305 return assign( nIndex, p.ptr() );
308 /// Copy guarded value from \p src guard to slot at index \p nIndex
309 void copy( size_t nIndex, Guard const& src )
311 assign( nIndex, src.get_native() );
314 /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
315 void copy( size_t nDestIndex, size_t nSrcIndex )
317 assign( nDestIndex, get_native( nSrcIndex ));
320 /// Clear value of the slot \p nIndex
321 void clear( size_t nIndex)
323 base_class::clear( nIndex );
326 /// Get current value of slot \p nIndex
327 template <typename T>
328 T * get( size_t nIndex) const
330 return reinterpret_cast<T *>( get_native( nIndex ) );
333 /// Get native guarded pointer stored
334 guarded_pointer get_native( size_t nIndex ) const
336 return base_class::operator[](nIndex).get_guard()->pPost.load(atomics::memory_order_relaxed);
339 /// Capacity of the guard array
340 static CDS_CONSTEXPR size_t capacity()
347 /// Initializes ptb::GarbageCollector singleton
349 The constructor calls GarbageCollector::Construct with passed parameters.
350 See ptb::GarbageCollector::Construct for explanation of parameters meaning.
353 size_t nLiberateThreshold = 1024
354 , size_t nInitialThreadGuardCount = 8
357 ptb::GarbageCollector::Construct(
359 nInitialThreadGuardCount
363 /// Terminates ptb::GarbageCollector singleton
365 The destructor calls \code ptb::GarbageCollector::Destruct() \endcode
369 ptb::GarbageCollector::Destruct();
372 /// Checks if count of hazard pointer is no less than \p nCountNeeded
374 The function always returns \p true since the guard count is unlimited for
375 PTB garbage collector.
377 static bool check_available_guards( size_t nCountNeeded, bool /*bRaiseException*/ = true )
379 CDS_UNUSED( nCountNeeded );
383 /// Retire pointer \p p with function \p pFunc
385 The function places pointer \p p to array of pointers ready for removing.
386 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
387 Deleting the pointer is the function \p pFunc call.
389 template <typename T>
390 static void retire( T * p, void (* pFunc)(T *) )
392 ptb::GarbageCollector::instance().retirePtr( p, pFunc );
395 /// Retire pointer \p p with functor of type \p Disposer
397 The function places pointer \p p to array of pointers ready for removing.
398 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
400 See gc::HP::retire for \p Disposer requirements.
402 template <class Disposer, typename T>
403 static void retire( T * p )
405 retire( p, cds::details::static_functor<Disposer, T>::call );
408 /// Checks if Pass-the-Buck GC is constructed and may be used
411 return ptb::GarbageCollector::isUsed();
414 /// Forced GC cycle call for current thread
416 Usually, this function should not be called directly.
418 static void scan() ; // inline in ptb_impl.h
420 /// Synonym for \ref scan()
421 static void force_dispose()
427 }} // namespace cds::gc
429 #endif // #ifndef __CDS_GC_PTB_DECL_H