Removed redundant spaces
[libcds.git] / cds / threading / details / msvc_manager.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
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.
18
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.
29 */
30
31 #ifndef CDSLIB_THREADING_DETAILS_MSVC_MANAGER_H
32 #define CDSLIB_THREADING_DETAILS_MSVC_MANAGER_H
33
34 #if !( CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS))
35 #   error "threading/details/msvc_manager.h may be used only with Microsoft Visual C++ / Intel C++ compiler"
36 #endif
37
38 #include <cds/threading/details/_common.h>
39
40 //@cond
41 namespace cds { namespace threading {
42
43     //@cond
44     struct msvc_internal {
45         typedef unsigned char  ThreadDataPlaceholder[ sizeof(ThreadData) ];
46         __declspec( thread ) static ThreadDataPlaceholder s_threadData;
47         __declspec( thread ) static ThreadData * s_pThreadData;
48     };
49     //@endcond
50
51     /// cds::threading::Manager implementation based on Microsoft Visual C++ __declspec( thread ) construction
52     CDS_CXX11_INLINE_NAMESPACE namespace msvc {
53
54         /// Thread-specific data manager based on MSVC __declspec( thread ) feature
55         class Manager {
56         private :
57             //@cond
58             static ThreadData * _threadData()
59             {
60                 return msvc_internal::s_pThreadData;
61             }
62
63             static ThreadData * create_thread_data()
64             {
65                 if ( !msvc_internal::s_pThreadData ) {
66                     msvc_internal::s_pThreadData = new (msvc_internal::s_threadData) ThreadData();
67                 }
68                 return msvc_internal::s_pThreadData;
69             }
70
71             static void destroy_thread_data()
72             {
73                 if ( msvc_internal::s_pThreadData ) {
74                     msvc_internal::s_pThreadData->ThreadData::~ThreadData();
75                     msvc_internal::s_pThreadData = nullptr;
76                 }
77             }
78
79             //@endcond
80
81         public:
82             /// Initialize manager (empty function)
83             /**
84                 This function is automatically called by cds::Initialize
85             */
86             static void init()
87             {}
88
89             /// Terminate manager (empty function)
90             /**
91                 This function is automatically called by cds::Terminate
92             */
93             static void fini()
94             {}
95
96             /// Checks whether current thread is attached to \p libcds feature or not.
97             static bool isThreadAttached()
98             {
99                 ThreadData * pData = _threadData();
100                 return pData != nullptr;
101             }
102
103             /// This method must be called in beginning of thread execution
104             static void attachThread()
105             {
106                 create_thread_data()->init();
107             }
108
109             /// This method must be called in end of thread execution
110             static void detachThread()
111             {
112                 assert( _threadData());
113
114                 if ( _threadData()->fini())
115                     destroy_thread_data();
116             }
117
118             /// Returns internal ThreadData pointer for the current thread
119             static ThreadData * thread_data()
120             {
121                 ThreadData * p = _threadData();
122                 assert( p );
123                 return p;
124             }
125
126             /// Get gc::HP thread GC implementation for current thread
127             /**
128                 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
129                 or if you did not use gc::HP.
130                 To initialize gc::HP GC you must constuct cds::gc::HP object in the beginning of your application
131             */
132             static gc::HP::thread_gc_impl&   getHZPGC()
133             {
134                 assert( _threadData()->m_hpManager );
135                 return *(_threadData()->m_hpManager);
136             }
137
138             /// Get gc::DHP thread GC implementation for current thread
139             /**
140                 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
141                 or if you did not use gc::DHP.
142                 To initialize gc::DHP GC you must constuct cds::gc::DHP object in the beginning of your application
143             */
144             static gc::DHP::thread_gc_impl&   getDHPGC()
145             {
146                 assert( _threadData()->m_dhpManager );
147                 return *(_threadData()->m_dhpManager);
148             }
149
150             //@cond
151             static size_t fake_current_processor()
152             {
153                 return _threadData()->fake_current_processor();
154             }
155             //@endcond
156         };
157
158     } // namespace msvc
159 }} // namespace cds::threading
160 //@endcond
161
162 #endif // #ifndef CDSLIB_THREADING_DETAILS_MSVC_MANAGER_H