Removed redundant spaces
[libcds.git] / cds / threading / details / cxx11_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_CXX11_MANAGER_H
32 #define CDSLIB_THREADING_DETAILS_CXX11_MANAGER_H
33
34 #include <cds/threading/details/_common.h>
35
36 #ifndef CDS_CXX11_THREAD_LOCAL_SUPPORT
37 #   error "The compiler does not support C++11 thread_local keyword. You cannot use CDS_THREADING_CXX11 threading model."
38 #endif
39
40 //@cond
41 namespace cds { namespace threading {
42
43     //@cond
44     struct cxx11_internal {
45         typedef unsigned char  ThreadDataPlaceholder[ sizeof(ThreadData) ];
46         static thread_local ThreadDataPlaceholder CDS_DATA_ALIGNMENT(8) s_threadData;
47         static thread_local ThreadData * s_pThreadData;
48     };
49     //@endcond
50
51     /// cds::threading::Manager implementation based on c++11 thread_local declaration
52     CDS_CXX11_INLINE_NAMESPACE namespace cxx11 {
53
54         /// Thread-specific data manager based on c++11 thread_local feature
55         class Manager {
56         private :
57             //@cond
58
59             static ThreadData * _threadData()
60             {
61                 return cxx11_internal::s_pThreadData;
62             }
63
64             static ThreadData * create_thread_data()
65             {
66                 if ( !cxx11_internal::s_pThreadData ) {
67                     cxx11_internal::s_pThreadData = new (cxx11_internal::s_threadData) ThreadData();
68                 }
69                 return cxx11_internal::s_pThreadData;
70             }
71
72             static void destroy_thread_data()
73             {
74                 if ( cxx11_internal::s_pThreadData ) {
75                     ThreadData * p = cxx11_internal::s_pThreadData;
76                     cxx11_internal::s_pThreadData = nullptr;
77                     p->ThreadData::~ThreadData();
78                 }
79             }
80             //@endcond
81
82         public:
83             /// Initialize manager (empty function)
84             /**
85                 This function is automatically called by cds::Initialize
86             */
87             static void init()
88             {}
89
90             /// Terminate manager (empty function)
91             /**
92                 This function is automatically called by cds::Terminate
93             */
94             static void fini()
95             {}
96
97             /// Checks whether current thread is attached to \p libcds feature or not.
98             static bool isThreadAttached()
99             {
100                 return _threadData() != 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 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 != nullptr );
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 != nullptr );
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 cxx11
159
160 }} // namespace cds::threading
161 //@endcond
162
163 #endif // #ifndef CDSLIB_THREADING_DETAILS_CXX11_MANAGER_H