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;
33 #ifdef CDS_CXX11_TEMPLATE_ALIAS_SUPPORT
36 @headerfile cds/gc/ptb.h
38 template <typename T> using atomic_ref = CDS_ATOMIC::atomic<T *>;
42 @headerfile cds/gc/ptb.h
44 template <typename T> using atomic_type = CDS_ATOMIC::atomic<T>;
46 /// Atomic marked pointer
48 @headerfile cds/gc/ptb.h
50 template <typename MarkedPtr> using atomic_marked_ptr = CDS_ATOMIC::atomic<MarkedPtr>;
53 class atomic_ref: public CDS_ATOMIC::atomic<T *>
55 typedef CDS_ATOMIC::atomic<T *> base_class;
57 # ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
58 atomic_ref() = default;
64 explicit CDS_CONSTEXPR atomic_ref(T * p) CDS_NOEXCEPT
70 class atomic_type: public CDS_ATOMIC::atomic<T>
72 typedef CDS_ATOMIC::atomic<T> base_class;
74 # ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
75 atomic_type() = default;
77 atomic_type() CDS_NOEXCEPT
81 explicit CDS_CONSTEXPR atomic_type(T const & v) CDS_NOEXCEPT
86 template <typename MarkedPtr>
87 class atomic_marked_ptr: public CDS_ATOMIC::atomic<MarkedPtr>
89 typedef CDS_ATOMIC::atomic<MarkedPtr> base_class;
91 # ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
92 atomic_marked_ptr() = default;
98 explicit CDS_CONSTEXPR atomic_marked_ptr(MarkedPtr val) CDS_NOEXCEPT
101 explicit CDS_CONSTEXPR atomic_marked_ptr(typename MarkedPtr::value_type * p) CDS_NOEXCEPT
107 /// Thread GC implementation for internal usage
108 typedef ptb::ThreadGC thread_gc_impl;
110 /// Wrapper for ptb::ThreadGC class
112 @headerfile cds/gc/ptb.h
113 This class performs automatically attaching/detaching Pass-the-Buck GC
114 for the current thread.
116 class thread_gc: public thread_gc_impl
124 The constructor attaches the current thread to the Pass-the-Buck GC
125 if it is not yet attached.
126 The \p bPersistent parameter specifies attachment persistence:
127 - \p true - the class destructor will not detach the thread from Pass-the-Buck GC.
128 - \p false (default) - the class destructor will detach the thread from Pass-the-Buck GC.
131 bool bPersistent = false
132 ) ; // inline in ptb_impl.h
136 If the object has been created in persistent mode, the destructor does nothing.
137 Otherwise it detaches the current thread from Pass-the-Buck GC.
139 ~thread_gc() ; // inline in ptb_impl.h
142 /// Base for container node
144 @headerfile cds/gc/ptb.h
145 This struct is empty for Pass-the-Buck GC
147 struct container_node
151 /// Pass-the-Buck guard
153 @headerfile cds/gc/ptb.h
154 This class is a wrapper for ptb::Guard.
156 class Guard: public ptb::Guard
159 typedef ptb::Guard base_class;
164 Guard() ; // inline in ptb_impl.h
167 /// Protects a pointer of type <tt> atomic<T*> </tt>
169 Return the value of \p toGuard
171 The function tries to load \p toGuard and to store it
172 to the HP slot repeatedly until the guard's value equals \p toGuard
174 template <typename T>
175 T protect( CDS_ATOMIC::atomic<T> const& toGuard )
177 T pCur = toGuard.load(CDS_ATOMIC::memory_order_relaxed);
180 pRet = assign( pCur );
181 pCur = toGuard.load(CDS_ATOMIC::memory_order_acquire);
182 } while ( pRet != pCur );
186 /// Protects a converted pointer of type <tt> atomic<T*> </tt>
188 Return the value of \p toGuard
190 The function tries to load \p toGuard and to store result of \p f functor
191 to the HP slot repeatedly until the guard's value equals \p toGuard.
193 The function is useful for intrusive containers when \p toGuard is a node pointer
194 that should be converted to a pointer to the value type before guarding.
195 The parameter \p f of type Func is a functor that makes this conversion:
198 value_type * operator()( T * p );
201 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
203 template <typename T, class Func>
204 T protect( CDS_ATOMIC::atomic<T> const& toGuard, Func f )
206 T pCur = toGuard.load(CDS_ATOMIC::memory_order_relaxed);
211 pCur = toGuard.load(CDS_ATOMIC::memory_order_acquire);
212 } while ( pRet != pCur );
216 /// Store \p p to the guard
218 The function equals to a simple assignment, no loop is performed.
219 Can be used for a pointer that cannot be changed concurrently.
221 template <typename T>
224 return base_class::operator =(p);
227 /// Store marked pointer \p p to the guard
229 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
230 Can be used for a marked pointer that cannot be changed concurrently.
232 template <typename T, int BITMASK>
233 T * assign( cds::details::marked_ptr<T, BITMASK> p )
235 return base_class::operator =( p.ptr() );
238 /// Copy from \p src guard to \p this guard
239 void copy( Guard const& src )
241 assign( src.get_native() );
244 /// Clear value of the guard
250 /// Get the value currently protected (relaxed read)
251 template <typename T>
254 return reinterpret_cast<T *>( get_native() );
257 /// Get native guarded pointer stored
258 guarded_pointer get_native() const
260 return base_class::get_guard()->pPost.load(CDS_ATOMIC::memory_order_relaxed);
265 /// Array of Pass-the-Buck guards
267 @headerfile cds/gc/ptb.h
268 This class is a wrapper for ptb::GuardArray template.
269 Template parameter \p Count defines the size of PTB array.
271 template <size_t Count>
272 class GuardArray: public ptb::GuardArray<Count>
275 typedef ptb::GuardArray<Count> base_class;
278 /// Rebind array for other size \p COUNT2
279 template <size_t OtherCount>
281 typedef GuardArray<OtherCount> other ; ///< rebinding result
286 GuardArray() ; // inline in ptb_impl.h
289 /// Protects a pointer of type \p atomic<T*>
291 Return the value of \p toGuard
293 The function tries to load \p toGuard and to store it
294 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
296 template <typename T>
297 T protect(size_t nIndex, CDS_ATOMIC::atomic<T> const& toGuard )
301 pRet = assign( nIndex, toGuard.load(CDS_ATOMIC::memory_order_relaxed) );
302 } while ( pRet != toGuard.load(CDS_ATOMIC::memory_order_acquire));
307 /// Protects a pointer of type \p atomic<T*>
309 Return the value of \p toGuard
311 The function tries to load \p toGuard and to store it
312 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
314 The function is useful for intrusive containers when \p toGuard is a node pointer
315 that should be converted to a pointer to the value type before guarding.
316 The parameter \p f of type Func is a functor that makes this conversion:
319 value_type * operator()( T * p );
322 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
324 template <typename T, class Func>
325 T protect(size_t nIndex, CDS_ATOMIC::atomic<T> const& toGuard, Func f )
329 assign( nIndex, f( pRet = toGuard.load(CDS_ATOMIC::memory_order_relaxed) ));
330 } while ( pRet != toGuard.load(CDS_ATOMIC::memory_order_acquire));
335 /// Store \p to the slot \p nIndex
337 The function equals to a simple assignment, no loop is performed.
339 template <typename T>
340 T * assign( size_t nIndex, T * p )
342 base_class::set(nIndex, p);
346 /// Store marked pointer \p p to the guard
348 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
349 Can be used for a marked pointer that cannot be changed concurrently.
351 template <typename T, int Bitmask>
352 T * assign( size_t nIndex, cds::details::marked_ptr<T, Bitmask> p )
354 return assign( nIndex, p.ptr() );
357 /// Copy guarded value from \p src guard to slot at index \p nIndex
358 void copy( size_t nIndex, Guard const& src )
360 assign( nIndex, src.get_native() );
363 /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
364 void copy( size_t nDestIndex, size_t nSrcIndex )
366 assign( nDestIndex, get_native( nSrcIndex ));
369 /// Clear value of the slot \p nIndex
370 void clear( size_t nIndex)
372 base_class::clear( nIndex );
375 /// Get current value of slot \p nIndex
376 template <typename T>
377 T * get( size_t nIndex) const
379 return reinterpret_cast<T *>( get_native( nIndex ) );
382 /// Get native guarded pointer stored
383 guarded_pointer get_native( size_t nIndex ) const
385 return base_class::operator[](nIndex).get_guard()->pPost.load(CDS_ATOMIC::memory_order_relaxed);
388 /// Capacity of the guard array
389 static CDS_CONSTEXPR size_t capacity()
396 /// Initializes ptb::GarbageCollector singleton
398 The constructor calls GarbageCollector::Construct with passed parameters.
399 See ptb::GarbageCollector::Construct for explanation of parameters meaning.
402 size_t nLiberateThreshold = 1024
403 , size_t nInitialThreadGuardCount = 8
406 ptb::GarbageCollector::Construct(
408 nInitialThreadGuardCount
412 /// Terminates ptb::GarbageCollector singleton
414 The destructor calls \code ptb::GarbageCollector::Destruct() \endcode
418 ptb::GarbageCollector::Destruct();
421 /// Checks if count of hazard pointer is no less than \p nCountNeeded
423 The function always returns \p true since the guard count is unlimited for
424 PTB garbage collector.
426 static bool check_available_guards( size_t nCountNeeded, bool /*bRaiseException*/ = true )
428 CDS_UNUSED( nCountNeeded );
432 /// Retire pointer \p p with function \p pFunc
434 The function places pointer \p p to array of pointers ready for removing.
435 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
436 Deleting the pointer is the function \p pFunc call.
438 template <typename T>
439 static void retire( T * p, void (* pFunc)(T *) )
441 ptb::GarbageCollector::instance().retirePtr( p, pFunc );
444 /// Retire pointer \p p with functor of type \p Disposer
446 The function places pointer \p p to array of pointers ready for removing.
447 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
449 See gc::HP::retire for \p Disposer requirements.
451 template <class Disposer, typename T>
452 static void retire( T * p )
454 retire( p, cds::details::static_functor<Disposer, T>::call );
457 /// Checks if Pass-the-Buck GC is constructed and may be used
460 return ptb::GarbageCollector::isUsed();
463 /// Forced GC cycle call for current thread
465 Usually, this function should not be called directly.
467 static void scan() ; // inline in ptb_impl.h
469 /// Synonym for \ref scan()
470 static void force_dispose()
476 }} // namespace cds::gc
478 #endif // #ifndef __CDS_GC_PTB_DECL_H