Replace CDS_ATOMIC with namespace atomics
[libcds.git] / cds / urcu / details / gp_decl.h
1 //$$CDS-header$$
2
3 #ifndef _CDS_URCU_DETAILS_GP_DECL_H
4 #define _CDS_URCU_DETAILS_GP_DECL_H
5
6 #include <cds/urcu/details/base.h>
7 #include <cds/details/static_functor.h>
8 #include <cds/details/lib.h>
9
10 //@cond
11 namespace cds { namespace urcu { namespace details {
12
13     // We could derive thread_data from thread_list_record
14     // but in this case m_nAccessControl would have offset != 0
15     // that is not so efficiently
16 #   define CDS_GPURCU_DECLARE_THREAD_DATA(tag_) \
17     template <> struct thread_data<tag_> { \
18         atomics::atomic<uint32_t>        m_nAccessControl ; \
19         thread_list_record< thread_data >   m_list ; \
20         thread_data(): m_nAccessControl(0) {} \
21         ~thread_data() {} \
22     }
23
24     CDS_GPURCU_DECLARE_THREAD_DATA( general_instant_tag );
25     CDS_GPURCU_DECLARE_THREAD_DATA( general_buffered_tag );
26     CDS_GPURCU_DECLARE_THREAD_DATA( general_threaded_tag );
27
28 #   undef CDS_GPURCU_DECLARE_THREAD_DATA
29
30     template <typename RCUtag>
31     struct gp_singleton_instance
32     {
33         static CDS_EXPORT_API singleton_vtbl *     s_pRCU;
34     };
35 #if !( CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS))
36     template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_instant_tag >::s_pRCU;
37     template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_buffered_tag >::s_pRCU;
38     template<> CDS_EXPORT_API singleton_vtbl * gp_singleton_instance< general_threaded_tag >::s_pRCU;
39 #endif
40
41     template <typename GPRCUtag>
42     class gp_thread_gc
43     {
44     public:
45         typedef GPRCUtag                    rcu_tag;
46         typedef typename rcu_tag::rcu_class rcu_class;
47         typedef thread_data< rcu_tag >      thread_record;
48         typedef cds::urcu::details::scoped_lock< gp_thread_gc > scoped_lock;
49
50     protected:
51         static thread_record * get_thread_record();
52
53     public:
54         gp_thread_gc();
55         ~gp_thread_gc();
56     public:
57         static void access_lock();
58         static void access_unlock();
59         static bool is_locked();
60
61         /// Retire pointer \p by the disposer \p Disposer
62         template <typename Disposer, typename T>
63         static void retire( T * p )
64         {
65             retire( p, cds::details::static_functor<Disposer, T>::call );
66         }
67
68         /// Retire pointer \p by the disposer \p pFunc
69         template <typename T>
70         static void retire( T * p, void (* pFunc)(T *) )
71         {
72             retired_ptr rp( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc ) );
73             retire( rp );
74         }
75
76         /// Retire pointer \p
77         static void retire( retired_ptr& p )
78         {
79             assert( gp_singleton_instance< rcu_tag >::s_pRCU );
80             gp_singleton_instance< rcu_tag >::s_pRCU->retire_ptr( p );
81         }
82     };
83
84 #   define CDS_GP_RCU_DECLARE_THREAD_GC( tag_ ) template <> class thread_gc<tag_>: public gp_thread_gc<tag_> {}
85
86     CDS_GP_RCU_DECLARE_THREAD_GC( general_instant_tag  );
87     CDS_GP_RCU_DECLARE_THREAD_GC( general_buffered_tag );
88     CDS_GP_RCU_DECLARE_THREAD_GC( general_threaded_tag );
89
90 #   undef CDS_GP_RCU_DECLARE_THREAD_GC
91
92     template <class RCUtag>
93     class gp_singleton: public singleton_vtbl
94     {
95     public:
96         typedef RCUtag  rcu_tag;
97         typedef cds::urcu::details::thread_gc< rcu_tag >   thread_gc;
98
99     protected:
100         typedef typename thread_gc::thread_record   thread_record;
101         typedef gp_singleton_instance< rcu_tag >    rcu_instance;
102
103     protected:
104         atomics::atomic<uint32_t>    m_nGlobalControl;
105         thread_list< rcu_tag >          m_ThreadList;
106
107     protected:
108         gp_singleton()
109             : m_nGlobalControl(1)
110         {}
111
112         ~gp_singleton()
113         {}
114
115     public:
116         static gp_singleton * instance()
117         {
118             return static_cast< gp_singleton *>( rcu_instance::s_pRCU );
119         }
120
121         static bool isUsed()
122         {
123             return rcu_instance::s_pRCU != nullptr;
124         }
125
126     public:
127         virtual void retire_ptr( retired_ptr& p ) = 0;
128
129     public: // thread_gc interface
130         thread_record * attach_thread()
131         {
132             return m_ThreadList.alloc();
133         }
134
135         void detach_thread( thread_record * pRec )
136         {
137             m_ThreadList.retire( pRec );
138         }
139
140         uint32_t global_control_word( atomics::memory_order mo ) const
141         {
142             return m_nGlobalControl.load( mo );
143         }
144
145     protected:
146         bool check_grace_period( thread_record * pRec ) const;
147
148         template <class Backoff>
149         void flip_and_wait( Backoff& bkoff );
150     };
151
152 #   define CDS_GP_RCU_DECLARE_SINGLETON( tag_ ) \
153     template <> class singleton< tag_ > { \
154     public: \
155         typedef tag_  rcu_tag ; \
156         typedef cds::urcu::details::thread_gc< rcu_tag >   thread_gc ; \
157     protected: \
158         typedef thread_gc::thread_record            thread_record ; \
159         typedef gp_singleton_instance< rcu_tag >    rcu_instance  ; \
160         typedef gp_singleton< rcu_tag >             rcu_singleton ; \
161     public: \
162         static bool isUsed() { return rcu_singleton::isUsed() ; } \
163         static rcu_singleton * instance() { assert( rcu_instance::s_pRCU ); return static_cast<rcu_singleton *>( rcu_instance::s_pRCU ); } \
164         static thread_record * attach_thread() { return instance()->attach_thread() ; } \
165         static void detach_thread( thread_record * pRec ) { return instance()->detach_thread( pRec ) ; } \
166         static uint32_t global_control_word( atomics::memory_order mo ) { return instance()->global_control_word( mo ) ; } \
167     }
168
169     CDS_GP_RCU_DECLARE_SINGLETON( general_instant_tag  );
170     CDS_GP_RCU_DECLARE_SINGLETON( general_buffered_tag );
171     CDS_GP_RCU_DECLARE_SINGLETON( general_threaded_tag );
172
173 #   undef CDS_GP_RCU_DECLARE_SINGLETON
174
175 }}} // namespace cds::urcu::details
176 //@endcond
177
178 #endif // #ifndef _CDS_URCU_DETAILS_GP_DECL_H