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);
228 std::nullptr_t assign( std::nullptr_t )
230 return base_class::operator =(nullptr);
234 /// Store marked pointer \p p to the guard
236 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
237 Can be used for a marked pointer that cannot be changed concurrently.
239 template <typename T, int BITMASK>
240 T * assign( cds::details::marked_ptr<T, BITMASK> p )
242 return base_class::operator =( p.ptr() );
245 /// Copy from \p src guard to \p this guard
246 void copy( Guard const& src )
248 assign( src.get_native() );
251 /// Clear value of the guard
257 /// Get the value currently protected (relaxed read)
258 template <typename T>
261 return reinterpret_cast<T *>( get_native() );
264 /// Get native guarded pointer stored
265 guarded_pointer get_native() const
267 return base_class::get_guard()->pPost.load(CDS_ATOMIC::memory_order_relaxed);
272 /// Array of Pass-the-Buck guards
274 @headerfile cds/gc/ptb.h
275 This class is a wrapper for ptb::GuardArray template.
276 Template parameter \p Count defines the size of PTB array.
278 template <size_t Count>
279 class GuardArray: public ptb::GuardArray<Count>
282 typedef ptb::GuardArray<Count> base_class;
285 /// Rebind array for other size \p COUNT2
286 template <size_t OtherCount>
288 typedef GuardArray<OtherCount> other ; ///< rebinding result
293 GuardArray() ; // inline in ptb_impl.h
296 /// Protects a pointer of type \p atomic<T*>
298 Return the value of \p toGuard
300 The function tries to load \p toGuard and to store it
301 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
303 template <typename T>
304 T protect(size_t nIndex, CDS_ATOMIC::atomic<T> const& toGuard )
308 pRet = assign( nIndex, toGuard.load(CDS_ATOMIC::memory_order_relaxed) );
309 } while ( pRet != toGuard.load(CDS_ATOMIC::memory_order_acquire));
314 /// Protects a pointer of type \p atomic<T*>
316 Return the value of \p toGuard
318 The function tries to load \p toGuard and to store it
319 to the slot \p nIndex repeatedly until the guard's value equals \p toGuard
321 The function is useful for intrusive containers when \p toGuard is a node pointer
322 that should be converted to a pointer to the value type before guarding.
323 The parameter \p f of type Func is a functor that makes this conversion:
326 value_type * operator()( T * p );
329 Really, the result of <tt> f( toGuard.load() ) </tt> is assigned to the hazard pointer.
331 template <typename T, class Func>
332 T protect(size_t nIndex, CDS_ATOMIC::atomic<T> const& toGuard, Func f )
336 assign( nIndex, f( pRet = toGuard.load(CDS_ATOMIC::memory_order_relaxed) ));
337 } while ( pRet != toGuard.load(CDS_ATOMIC::memory_order_acquire));
342 /// Store \p to the slot \p nIndex
344 The function equals to a simple assignment, no loop is performed.
346 template <typename T>
347 T * assign( size_t nIndex, T * p )
349 base_class::set(nIndex, p);
353 /// Store marked pointer \p p to the guard
355 The function equals to a simple assignment of <tt>p.ptr()</tt>, no loop is performed.
356 Can be used for a marked pointer that cannot be changed concurrently.
358 template <typename T, int Bitmask>
359 T * assign( size_t nIndex, cds::details::marked_ptr<T, Bitmask> p )
361 return assign( nIndex, p.ptr() );
364 /// Copy guarded value from \p src guard to slot at index \p nIndex
365 void copy( size_t nIndex, Guard const& src )
367 assign( nIndex, src.get_native() );
370 /// Copy guarded value from slot \p nSrcIndex to slot at index \p nDestIndex
371 void copy( size_t nDestIndex, size_t nSrcIndex )
373 assign( nDestIndex, get_native( nSrcIndex ));
376 /// Clear value of the slot \p nIndex
377 void clear( size_t nIndex)
379 base_class::clear( nIndex );
382 /// Get current value of slot \p nIndex
383 template <typename T>
384 T * get( size_t nIndex) const
386 return reinterpret_cast<T *>( get_native( nIndex ) );
389 /// Get native guarded pointer stored
390 guarded_pointer get_native( size_t nIndex ) const
392 return base_class::operator[](nIndex).get_guard()->pPost.load(CDS_ATOMIC::memory_order_relaxed);
395 /// Capacity of the guard array
396 static CDS_CONSTEXPR size_t capacity()
403 /// Initializes ptb::GarbageCollector singleton
405 The constructor calls GarbageCollector::Construct with passed parameters.
406 See ptb::GarbageCollector::Construct for explanation of parameters meaning.
409 size_t nLiberateThreshold = 1024
410 , size_t nInitialThreadGuardCount = 8
413 ptb::GarbageCollector::Construct(
415 nInitialThreadGuardCount
419 /// Terminates ptb::GarbageCollector singleton
421 The destructor calls \code ptb::GarbageCollector::Destruct() \endcode
425 ptb::GarbageCollector::Destruct();
428 /// Checks if count of hazard pointer is no less than \p nCountNeeded
430 The function always returns \p true since the guard count is unlimited for
431 PTB garbage collector.
433 static bool check_available_guards( size_t nCountNeeded, bool /*bRaiseException*/ = true )
435 CDS_UNUSED( nCountNeeded );
439 /// Retire pointer \p p with function \p pFunc
441 The function places pointer \p p to array of pointers ready for removing.
442 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
443 Deleting the pointer is the function \p pFunc call.
445 template <typename T>
446 static void retire( T * p, void (* pFunc)(T *) )
448 ptb::GarbageCollector::instance().retirePtr( p, pFunc );
451 /// Retire pointer \p p with functor of type \p Disposer
453 The function places pointer \p p to array of pointers ready for removing.
454 (so called retired pointer array). The pointer can be safely removed when no guarded pointer points to it.
456 See gc::HP::retire for \p Disposer requirements.
458 template <class Disposer, typename T>
459 static void retire( T * p )
461 retire( p, cds::details::static_functor<Disposer, T>::call );
464 /// Checks if Pass-the-Buck GC is constructed and may be used
467 return ptb::GarbageCollector::isUsed();
470 /// Forced GC cycle call for current thread
472 Usually, this function should not be called directly.
474 static void scan() ; // inline in ptb_impl.h
476 /// Synonym for \ref scan()
477 static void force_dispose()
483 }} // namespace cds::gc
485 #endif // #ifndef __CDS_GC_PTB_DECL_H