Add support for Intel C++ compiler for Linux (icc 15)
[libcds.git] / cds / threading / details / msvc_manager.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_THREADING_DETAILS_MSVC_MANAGER_H
4 #define __CDS_THREADING_DETAILS_MSVC_MANAGER_H
5
6 #if !( CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS))
7 #   error "threading/details/msvc_manager.h may be used only with Microsoft Visual C++ / Intel 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 msvc_internal {
17         typedef unsigned char  ThreadDataPlaceholder[ sizeof(ThreadData) ];
18         __declspec( thread ) static ThreadDataPlaceholder s_threadData;
19         __declspec( thread ) static ThreadData * s_pThreadData;
20     };
21     //@endcond
22
23     /// cds::threading::Manager implementation based on Microsoft Visual C++ __declspec( thread ) construction
24     CDS_CXX11_INLINE_NAMESPACE namespace msvc {
25
26         /// Thread-specific data manager based on MSVC __declspec( thread ) feature
27         class Manager {
28         private :
29             //@cond
30             static ThreadData * _threadData()
31             {
32                 return msvc_internal::s_pThreadData;
33             }
34
35             static ThreadData * create_thread_data()
36             {
37                 if ( !msvc_internal::s_pThreadData ) {
38                     msvc_internal::s_pThreadData = new (msvc_internal::s_threadData) ThreadData();
39                 }
40                 return msvc_internal::s_pThreadData;
41             }
42
43             static void destroy_thread_data()
44             {
45                 if ( msvc_internal::s_pThreadData ) {
46                     msvc_internal::s_pThreadData->ThreadData::~ThreadData();
47                     msvc_internal::s_pThreadData = nullptr;
48                 }
49             }
50
51             //@endcond
52
53         public:
54             /// Initialize manager (empty function)
55             /**
56                 This function is automatically called by cds::Initialize
57             */
58             static void init()
59             {}
60
61             /// Terminate manager (empty function)
62             /**
63                 This function is automatically called by cds::Terminate
64             */
65             static void fini()
66             {}
67
68             /// Checks whether current thread is attached to \p libcds feature or not.
69             static bool isThreadAttached()
70             {
71                 ThreadData * pData = _threadData();
72                 return pData != 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 internal 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::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 );
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 );
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 msvc
143 }} // namespace cds::threading
144 //@endcond
145
146 #endif // #ifndef __CDS_THREADING_DETAILS_MSVC_MANAGER_H