00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_tbb_thread_H
00022 #define __TBB_tbb_thread_H
00023
00024 #if _WIN32||_WIN64
00025 #include <windows.h>
00026 #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI
00027 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* )
00028 #else
00029 #define __TBB_NATIVE_THREAD_ROUTINE void*
00030 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* )
00031 #include <pthread.h>
00032 #endif // _WIN32||_WIN64
00033
00034 #include "tbb_stddef.h"
00035 #include "tick_count.h"
00036 #include <exception>
00037
00038 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00039
00040 #pragma warning (push)
00041 #pragma warning (disable: 4530)
00042 #endif
00043
00044 #include <iosfwd>
00045
00046 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00047 #pragma warning (pop)
00048 #endif
00049
00050 namespace tbb {
00051
00053 namespace internal {
00054
00055 class tbb_thread_v3;
00056
00057 }
00058
00059 void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 );
00060
00061 namespace internal {
00062
00064 void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
00066 void __TBB_EXPORTED_FUNC free_closure_v3( void* );
00067
00068 struct thread_closure_base {
00069 void* operator new( size_t size ) {return allocate_closure_v3(size);}
00070 void operator delete( void* ptr ) {free_closure_v3(ptr);}
00071 };
00072
00073 template<class F> struct thread_closure_0: thread_closure_base {
00074 F function;
00075
00076 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00077 thread_closure_0 *self = static_cast<thread_closure_0*>(c);
00078 __TBB_TRY {
00079 self->function();
00080 } __TBB_CATCH( ... ) {
00081 std::terminate();
00082 }
00083 delete self;
00084 return 0;
00085 }
00086 thread_closure_0( const F& f ) : function(f) {}
00087 };
00089 template<class F, class X> struct thread_closure_1: thread_closure_base {
00090 F function;
00091 X arg1;
00093 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00094 thread_closure_1 *self = static_cast<thread_closure_1*>(c);
00095 __TBB_TRY {
00096 self->function(self->arg1);
00097 } __TBB_CATCH( ... ) {
00098 std::terminate();
00099 }
00100 delete self;
00101 return 0;
00102 }
00103 thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
00104 };
00105 template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
00106 F function;
00107 X arg1;
00108 Y arg2;
00110 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00111 thread_closure_2 *self = static_cast<thread_closure_2*>(c);
00112 __TBB_TRY {
00113 self->function(self->arg1, self->arg2);
00114 } __TBB_CATCH( ... ) {
00115 std::terminate();
00116 }
00117 delete self;
00118 return 0;
00119 }
00120 thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
00121 };
00122
00124 class tbb_thread_v3 {
00125 tbb_thread_v3(const tbb_thread_v3&);
00126 public:
00127 #if _WIN32||_WIN64
00128 typedef HANDLE native_handle_type;
00129 #else
00130 typedef pthread_t native_handle_type;
00131 #endif // _WIN32||_WIN64
00132
00133 class id;
00135 tbb_thread_v3() : my_handle(0)
00136 #if _WIN32||_WIN64
00137 , my_thread_id(0)
00138 #endif
00139 {}
00140
00142 template <class F> explicit tbb_thread_v3(F f) {
00143 typedef internal::thread_closure_0<F> closure_type;
00144 internal_start(closure_type::start_routine, new closure_type(f));
00145 }
00147 template <class F, class X> tbb_thread_v3(F f, X x) {
00148 typedef internal::thread_closure_1<F,X> closure_type;
00149 internal_start(closure_type::start_routine, new closure_type(f,x));
00150 }
00152 template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
00153 typedef internal::thread_closure_2<F,X,Y> closure_type;
00154 internal_start(closure_type::start_routine, new closure_type(f,x,y));
00155 }
00156
00157 tbb_thread_v3& operator=(tbb_thread_v3& x) {
00158 if (joinable()) detach();
00159 my_handle = x.my_handle;
00160 x.my_handle = 0;
00161 #if _WIN32||_WIN64
00162 my_thread_id = x.my_thread_id;
00163 x.my_thread_id = 0;
00164 #endif // _WIN32||_WIN64
00165 return *this;
00166 }
00167 void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );}
00168 bool joinable() const {return my_handle!=0; }
00170 void __TBB_EXPORTED_METHOD join();
00172 void __TBB_EXPORTED_METHOD detach();
00173 ~tbb_thread_v3() {if( joinable() ) detach();}
00174 inline id get_id() const;
00175 native_handle_type native_handle() { return my_handle; }
00176
00178 static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
00179 private:
00180 native_handle_type my_handle;
00181 #if _WIN32||_WIN64
00182 DWORD my_thread_id;
00183 #endif // _WIN32||_WIN64
00184
00186 void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine),
00187 void* closure );
00188 friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00189 friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00190 };
00191
00192 class tbb_thread_v3::id {
00193 #if _WIN32||_WIN64
00194 DWORD my_id;
00195 id( DWORD id_ ) : my_id(id_) {}
00196 #else
00197 pthread_t my_id;
00198 id( pthread_t id_ ) : my_id(id_) {}
00199 #endif // _WIN32||_WIN64
00200 friend class tbb_thread_v3;
00201 public:
00202 id() : my_id(0) {}
00203
00204 friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y );
00205 friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00206 friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y );
00207 friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00208 friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y );
00209 friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00210
00211 template<class charT, class traits>
00212 friend std::basic_ostream<charT, traits>&
00213 operator<< (std::basic_ostream<charT, traits> &out,
00214 tbb_thread_v3::id id)
00215 {
00216 out << id.my_id;
00217 return out;
00218 }
00219 friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00220 };
00221
00222 tbb_thread_v3::id tbb_thread_v3::get_id() const {
00223 #if _WIN32||_WIN64
00224 return id(my_thread_id);
00225 #else
00226 return id(my_handle);
00227 #endif // _WIN32||_WIN64
00228 }
00229 void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00230 tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00231 void __TBB_EXPORTED_FUNC thread_yield_v3();
00232 void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
00233
00234 inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y)
00235 {
00236 return x.my_id == y.my_id;
00237 }
00238 inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00239 {
00240 return x.my_id != y.my_id;
00241 }
00242 inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y)
00243 {
00244 return x.my_id < y.my_id;
00245 }
00246 inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00247 {
00248 return x.my_id <= y.my_id;
00249 }
00250 inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y)
00251 {
00252 return x.my_id > y.my_id;
00253 }
00254 inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00255 {
00256 return x.my_id >= y.my_id;
00257 }
00258
00259 }
00260
00262 typedef internal::tbb_thread_v3 tbb_thread;
00263
00264 using internal::operator==;
00265 using internal::operator!=;
00266 using internal::operator<;
00267 using internal::operator>;
00268 using internal::operator<=;
00269 using internal::operator>=;
00270
00271 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
00272 internal::move_v3(t1, t2);
00273 }
00274
00275 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) {
00276 tbb::tbb_thread::native_handle_type h = t1.my_handle;
00277 t1.my_handle = t2.my_handle;
00278 t2.my_handle = h;
00279 #if _WIN32||_WIN64
00280 DWORD i = t1.my_thread_id;
00281 t1.my_thread_id = t2.my_thread_id;
00282 t2.my_thread_id = i;
00283 #endif
00284 }
00285
00286 namespace this_tbb_thread {
00287 inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
00289 inline void yield() { internal::thread_yield_v3(); }
00291 inline void sleep(const tick_count::interval_t &i) {
00292 internal::thread_sleep_v3(i);
00293 }
00294 }
00295
00296 }
00297
00298 #endif