2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CDSLIB_URCU_DETAILS_SH_DECL_H
32 #define CDSLIB_URCU_DETAILS_SH_DECL_H
34 #include <cds/urcu/details/base.h>
36 #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
37 #include <cds/details/static_functor.h>
38 #include <cds/details/lib.h>
43 namespace cds { namespace urcu { namespace details {
45 // We could derive thread_data from thread_list_record
46 // but in this case m_nAccessControl would have offset != 0
47 // that is not so efficiently
48 # define CDS_SHURCU_DECLARE_THREAD_DATA(tag_) \
49 template <> struct thread_data<tag_> { \
50 atomics::atomic<uint32_t> m_nAccessControl ; \
51 atomics::atomic<bool> m_bNeedMemBar ; \
52 thread_list_record< thread_data > m_list ; \
53 thread_data(): m_nAccessControl(0), m_bNeedMemBar(false) {} \
54 explicit thread_data( OS::ThreadId owner ): m_nAccessControl(0), m_bNeedMemBar(false), m_list(owner) {} \
58 CDS_SHURCU_DECLARE_THREAD_DATA( signal_buffered_tag );
60 # undef CDS_SHURCU_DECLARE_THREAD_DATA
62 template <typename RCUtag>
63 struct sh_singleton_instance
65 static CDS_EXPORT_API singleton_vtbl * s_pRCU;
67 #if CDS_COMPILER != CDS_COMPILER_MSVC
68 template<> CDS_EXPORT_API singleton_vtbl * sh_singleton_instance< signal_buffered_tag >::s_pRCU;
71 template <typename SigRCUtag>
75 typedef SigRCUtag rcu_tag;
76 typedef typename rcu_tag::rcu_class rcu_class;
77 typedef thread_data< rcu_tag > thread_record;
78 typedef cds::urcu::details::scoped_lock< sh_thread_gc > scoped_lock;
81 static thread_record * get_thread_record();
88 static void access_lock();
89 static void access_unlock();
90 static bool is_locked();
92 /// Retire pointer \p by the disposer \p Disposer
93 template <typename Disposer, typename T>
94 static void retire( T * p )
96 retire( p, cds::details::static_functor<Disposer, T>::call );
99 /// Retire pointer \p by the disposer \p pFunc
100 template <typename T>
101 static void retire( T * p, void (* pFunc)(T *))
103 retired_ptr rp( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc ));
107 /// Retire pointer \p
108 static void retire( retired_ptr& p )
110 assert( sh_singleton_instance< rcu_tag >::s_pRCU );
111 sh_singleton_instance< rcu_tag >::s_pRCU->retire_ptr( p );
115 # define CDS_SH_RCU_DECLARE_THREAD_GC( tag_ ) template <> class thread_gc<tag_>: public sh_thread_gc<tag_> {}
117 CDS_SH_RCU_DECLARE_THREAD_GC( signal_buffered_tag );
119 # undef CDS_SH_RCU_DECLARE_THREAD_GC
121 template <class RCUtag>
122 class sh_singleton: public singleton_vtbl
125 typedef RCUtag rcu_tag;
126 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc;
129 typedef typename thread_gc::thread_record thread_record;
130 typedef sh_singleton_instance< rcu_tag > rcu_instance;
133 atomics::atomic<uint32_t> m_nGlobalControl;
134 thread_list< rcu_tag > m_ThreadList;
138 sh_singleton( int nSignal )
139 : m_nGlobalControl(1)
140 , m_nSigNo( nSignal )
142 set_signal_handler();
147 clear_signal_handler();
151 static sh_singleton * instance()
153 return static_cast< sh_singleton *>( rcu_instance::s_pRCU );
158 return rcu_instance::s_pRCU != nullptr;
161 int signal_no() const
167 virtual void retire_ptr( retired_ptr& p ) = 0;
169 public: // thread_gc interface
170 thread_record * attach_thread()
172 return m_ThreadList.alloc();
175 void detach_thread( thread_record * pRec )
177 m_ThreadList.retire( pRec );
180 uint32_t global_control_word( atomics::memory_order mo ) const
182 return m_nGlobalControl.load( mo );
186 void set_signal_handler();
187 void clear_signal_handler();
188 static void signal_handler( int signo, siginfo_t * sigInfo, void * context );
189 void raise_signal( cds::OS::ThreadId tid );
191 template <class Backoff>
192 void force_membar_all_threads( Backoff& bkOff );
194 void switch_next_epoch()
196 m_nGlobalControl.fetch_xor( rcu_tag::c_nControlBit, atomics::memory_order_seq_cst );
198 bool check_grace_period( thread_record * pRec ) const;
200 template <class Backoff>
201 void wait_for_quiescent_state( Backoff& bkOff );
204 # define CDS_SIGRCU_DECLARE_SINGLETON( tag_ ) \
205 template <> class singleton< tag_ > { \
207 typedef tag_ rcu_tag ; \
208 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc ; \
210 typedef thread_gc::thread_record thread_record ; \
211 typedef sh_singleton_instance< rcu_tag > rcu_instance ; \
212 typedef sh_singleton< rcu_tag > rcu_singleton ; \
214 static bool isUsed() { return rcu_singleton::isUsed() ; } \
215 static rcu_singleton * instance() { assert( rcu_instance::s_pRCU ); return static_cast<rcu_singleton *>( rcu_instance::s_pRCU ); } \
216 static thread_record * attach_thread() { return instance()->attach_thread() ; } \
217 static void detach_thread( thread_record * pRec ) { return instance()->detach_thread( pRec ) ; } \
218 static uint32_t global_control_word( atomics::memory_order mo ) { return instance()->global_control_word( mo ) ; } \
221 CDS_SIGRCU_DECLARE_SINGLETON( signal_buffered_tag );
223 # undef CDS_SIGRCU_DECLARE_SINGLETON
225 }}} // namespace cds::urcu::details
228 #endif // #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
229 #endif // #ifndef CDSLIB_URCU_DETAILS_SH_DECL_H