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) {} \
52 CDS_GPURCU_DECLARE_THREAD_DATA( general_instant_tag );
53 CDS_GPURCU_DECLARE_THREAD_DATA( general_buffered_tag );
54 CDS_GPURCU_DECLARE_THREAD_DATA( general_threaded_tag );
56 # undef CDS_GPURCU_DECLARE_THREAD_DATA
58 template <typename RCUtag>
59 struct gp_singleton_instance
61 static CDS_EXPORT_API singleton_vtbl * s_pRCU;
63 #if !( CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS))
64 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_instant_tag >::s_pRCU;
65 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_buffered_tag >::s_pRCU;
66 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_threaded_tag >::s_pRCU;
69 template <typename GPRCUtag>
73 typedef GPRCUtag rcu_tag;
74 typedef typename rcu_tag::rcu_class rcu_class;
75 typedef thread_data< rcu_tag > thread_record;
76 typedef cds::urcu::details::scoped_lock< gp_thread_gc > scoped_lock;
79 static thread_record * get_thread_record();
85 static void access_lock();
86 static void access_unlock();
87 static bool is_locked();
89 /// Retire pointer \p by the disposer \p Disposer
90 template <typename Disposer, typename T>
91 static void retire( T * p )
93 retire( p, cds::details::static_functor<Disposer, T>::call );
96 /// Retire pointer \p by the disposer \p pFunc
98 static void retire( T * p, void (* pFunc)(T *))
100 retired_ptr rp( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc ));
104 /// Retire pointer \p
105 static void retire( retired_ptr& p )
107 assert( gp_singleton_instance< rcu_tag >::s_pRCU );
108 gp_singleton_instance< rcu_tag >::s_pRCU->retire_ptr( p );
112 # define CDS_GP_RCU_DECLARE_THREAD_GC( tag_ ) template <> class thread_gc<tag_>: public gp_thread_gc<tag_> {}
114 CDS_GP_RCU_DECLARE_THREAD_GC( general_instant_tag );
115 CDS_GP_RCU_DECLARE_THREAD_GC( general_buffered_tag );
116 CDS_GP_RCU_DECLARE_THREAD_GC( general_threaded_tag );
118 # undef CDS_GP_RCU_DECLARE_THREAD_GC
120 template <class RCUtag>
121 class gp_singleton: public singleton_vtbl
124 typedef RCUtag rcu_tag;
125 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc;
128 typedef typename thread_gc::thread_record thread_record;
129 typedef gp_singleton_instance< rcu_tag > rcu_instance;
132 atomics::atomic<uint32_t> m_nGlobalControl;
133 thread_list< rcu_tag > m_ThreadList;
137 : m_nGlobalControl(1)
144 static gp_singleton * instance()
146 return static_cast< gp_singleton *>( rcu_instance::s_pRCU );
151 return rcu_instance::s_pRCU != nullptr;
155 virtual void retire_ptr( retired_ptr& p ) = 0;
157 public: // thread_gc interface
158 thread_record * attach_thread()
160 return m_ThreadList.alloc();
163 void detach_thread( thread_record * pRec )
165 m_ThreadList.retire( pRec );
168 uint32_t global_control_word( atomics::memory_order mo ) const
170 return m_nGlobalControl.load( mo );
174 bool check_grace_period( thread_record * pRec ) const;
176 template <class Backoff>
177 void flip_and_wait( Backoff& bkoff );
180 # define CDS_GP_RCU_DECLARE_SINGLETON( tag_ ) \
181 template <> class singleton< tag_ > { \
183 typedef tag_ rcu_tag ; \
184 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc ; \
186 typedef thread_gc::thread_record thread_record ; \
187 typedef gp_singleton_instance< rcu_tag > rcu_instance ; \
188 typedef gp_singleton< rcu_tag > rcu_singleton ; \
190 static bool isUsed() { return rcu_singleton::isUsed() ; } \
191 static rcu_singleton * instance() { assert( rcu_instance::s_pRCU ); return static_cast<rcu_singleton *>( rcu_instance::s_pRCU ); } \
192 static thread_record * attach_thread() { return instance()->attach_thread() ; } \
193 static void detach_thread( thread_record * pRec ) { return instance()->detach_thread( pRec ) ; } \
194 static uint32_t global_control_word( atomics::memory_order mo ) { return instance()->global_control_word( mo ) ; } \
197 CDS_GP_RCU_DECLARE_SINGLETON( general_instant_tag );
198 CDS_GP_RCU_DECLARE_SINGLETON( general_buffered_tag );
199 CDS_GP_RCU_DECLARE_SINGLETON( general_threaded_tag );
201 # undef CDS_GP_RCU_DECLARE_SINGLETON
203 }}} // namespace cds::urcu::details
206 #endif // #ifndef CDSLIB_URCU_DETAILS_GP_DECL_H