3 #ifndef CDSLIB_THREADING_DETAILS_PTHREAD_MANAGER_H
4 #define CDSLIB_THREADING_DETAILS_PTHREAD_MANAGER_H
6 #include <system_error>
9 #include <cds/threading/details/_common.h>
12 namespace cds { namespace threading {
14 /// cds::threading::Manager implementation based on pthread thread-specific data functions
15 CDS_CXX11_INLINE_NAMESPACE namespace pthread {
17 /// Thread-specific data manager based on pthread thread-specific data functions
19 Manager throws an exception of Manager::pthread_exception class if an error occurs
23 /// pthread error code type
24 typedef int pthread_error_code;
27 class pthread_exception: public std::system_error
30 /// Exception constructor
31 pthread_exception( int nCode, const char * pszFunction )
32 : std::system_error( nCode, std::system_category(), pszFunction )
36 /// pthread TLS key holder
39 static pthread_key_t m_key;
41 static void key_destructor(void * p)
44 reinterpret_cast<ThreadData *>(p)->fini();
45 delete reinterpret_cast<ThreadData *>(p);
51 pthread_error_code nErr;
52 if ( (nErr = pthread_key_create( &m_key, key_destructor )) != 0 )
53 throw pthread_exception( nErr, "pthread_key_create" );
58 pthread_error_code nErr;
59 if ( (nErr = pthread_key_delete( m_key )) != 0 )
60 throw pthread_exception( nErr, "pthread_key_delete" );
63 static ThreadData * get()
65 return reinterpret_cast<ThreadData *>( pthread_getspecific( m_key ) );
70 pthread_error_code nErr;
71 ThreadData * pData = new ThreadData;
72 if ( ( nErr = pthread_setspecific( m_key, pData )) != 0 )
73 throw pthread_exception( nErr, "pthread_setspecific" );
77 ThreadData * p = get();
78 pthread_setspecific( m_key, nullptr );
97 static ThreadData * _threadData( EThreadAction nAction )
101 return Holder::get();
103 return Holder::get();
104 case do_attachThread:
105 if ( Holder::get() == nullptr )
107 return Holder::get();
108 case do_detachThread:
115 assert( false ) ; // anything forgotten?..
117 assert(false) ; // how did we get here?
123 /// Initialize manager
125 This function is automatically called by cds::Initialize
132 /// Terminate manager
134 This function is automatically called by cds::Terminate
141 /// Checks whether current thread is attached to \p libcds feature or not.
142 static bool isThreadAttached()
144 return _threadData( do_checkData ) != nullptr;
147 /// This method must be called in beginning of thread execution
149 If TLS pointer to manager's data is \p nullptr, pthread_exception is thrown
151 If an error occurs in call of pthread API function, pthread_exception is thrown
152 with pthread error code.
154 static void attachThread()
156 ThreadData * pData = _threadData( do_attachThread );
163 throw pthread_exception( -1, "cds::threading::pthread::Manager::attachThread" );
166 /// This method must be called in end of thread execution
168 If TLS pointer to manager's data is \p nullptr, pthread_exception is thrown
170 If an error occurs in call of pthread API function, pthread_exception is thrown
171 with pthread error code.
173 static void detachThread()
175 ThreadData * pData = _threadData( do_getData );
180 _threadData( do_detachThread );
183 throw pthread_exception( -1, "cds::threading::pthread::Manager::detachThread" );
186 /// Returns ThreadData pointer for the current thread
187 static ThreadData * thread_data()
189 return _threadData( do_getData );
192 /// Get gc::HP thread GC implementation for current thread
194 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
195 or if you did not use gc::HP.
196 To initialize gc::HP GC you must constuct cds::gc::HP object in the beginning of your application
198 static gc::HP::thread_gc_impl& getHZPGC()
200 return *(_threadData( do_getData )->m_hpManager);
203 /// Get gc::DHP thread GC implementation for current thread
205 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
206 or if you did not use gc::DHP.
207 To initialize gc::DHP GC you must constuct cds::gc::DHP object in the beginning of your application
209 static gc::DHP::thread_gc_impl& getDHPGC()
211 return *(_threadData( do_getData )->m_dhpManager);
215 static size_t fake_current_processor()
217 return _threadData( do_getData )->fake_current_processor();
223 } // namespace pthread
224 }} // namespace cds::threading
227 #endif // #ifndef CDSLIB_THREADING_DETAILS_PTHREAD_MANAGER_H