2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
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_GP_DECL_H
32 #define CDSLIB_URCU_DETAILS_GP_DECL_H
34 #include <cds/urcu/details/base.h>
35 #include <cds/details/static_functor.h>
36 #include <cds/details/lib.h>
39 namespace cds { namespace urcu { namespace details {
41 // We could derive thread_data from thread_list_record
42 // but in this case m_nAccessControl would have offset != 0
43 // that is not so efficiently
44 # define CDS_GPURCU_DECLARE_THREAD_DATA(tag_) \
45 template <> struct thread_data<tag_> { \
46 atomics::atomic<uint32_t> m_nAccessControl ; \
47 thread_list_record< thread_data > m_list ; \
48 thread_data(): m_nAccessControl(0) {} \
49 explicit thread_data( OS::ThreadId owner ): m_nAccessControl(0), m_list(owner) {} \
53 CDS_GPURCU_DECLARE_THREAD_DATA( general_instant_tag );
54 CDS_GPURCU_DECLARE_THREAD_DATA( general_buffered_tag );
55 CDS_GPURCU_DECLARE_THREAD_DATA( general_threaded_tag );
57 # undef CDS_GPURCU_DECLARE_THREAD_DATA
59 template <typename RCUtag>
60 struct gp_singleton_instance
62 static CDS_EXPORT_API singleton_vtbl * s_pRCU;
64 #if !( CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS))
65 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_instant_tag >::s_pRCU;
66 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_buffered_tag >::s_pRCU;
67 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_threaded_tag >::s_pRCU;
70 template <typename GPRCUtag>
74 typedef GPRCUtag rcu_tag;
75 typedef typename rcu_tag::rcu_class rcu_class;
76 typedef thread_data< rcu_tag > thread_record;
77 typedef cds::urcu::details::scoped_lock< gp_thread_gc > scoped_lock;
80 static thread_record * get_thread_record();
86 static void access_lock();
87 static void access_unlock();
88 static bool is_locked();
90 /// Retire pointer \p by the disposer \p Disposer
91 template <typename Disposer, typename T>
92 static void retire( T * p )
94 retire( p, cds::details::static_functor<Disposer, T>::call );
97 /// Retire pointer \p by the disposer \p pFunc
99 static void retire( T * p, void (* pFunc)(T *))
101 retired_ptr rp( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc ));
105 /// Retire pointer \p
106 static void retire( retired_ptr& p )
108 assert( gp_singleton_instance< rcu_tag >::s_pRCU );
109 gp_singleton_instance< rcu_tag >::s_pRCU->retire_ptr( p );
113 # define CDS_GP_RCU_DECLARE_THREAD_GC( tag_ ) template <> class thread_gc<tag_>: public gp_thread_gc<tag_> {}
115 CDS_GP_RCU_DECLARE_THREAD_GC( general_instant_tag );
116 CDS_GP_RCU_DECLARE_THREAD_GC( general_buffered_tag );
117 CDS_GP_RCU_DECLARE_THREAD_GC( general_threaded_tag );
119 # undef CDS_GP_RCU_DECLARE_THREAD_GC
121 template <class RCUtag>
122 class gp_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 gp_singleton_instance< rcu_tag > rcu_instance;
133 atomics::atomic<uint32_t> m_nGlobalControl;
134 thread_list< rcu_tag > m_ThreadList;
138 : m_nGlobalControl(1)
145 static gp_singleton * instance()
147 return static_cast< gp_singleton *>( rcu_instance::s_pRCU );
152 return rcu_instance::s_pRCU != nullptr;
156 virtual void retire_ptr( retired_ptr& p ) = 0;
158 public: // thread_gc interface
159 thread_record * attach_thread()
161 return m_ThreadList.alloc();
164 void detach_thread( thread_record * pRec )
166 m_ThreadList.retire( pRec );
169 uint32_t global_control_word( atomics::memory_order mo ) const
171 return m_nGlobalControl.load( mo );
175 bool check_grace_period( thread_record * pRec ) const;
177 template <class Backoff>
178 void flip_and_wait( Backoff& bkoff );
181 # define CDS_GP_RCU_DECLARE_SINGLETON( tag_ ) \
182 template <> class singleton< tag_ > { \
184 typedef tag_ rcu_tag ; \
185 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc ; \
187 typedef thread_gc::thread_record thread_record ; \
188 typedef gp_singleton_instance< rcu_tag > rcu_instance ; \
189 typedef gp_singleton< rcu_tag > rcu_singleton ; \
191 static bool isUsed() { return rcu_singleton::isUsed() ; } \
192 static rcu_singleton * instance() { assert( rcu_instance::s_pRCU ); return static_cast<rcu_singleton *>( rcu_instance::s_pRCU ); } \
193 static thread_record * attach_thread() { return instance()->attach_thread() ; } \
194 static void detach_thread( thread_record * pRec ) { return instance()->detach_thread( pRec ) ; } \
195 static uint32_t global_control_word( atomics::memory_order mo ) { return instance()->global_control_word( mo ) ; } \
198 CDS_GP_RCU_DECLARE_SINGLETON( general_instant_tag );
199 CDS_GP_RCU_DECLARE_SINGLETON( general_buffered_tag );
200 CDS_GP_RCU_DECLARE_SINGLETON( general_threaded_tag );
202 # undef CDS_GP_RCU_DECLARE_SINGLETON
204 }}} // namespace cds::urcu::details
207 #endif // #ifndef CDSLIB_URCU_DETAILS_GP_DECL_H