3 #ifndef __CDS_THREADING_DETAILS_PTHREAD_MANAGER_H
4 #define __CDS_THREADING_DETAILS_PTHREAD_MANAGER_H
8 #include <cds/threading/details/_common.h>
11 namespace cds { namespace threading {
13 /// cds::threading::Manager implementation based on pthread thread-specific data functions
14 CDS_CXX11_INLINE_NAMESPACE namespace pthread {
16 /// Thread-specific data manager based on pthread thread-specific data functions
18 Manager throws an exception of Manager::pthread_exception class if an error occurs
22 /// pthread error code type
23 typedef int pthread_error_code;
26 class pthread_exception: public cds::Exception {
28 const pthread_error_code m_errCode ; ///< pthread error code, -1 if no pthread error code
30 /// Exception constructor
31 pthread_exception( pthread_error_code nCode, const char * pszFunction )
35 sprintf( buf, "Pthread error %i [function %s]", nCode, pszFunction );
40 /// pthread TLS key holder
43 static pthread_key_t m_key;
45 static void key_destructor(void * p)
48 reinterpret_cast<ThreadData *>(p)->fini();
49 delete reinterpret_cast<ThreadData *>(p);
55 pthread_error_code nErr;
56 if ( (nErr = pthread_key_create( &m_key, key_destructor )) != 0 )
57 throw pthread_exception( nErr, "pthread_key_create" );
62 pthread_error_code nErr;
63 if ( (nErr = pthread_key_delete( m_key )) != 0 )
64 throw pthread_exception( nErr, "pthread_key_delete" );
67 static ThreadData * get()
69 return reinterpret_cast<ThreadData *>( pthread_getspecific( m_key ) );
74 pthread_error_code nErr;
75 ThreadData * pData = new ThreadData;
76 if ( ( nErr = pthread_setspecific( m_key, pData )) != 0 )
77 throw pthread_exception( nErr, "pthread_setspecific" );
81 ThreadData * p = get();
82 pthread_setspecific( m_key, NULL );
101 static ThreadData * _threadData( EThreadAction nAction )
105 return Holder::get();
107 return Holder::get();
108 case do_attachThread:
109 if ( Holder::get() == NULL )
111 return Holder::get();
112 case do_detachThread:
119 assert( false ) ; // anything forgotten?..
121 assert(false) ; // how did we get here?
127 /// Initialize manager
129 This function is automatically called by cds::Initialize
136 /// Terminate manager
138 This function is automatically called by cds::Terminate
145 /// Checks whether current thread is attached to \p libcds feature or not.
146 static bool isThreadAttached()
148 return _threadData( do_checkData ) != NULL;
151 /// This method must be called in beginning of thread execution
153 If TLS pointer to manager's data is NULL, pthread_exception is thrown
155 If an error occurs in call of pthread API function, pthread_exception is thrown
156 with pthread error code.
158 static void attachThread()
160 ThreadData * pData = _threadData( do_attachThread );
161 assert( pData != NULL );
167 throw pthread_exception( -1, "cds::threading::pthread::Manager::attachThread" );
170 /// This method must be called in end of thread execution
172 If TLS pointer to manager's data is NULL, pthread_exception is thrown
174 If an error occurs in call of pthread API function, pthread_exception is thrown
175 with pthread error code.
177 static void detachThread()
179 ThreadData * pData = _threadData( do_getData );
180 assert( pData != NULL );
184 _threadData( do_detachThread );
187 throw pthread_exception( -1, "cds::threading::pthread::Manager::detachThread" );
190 /// Returns ThreadData pointer for the current thread
191 static ThreadData * thread_data()
193 return _threadData( do_getData );
196 /// Get gc::HP thread GC implementation for current thread
198 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
199 or if you did not use gc::HP.
200 To initialize gc::HP GC you must constuct cds::gc::HP object in the beginning of your application
202 static gc::HP::thread_gc_impl& getHZPGC()
204 return *(_threadData( do_getData )->m_hpManager);
207 /// Get gc::HRC thread GC implementation for current thread
209 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
210 or if you did not use gc::HRC.
211 To initialize gc::HRC GC you must constuct cds::gc::HRC object in the beginning of your application
213 static gc::HRC::thread_gc_impl& getHRCGC()
215 return *(_threadData( do_getData )->m_hrcManager);
218 /// Get gc::PTB thread GC implementation for current thread
220 The object returned may be uninitialized if you did not call attachThread in the beginning of thread execution
221 or if you did not use gc::PTB.
222 To initialize gc::PTB GC you must constuct cds::gc::PTB object in the beginning of your application
224 static gc::PTB::thread_gc_impl& getPTBGC()
226 return *(_threadData( do_getData )->m_ptbManager);
230 static size_t fake_current_processor()
232 return _threadData( do_getData )->fake_current_processor();
238 } // namespace pthread
239 }} // namespace cds::threading
242 #endif // #ifndef __CDS_THREADING_DETAILS_PTHREAD_MANAGER_H