issue#11: cds: changed __CDS_ guard prefix to CDSLIB_ for all .h files
[libcds.git] / cds / threading / details / gcc_manager.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_THREADING_DETAILS_GCC_MANAGER_H
4 #define CDSLIB_THREADING_DETAILS_GCC_MANAGER_H
5
6 #if !( CDS_COMPILER == CDS_COMPILER_GCC || CDS_COMPILER == CDS_COMPILER_CLANG || CDS_COMPILER == CDS_COMPILER_INTEL)
7 #   error "threading/details/gcc_manager.h may be used only with GCC or Clang C++ compiler"
8 #endif
9
10 #include <cds/threading/details/_common.h>
11
12 //@cond
13 namespace cds { namespace threading {
14
15     //@cond
16     struct gcc_internal {
17         typedef unsigned char  ThreadDataPlaceholder[ sizeof(ThreadData) ];
18         static __thread ThreadDataPlaceholder CDS_DATA_ALIGNMENT(8) s_threadData;
19         static __thread ThreadData * s_pThreadData;
20     };
21     //@endcond
22
23     /// cds::threading::Manager implementation based on GCC __thread declaration
24     CDS_CXX11_INLINE_NAMESPACE namespace gcc {
25
26         /// Thread-specific data manager based on GCC __thread feature
27         class Manager {
28         private :
29             //@cond
30
31             static ThreadData * _threadData()
32             {
33                 return gcc_internal::s_pThreadData;
34             }
35
36             static ThreadData * create_thread_data()
37             {
38                 if ( !gcc_internal::s_pThreadData ) {
39                     gcc_internal::s_pThreadData = new (gcc_internal::s_threadData) ThreadData();
40                 }
41                 return gcc_internal::s_pThreadData;
42             }
43
44             static void destroy_thread_data()
45             {
46                 if ( gcc_internal::s_pThreadData ) {
47                     ThreadData * p = gcc_internal::s_pThreadData;
48                     gcc_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 );
107                 return *(_threadData()->m_hpManager);
108             }
109
110             /// Get gc::DHP 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::DHP.
114                 To initialize gc::DHP GC you must constuct cds::gc::DHP object in the beginning of your application
115             */
116             static gc::DHP::thread_gc_impl&   getDHPGC()
117             {
118                 assert( _threadData()->m_dhpManager );
119                 return *(_threadData()->m_dhpManager);
120             }
121
122             //@cond
123             static size_t fake_current_processor()
124             {
125                 return _threadData()->fake_current_processor();
126             }
127             //@endcond
128         };
129
130     } // namespace gcc
131
132 }} // namespace cds::threading
133 //@endcond
134
135 #endif // #ifndef CDSLIB_THREADING_DETAILS_GCC_MANAGER_H