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_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>
37 #include <cds/user_setup/cache_line.h>
40 namespace cds { namespace urcu { namespace details {
42 // We could derive thread_data from thread_list_record
43 // but in this case m_nAccessControl would have offset != 0
44 // that is not so efficiently
45 # define CDS_GPURCU_DECLARE_THREAD_DATA(tag_) \
46 template <> struct thread_data<tag_> { \
47 atomics::atomic<uint32_t> m_nAccessControl ; \
48 thread_list_record< thread_data > m_list ; \
49 char pad_[cds::c_nCacheLineSize]; \
50 thread_data(): m_nAccessControl(0) {} \
51 explicit thread_data( OS::ThreadId owner ): m_nAccessControl(0), m_list(owner) {} \
55 CDS_GPURCU_DECLARE_THREAD_DATA( general_instant_tag );
56 CDS_GPURCU_DECLARE_THREAD_DATA( general_buffered_tag );
57 CDS_GPURCU_DECLARE_THREAD_DATA( general_threaded_tag );
59 # undef CDS_GPURCU_DECLARE_THREAD_DATA
61 template <typename RCUtag>
62 struct gp_singleton_instance
64 static CDS_EXPORT_API singleton_vtbl * s_pRCU;
66 #if !( CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS))
67 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_instant_tag >::s_pRCU;
68 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_buffered_tag >::s_pRCU;
69 template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_threaded_tag >::s_pRCU;
72 template <typename GPRCUtag>
76 typedef GPRCUtag rcu_tag;
77 typedef typename rcu_tag::rcu_class rcu_class;
78 typedef thread_data< rcu_tag > thread_record;
79 typedef cds::urcu::details::scoped_lock< gp_thread_gc > scoped_lock;
82 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( gp_singleton_instance< rcu_tag >::s_pRCU );
111 gp_singleton_instance< rcu_tag >::s_pRCU->retire_ptr( p );
115 # define CDS_GP_RCU_DECLARE_THREAD_GC( tag_ ) template <> class thread_gc<tag_>: public gp_thread_gc<tag_> {}
117 CDS_GP_RCU_DECLARE_THREAD_GC( general_instant_tag );
118 CDS_GP_RCU_DECLARE_THREAD_GC( general_buffered_tag );
119 CDS_GP_RCU_DECLARE_THREAD_GC( general_threaded_tag );
121 # undef CDS_GP_RCU_DECLARE_THREAD_GC
123 template <class RCUtag>
124 class gp_singleton: public singleton_vtbl
127 typedef RCUtag rcu_tag;
128 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc;
131 typedef typename thread_gc::thread_record thread_record;
132 typedef gp_singleton_instance< rcu_tag > rcu_instance;
135 atomics::atomic<uint32_t> m_nGlobalControl;
136 thread_list< rcu_tag > m_ThreadList;
140 : m_nGlobalControl(1)
147 static gp_singleton * instance()
149 return static_cast< gp_singleton *>( rcu_instance::s_pRCU );
154 return rcu_instance::s_pRCU != nullptr;
158 virtual void retire_ptr( retired_ptr& p ) = 0;
160 public: // thread_gc interface
161 thread_record * attach_thread()
163 return m_ThreadList.alloc();
166 void detach_thread( thread_record * pRec )
168 m_ThreadList.retire( pRec );
171 uint32_t global_control_word( atomics::memory_order mo ) const
173 return m_nGlobalControl.load( mo );
177 bool check_grace_period( thread_record * pRec ) const;
179 template <class Backoff>
180 void flip_and_wait( Backoff& bkoff );
183 # define CDS_GP_RCU_DECLARE_SINGLETON( tag_ ) \
184 template <> class singleton< tag_ > { \
186 typedef tag_ rcu_tag ; \
187 typedef cds::urcu::details::thread_gc< rcu_tag > thread_gc ; \
189 typedef thread_gc::thread_record thread_record ; \
190 typedef gp_singleton_instance< rcu_tag > rcu_instance ; \
191 typedef gp_singleton< rcu_tag > rcu_singleton ; \
193 static bool isUsed() { return rcu_singleton::isUsed() ; } \
194 static rcu_singleton * instance() { assert( rcu_instance::s_pRCU ); return static_cast<rcu_singleton *>( rcu_instance::s_pRCU ); } \
195 static thread_record * attach_thread() { return instance()->attach_thread() ; } \
196 static void detach_thread( thread_record * pRec ) { return instance()->detach_thread( pRec ) ; } \
197 static uint32_t global_control_word( atomics::memory_order mo ) { return instance()->global_control_word( mo ) ; } \
200 CDS_GP_RCU_DECLARE_SINGLETON( general_instant_tag );
201 CDS_GP_RCU_DECLARE_SINGLETON( general_buffered_tag );
202 CDS_GP_RCU_DECLARE_SINGLETON( general_threaded_tag );
204 # undef CDS_GP_RCU_DECLARE_SINGLETON
206 }}} // namespace cds::urcu::details
209 #endif // #ifndef CDSLIB_URCU_DETAILS_GP_DECL_H