2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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.
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.
31 #ifndef CDSLIB_THREADING_DETAILS_WINTLS_MANAGER_H
32 #define CDSLIB_THREADING_DETAILS_WINTLS_MANAGER_H
34 #include <system_error>
36 #include <cds/threading/details/_common.h>
39 namespace cds { namespace threading {
41 /// cds::threading::Manager implementation based on Windows TLS API
42 CDS_CXX11_INLINE_NAMESPACE namespace wintls {
44 /// Thread-specific data manager based on Windows TLS API
46 Manager throws an exception of Manager::api_exception class if an error occurs
50 /// Windows TLS API error code type
51 typedef DWORD api_error_code;
54 class api_exception : public std::system_error
57 /// Exception constructor
58 api_exception( api_error_code nCode, const char * pszFunction )
59 : std::system_error( static_cast<int>(nCode), std::system_category(), pszFunction )
75 static CDS_EXPORT_API DWORD m_key;
79 if ( m_key == TLS_OUT_OF_INDEXES ) {
80 if ( (m_key = ::TlsAlloc()) == TLS_OUT_OF_INDEXES )
81 throw api_exception( ::GetLastError(), "TlsAlloc" );
87 if ( m_key != TLS_OUT_OF_INDEXES ) {
88 if ( ::TlsFree( m_key ) == 0 )
89 throw api_exception( ::GetLastError(), "TlsFree" );
90 m_key = TLS_OUT_OF_INDEXES;
94 static ThreadData * get()
97 void * pData = ::TlsGetValue( m_key );
98 if ( pData == nullptr && (nErr = ::GetLastError()) != ERROR_SUCCESS )
99 throw api_exception( nErr, "TlsGetValue" );
100 return reinterpret_cast<ThreadData *>( pData );
105 ThreadData * pData = new ThreadData;
106 if ( !::TlsSetValue( m_key, pData ))
107 throw api_exception( ::GetLastError(), "TlsSetValue" );
111 ThreadData * p = get();
112 ::TlsSetValue( m_key, nullptr );
120 static ThreadData * _threadData( EThreadAction nAction )
126 ThreadData * p = Holder::get();
131 return Holder::get();
134 return Holder::get();
135 case do_attachThread:
136 if ( Holder::get() == nullptr )
138 return Holder::get();
139 case do_detachThread:
143 assert( false ) ; // anything forgotten?..
150 /// Initialize manager
152 This function is automatically called by cds::Initialize
159 /// Terminate manager
161 This function is automatically called by cds::Terminate
168 /// Checks whether current thread is attached to \p libcds feature or not.
169 static bool isThreadAttached()
171 return _threadData( do_checkData ) != nullptr;
174 /// This method must be called in beginning of thread execution
176 If TLS pointer to manager's data is \p nullptr, api_exception is thrown
178 If an error occurs in call of Win TLS API function, api_exception is thrown
179 with Windows error code.
181 static void attachThread()
183 ThreadData * pData = _threadData( do_attachThread );
190 throw api_exception( api_error_code(-1), "cds::threading::wintls::Manager::attachThread" );
193 /// This method must be called in end of thread execution
195 If TLS pointer to manager's data is \p nullptr, api_exception is thrown
197 If an error occurs in call of Win TLS API function, api_exception is thrown
198 with Windows error code.
200 static void detachThread()
202 ThreadData * pData = _threadData( do_getData );
207 _threadData( do_detachThread );
210 throw api_exception( api_error_code(-1), "cds::threading::winapi::Manager::detachThread" );
213 /// Returns ThreadData pointer for the current thread
214 static ThreadData * thread_data()
216 return _threadData( do_getData );
219 /// Get gc::HP thread GC implementation for current thread
221 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
222 or if you did not use gc::HP.
223 To initialize gc::HP GC you must constuct cds::gc::HP object in the beginning of your application
225 static gc::HP::thread_gc_impl& getHZPGC()
227 return *(_threadData( do_getData )->m_hpManager);
230 /// Get gc::DHP thread GC implementation for current thread
232 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
233 or if you did not use gc::DHP.
234 To initialize gc::DHP GC you must constuct cds::gc::DHP object in the beginning of your application
236 static gc::DHP::thread_gc_impl& getDHPGC()
238 return *(_threadData( do_getData )->m_dhpManager);
242 static size_t fake_current_processor()
244 return _threadData( do_getData )->fake_current_processor();
249 } // namespace wintls
250 }} // namespace cds::threading
253 #endif // #ifndef CDSLIB_THREADING_DETAILS_WINTLS_MANAGER_H