3 #ifndef _CDS_URCU_DETAILS_SH_DECL_H
4 #define _CDS_URCU_DETAILS_SH_DECL_H
6 #include <cds/urcu/details/base.h>
8 #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
9 #include <cds/details/static_functor.h>
10 #include <cds/details/lib.h>
15 namespace cds { namespace urcu { namespace details {
17 // We could derive thread_data from thread_list_record
18 // but in this case m_nAccessControl would have offset != 0
19 // that is not so efficiently
20 # define CDS_SHURCU_DECLARE_THREAD_DATA(tag_) \
21 template <> struct thread_data<tag_> { \
22 CDS_ATOMIC::atomic<uint32_t> m_nAccessControl ; \
23 CDS_ATOMIC::atomic<bool> m_bNeedMemBar ; \
24 thread_list_record< thread_data > m_list ; \
25 thread_data(): m_nAccessControl(0), m_bNeedMemBar(false) {} \
29 CDS_SHURCU_DECLARE_THREAD_DATA( signal_buffered_tag );
30 CDS_SHURCU_DECLARE_THREAD_DATA( signal_threaded_tag );
32 # undef CDS_SHURCU_DECLARE_THREAD_DATA
34 template <typename RCUtag>
35 struct sh_singleton_instance
37 static CDS_EXPORT_API singleton_vtbl * s_pRCU;
39 #if CDS_COMPILER != CDS_COMPILER_MSVC
40 template<> CDS_EXPORT_API singleton_vtbl * sh_singleton_instance< signal_buffered_tag >::s_pRCU;
41 template<> CDS_EXPORT_API singleton_vtbl * sh_singleton_instance< signal_threaded_tag >::s_pRCU;
44 template <typename SigRCUtag>
48 typedef SigRCUtag rcu_tag;
49 typedef typename rcu_tag::rcu_class rcu_class;
50 typedef thread_data< rcu_tag > thread_record;
51 typedef cds::urcu::details::scoped_lock< sh_thread_gc > scoped_lock;
54 static thread_record * get_thread_record();
60 static void access_lock();
61 static void access_unlock();
62 static bool is_locked();
64 /// Retire pointer \p by the disposer \p Disposer
65 template <typename Disposer, typename T>
66 static void retire( T * p )
68 retire( p, cds::details::static_functor<Disposer, T>::call );
71 /// Retire pointer \p by the disposer \p pFunc
73 static void retire( T * p, void (* pFunc)(T *) )
75 retired_ptr rp( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc ) );
80 static void retire( retired_ptr& p )
82 assert( sh_singleton_instance< rcu_tag >::s_pRCU );
83 sh_singleton_instance< rcu_tag >::s_pRCU->retire_ptr( p );
87 # define CDS_SH_RCU_DECLARE_THREAD_GC( tag_ ) template <> class thread_gc<tag_>: public sh_thread_gc<tag_> {}
89 CDS_SH_RCU_DECLARE_THREAD_GC( signal_buffered_tag );
90 CDS_SH_RCU_DECLARE_THREAD_GC( signal_threaded_tag );
92 # undef CDS_SH_RCU_DECLARE_THREAD_GC
94 template <class RCUtag>
95 class sh_singleton: public singleton_vtbl
98 typedef RCUtag rcu_tag;
99 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc;
102 typedef typename thread_gc::thread_record thread_record;
103 typedef sh_singleton_instance< rcu_tag > rcu_instance;
106 CDS_ATOMIC::atomic<uint32_t> m_nGlobalControl;
107 thread_list< rcu_tag > m_ThreadList;
111 sh_singleton( int nSignal )
112 : m_nGlobalControl(1)
113 , m_nSigNo( nSignal )
115 set_signal_handler();
120 clear_signal_handler();
124 static sh_singleton * instance()
126 return static_cast< sh_singleton *>( rcu_instance::s_pRCU );
131 return rcu_instance::s_pRCU != NULL;
134 int signal_no() const
140 virtual void retire_ptr( retired_ptr& p ) = 0;
142 public: // thread_gc interface
143 thread_record * attach_thread()
145 return m_ThreadList.alloc();
148 void detach_thread( thread_record * pRec )
150 m_ThreadList.retire( pRec );
153 uint32_t global_control_word( CDS_ATOMIC::memory_order mo ) const
155 return m_nGlobalControl.load( mo );
159 void set_signal_handler();
160 void clear_signal_handler();
161 static void signal_handler( int signo, siginfo_t * sigInfo, void * context );
162 void raise_signal( std::thread::id tid );
164 template <class Backoff>
165 void force_membar_all_threads( Backoff& bkOff );
167 void switch_next_epoch()
169 m_nGlobalControl.fetch_xor( rcu_tag::c_nControlBit, CDS_ATOMIC::memory_order_seq_cst );
171 bool check_grace_period( thread_record * pRec ) const;
173 template <class Backoff>
174 void wait_for_quiescent_state( Backoff& bkOff );
177 # define CDS_SIGRCU_DECLARE_SINGLETON( tag_ ) \
178 template <> class singleton< tag_ > { \
180 typedef tag_ rcu_tag ; \
181 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc ; \
183 typedef thread_gc::thread_record thread_record ; \
184 typedef sh_singleton_instance< rcu_tag > rcu_instance ; \
185 typedef sh_singleton< rcu_tag > rcu_singleton ; \
187 static bool isUsed() { return rcu_singleton::isUsed() ; } \
188 static rcu_singleton * instance() { assert( rcu_instance::s_pRCU ); return static_cast<rcu_singleton *>( rcu_instance::s_pRCU ); } \
189 static thread_record * attach_thread() { return instance()->attach_thread() ; } \
190 static void detach_thread( thread_record * pRec ) { return instance()->detach_thread( pRec ) ; } \
191 static uint32_t global_control_word( CDS_ATOMIC::memory_order mo ) { return instance()->global_control_word( mo ) ; } \
194 CDS_SIGRCU_DECLARE_SINGLETON( signal_buffered_tag );
195 CDS_SIGRCU_DECLARE_SINGLETON( signal_threaded_tag );
197 # undef CDS_SIGRCU_DECLARE_SINGLETON
199 }}} // namespace cds::urcu::details
202 #endif // #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
203 #endif // #ifndef _CDS_URCU_DETAILS_SH_DECL_H