3 #ifndef CDSLIB_URCU_DETAILS_GP_DECL_H
4 #define CDSLIB_URCU_DETAILS_GP_DECL_H
6 #include <cds/urcu/details/base.h>
7 #include <cds/details/static_functor.h>
8 #include <cds/details/lib.h>
11 namespace cds { namespace urcu { namespace details {
13 // We could derive thread_data from thread_list_record
14 // but in this case m_nAccessControl would have offset != 0
15 // that is not so efficiently
16 # define CDS_GPURCU_DECLARE_THREAD_DATA(tag_) \
17 template <> struct thread_data<tag_> { \
18 atomics::atomic<uint32_t> m_nAccessControl ; \
19 thread_list_record< thread_data > m_list ; \
20 thread_data(): m_nAccessControl(0) {} \
24 CDS_GPURCU_DECLARE_THREAD_DATA( general_instant_tag );
25 CDS_GPURCU_DECLARE_THREAD_DATA( general_buffered_tag );
26 CDS_GPURCU_DECLARE_THREAD_DATA( general_threaded_tag );
28 # undef CDS_GPURCU_DECLARE_THREAD_DATA
30 template <typename RCUtag>
31 struct gp_singleton_instance
33 static CDS_EXPORT_API singleton_vtbl * s_pRCU;
35 #if !( CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS))
36 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_instant_tag >::s_pRCU;
37 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_buffered_tag >::s_pRCU;
38 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_threaded_tag >::s_pRCU;
41 template <typename GPRCUtag>
45 typedef GPRCUtag rcu_tag;
46 typedef typename rcu_tag::rcu_class rcu_class;
47 typedef thread_data< rcu_tag > thread_record;
48 typedef cds::urcu::details::scoped_lock< gp_thread_gc > scoped_lock;
51 static thread_record * get_thread_record();
57 static void access_lock();
58 static void access_unlock();
59 static bool is_locked();
61 /// Retire pointer \p by the disposer \p Disposer
62 template <typename Disposer, typename T>
63 static void retire( T * p )
65 retire( p, cds::details::static_functor<Disposer, T>::call );
68 /// Retire pointer \p by the disposer \p pFunc
70 static void retire( T * p, void (* pFunc)(T *) )
72 retired_ptr rp( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc ) );
77 static void retire( retired_ptr& p )
79 assert( gp_singleton_instance< rcu_tag >::s_pRCU );
80 gp_singleton_instance< rcu_tag >::s_pRCU->retire_ptr( p );
84 # define CDS_GP_RCU_DECLARE_THREAD_GC( tag_ ) template <> class thread_gc<tag_>: public gp_thread_gc<tag_> {}
86 CDS_GP_RCU_DECLARE_THREAD_GC( general_instant_tag );
87 CDS_GP_RCU_DECLARE_THREAD_GC( general_buffered_tag );
88 CDS_GP_RCU_DECLARE_THREAD_GC( general_threaded_tag );
90 # undef CDS_GP_RCU_DECLARE_THREAD_GC
92 template <class RCUtag>
93 class gp_singleton: public singleton_vtbl
96 typedef RCUtag rcu_tag;
97 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc;
100 typedef typename thread_gc::thread_record thread_record;
101 typedef gp_singleton_instance< rcu_tag > rcu_instance;
104 atomics::atomic<uint32_t> m_nGlobalControl;
105 thread_list< rcu_tag > m_ThreadList;
109 : m_nGlobalControl(1)
116 static gp_singleton * instance()
118 return static_cast< gp_singleton *>( rcu_instance::s_pRCU );
123 return rcu_instance::s_pRCU != nullptr;
127 virtual void retire_ptr( retired_ptr& p ) = 0;
129 public: // thread_gc interface
130 thread_record * attach_thread()
132 return m_ThreadList.alloc();
135 void detach_thread( thread_record * pRec )
137 m_ThreadList.retire( pRec );
140 uint32_t global_control_word( atomics::memory_order mo ) const
142 return m_nGlobalControl.load( mo );
146 bool check_grace_period( thread_record * pRec ) const;
148 template <class Backoff>
149 void flip_and_wait( Backoff& bkoff );
152 # define CDS_GP_RCU_DECLARE_SINGLETON( tag_ ) \
153 template <> class singleton< tag_ > { \
155 typedef tag_ rcu_tag ; \
156 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc ; \
158 typedef thread_gc::thread_record thread_record ; \
159 typedef gp_singleton_instance< rcu_tag > rcu_instance ; \
160 typedef gp_singleton< rcu_tag > rcu_singleton ; \
162 static bool isUsed() { return rcu_singleton::isUsed() ; } \
163 static rcu_singleton * instance() { assert( rcu_instance::s_pRCU ); return static_cast<rcu_singleton *>( rcu_instance::s_pRCU ); } \
164 static thread_record * attach_thread() { return instance()->attach_thread() ; } \
165 static void detach_thread( thread_record * pRec ) { return instance()->detach_thread( pRec ) ; } \
166 static uint32_t global_control_word( atomics::memory_order mo ) { return instance()->global_control_word( mo ) ; } \
169 CDS_GP_RCU_DECLARE_SINGLETON( general_instant_tag );
170 CDS_GP_RCU_DECLARE_SINGLETON( general_buffered_tag );
171 CDS_GP_RCU_DECLARE_SINGLETON( general_threaded_tag );
173 # undef CDS_GP_RCU_DECLARE_SINGLETON
175 }}} // namespace cds::urcu::details
178 #endif // #ifndef CDSLIB_URCU_DETAILS_GP_DECL_H