Replace NULL with nullptr
[libcds.git] / cds / threading / details / cxx11_manager.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_THREADING_DETAILS_CXX11_MANAGER_H
4 #define __CDS_THREADING_DETAILS_CXX11_MANAGER_H
5
6 #include <cds/threading/details/_common.h>
7
8 #ifndef CDS_CXX11_THREAD_LOCAL_SUPPORT
9 #   error "The compiler does not support C++11 thread_local keyword. You cannot use CDS_THREADING_CXX11 threading model."
10 #endif
11
12 //@cond
13 namespace cds { namespace threading {
14
15     //@cond
16     struct cxx11_internal {
17         typedef unsigned char  ThreadDataPlaceholder[ sizeof(ThreadData) ];
18         static thread_local ThreadDataPlaceholder CDS_DATA_ALIGNMENT(8) s_threadData;
19         static thread_local ThreadData * s_pThreadData;
20     };
21     //@endcond
22
23     /// cds::threading::Manager implementation based on c++11 thread_local declaration
24     CDS_CXX11_INLINE_NAMESPACE namespace cxx11 {
25
26         /// Thread-specific data manager based on c++11 thread_local feature
27         class Manager {
28         private :
29             //@cond
30
31             static ThreadData * _threadData()
32             {
33                 return cxx11_internal::s_pThreadData;
34             }
35
36             static ThreadData * create_thread_data()
37             {
38                 if ( !cxx11_internal::s_pThreadData ) {
39                     cxx11_internal::s_pThreadData = new (cxx11_internal::s_threadData) ThreadData();
40                 }
41                 return cxx11_internal::s_pThreadData;
42             }
43
44             static void destroy_thread_data()
45             {
46                 if ( cxx11_internal::s_pThreadData ) {
47                     ThreadData * p = cxx11_internal::s_pThreadData;
48                     cxx11_internal::s_pThreadData = nullptr;
49                     p->ThreadData::~ThreadData();
50                 }
51             }
52             //@endcond
53
54         public:
55             /// Initialize manager (empty function)
56             /**
57                 This function is automatically called by cds::Initialize
58             */
59             static void init()
60             {}
61
62             /// Terminate manager (empty function)
63             /**
64                 This function is automatically called by cds::Terminate
65             */
66             static void fini()
67             {}
68
69             /// Checks whether current thread is attached to \p libcds feature or not.
70             static bool isThreadAttached()
71             {
72                 return _threadData() != nullptr;
73             }
74
75             /// This method must be called in beginning of thread execution
76             static void attachThread()
77             {
78                 create_thread_data()->init();
79             }
80
81             /// This method must be called in end of thread execution
82             static void detachThread()
83             {
84                 assert( _threadData() );
85
86                 if ( _threadData()->fini() )
87                     destroy_thread_data();
88             }
89
90             /// Returns ThreadData pointer for the current thread
91             static ThreadData * thread_data()
92             {
93                 ThreadData * p = _threadData();
94                 assert( p );
95                 return p;
96             }
97
98             /// Get gc::HP thread GC implementation for current thread
99             /**
100                 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
101                 or if you did not use gc::HP.
102                 To initialize gc::HP GC you must constuct cds::gc::HP object in the beginning of your application
103             */
104             static gc::HP::thread_gc_impl&   getHZPGC()
105             {
106                 assert( _threadData()->m_hpManager != nullptr );
107                 return *(_threadData()->m_hpManager);
108             }
109
110             /// Get gc::HRC thread GC implementation for current thread
111             /**
112                 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
113                 or if you did not use gc::HRC.
114                 To initialize gc::HRC GC you must constuct cds::gc::HRC object in the beginning of your application
115             */
116             static gc::HRC::thread_gc_impl&   getHRCGC()
117             {
118                 assert( _threadData()->m_hrcManager != nullptr );
119                 return *(_threadData()->m_hrcManager);
120             }
121
122             /// Get gc::PTB thread GC implementation for current thread
123             /**
124                 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
125                 or if you did not use gc::PTB.
126                 To initialize gc::PTB GC you must constuct cds::gc::PTB object in the beginning of your application
127             */
128             static gc::PTB::thread_gc_impl&   getPTBGC()
129             {
130                 assert( _threadData()->m_ptbManager != nullptr );
131                 return *(_threadData()->m_ptbManager);
132             }
133
134             //@cond
135             static size_t fake_current_processor()
136             {
137                 return _threadData()->fake_current_processor();
138             }
139             //@endcond
140         };
141
142     } // namespace cxx11
143
144 }} // namespace cds::threading
145 //@endcond
146
147 #endif // #ifndef __CDS_THREADING_DETAILS_CXX11_MANAGER_H