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 <iosfwd>
00035 #include <exception>
00036 #include "tbb_stddef.h"
00037 #include "tick_count.h"
00038
00039 namespace tbb {
00040
00042 namespace internal {
00043
00044 class tbb_thread_v3;
00045
00046 }
00047
00048 void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 );
00049
00050 namespace internal {
00051
00053 void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
00055 void __TBB_EXPORTED_FUNC free_closure_v3( void* );
00056
00057 struct thread_closure_base {
00058 void* operator new( size_t size ) {return allocate_closure_v3(size);}
00059 void operator delete( void* ptr ) {free_closure_v3(ptr);}
00060 };
00061
00062 template<class F> struct thread_closure_0: thread_closure_base {
00063 F function;
00064
00065 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00066 thread_closure_0 *self = static_cast<thread_closure_0*>(c);
00067 try {
00068 self->function();
00069 } catch ( ... ) {
00070 std::terminate();
00071 }
00072 delete self;
00073 return 0;
00074 }
00075 thread_closure_0( const F& f ) : function(f) {}
00076 };
00078 template<class F, class X> struct thread_closure_1: thread_closure_base {
00079 F function;
00080 X arg1;
00082 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00083 thread_closure_1 *self = static_cast<thread_closure_1*>(c);
00084 try {
00085 self->function(self->arg1);
00086 } catch ( ... ) {
00087 std::terminate();
00088 }
00089 delete self;
00090 return 0;
00091 }
00092 thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
00093 };
00094 template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
00095 F function;
00096 X arg1;
00097 Y arg2;
00099 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00100 thread_closure_2 *self = static_cast<thread_closure_2*>(c);
00101 try {
00102 self->function(self->arg1, self->arg2);
00103 } catch ( ... ) {
00104 std::terminate();
00105 }
00106 delete self;
00107 return 0;
00108 }
00109 thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
00110 };
00111
00113 class tbb_thread_v3 {
00114 tbb_thread_v3(const tbb_thread_v3&);
00115 public:
00116 #if _WIN32||_WIN64
00117 typedef HANDLE native_handle_type;
00118 #else
00119 typedef pthread_t native_handle_type;
00120 #endif // _WIN32||_WIN64
00121
00122 class id;
00124 tbb_thread_v3() : my_handle(0)
00125 #if _WIN32||_WIN64
00126 , my_thread_id(0)
00127 #endif
00128 {}
00129
00131 template <class F> explicit tbb_thread_v3(F f) {
00132 typedef internal::thread_closure_0<F> closure_type;
00133 internal_start(closure_type::start_routine, new closure_type(f));
00134 }
00136 template <class F, class X> tbb_thread_v3(F f, X x) {
00137 typedef internal::thread_closure_1<F,X> closure_type;
00138 internal_start(closure_type::start_routine, new closure_type(f,x));
00139 }
00141 template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
00142 typedef internal::thread_closure_2<F,X,Y> closure_type;
00143 internal_start(closure_type::start_routine, new closure_type(f,x,y));
00144 }
00145
00146 tbb_thread_v3& operator=(tbb_thread_v3& x) {
00147 if (joinable()) detach();
00148 my_handle = x.my_handle;
00149 x.my_handle = 0;
00150 #if _WIN32||_WIN64
00151 my_thread_id = x.my_thread_id;
00152 x.my_thread_id = 0;
00153 #endif // _WIN32||_WIN64
00154 return *this;
00155 }
00156 void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );}
00157 bool joinable() const {return my_handle!=0; }
00159 void __TBB_EXPORTED_METHOD join();
00161 void __TBB_EXPORTED_METHOD detach();
00162 ~tbb_thread_v3() {if( joinable() ) detach();}
00163 inline id get_id() const;
00164 native_handle_type native_handle() { return my_handle; }
00165
00167 static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
00168 private:
00169 native_handle_type my_handle;
00170 #if _WIN32||_WIN64
00171 DWORD my_thread_id;
00172 #endif // _WIN32||_WIN64
00173
00175 void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine),
00176 void* closure );
00177 friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00178 friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00179 };
00180
00181 class tbb_thread_v3::id {
00182 #if _WIN32||_WIN64
00183 DWORD my_id;
00184 id( DWORD my_id ) : my_id(my_id) {}
00185 #else
00186 pthread_t my_id;
00187 id( pthread_t my_id ) : my_id(my_id) {}
00188 #endif // _WIN32||_WIN64
00189 friend class tbb_thread_v3;
00190 public:
00191 id() : my_id(0) {}
00192
00193 friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y );
00194 friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00195 friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y );
00196 friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00197 friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y );
00198 friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00199
00200 template<class charT, class traits>
00201 friend std::basic_ostream<charT, traits>&
00202 operator<< (std::basic_ostream<charT, traits> &out,
00203 tbb_thread_v3::id id)
00204 {
00205 out << id.my_id;
00206 return out;
00207 }
00208 friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00209 };
00210
00211 tbb_thread_v3::id tbb_thread_v3::get_id() const {
00212 #if _WIN32||_WIN64
00213 return id(my_thread_id);
00214 #else
00215 return id(my_handle);
00216 #endif // _WIN32||_WIN64
00217 }
00218 void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00219 tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00220 void __TBB_EXPORTED_FUNC thread_yield_v3();
00221 void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
00222
00223 inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y)
00224 {
00225 return x.my_id == y.my_id;
00226 }
00227 inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00228 {
00229 return x.my_id != y.my_id;
00230 }
00231 inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y)
00232 {
00233 return x.my_id < y.my_id;
00234 }
00235 inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00236 {
00237 return x.my_id <= y.my_id;
00238 }
00239 inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y)
00240 {
00241 return x.my_id > y.my_id;
00242 }
00243 inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00244 {
00245 return x.my_id >= y.my_id;
00246 }
00247
00248 }
00249
00251 typedef internal::tbb_thread_v3 tbb_thread;
00252
00253 using internal::operator==;
00254 using internal::operator!=;
00255 using internal::operator<;
00256 using internal::operator>;
00257 using internal::operator<=;
00258 using internal::operator>=;
00259
00260 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
00261 internal::move_v3(t1, t2);
00262 }
00263
00264 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) {
00265 tbb::tbb_thread::native_handle_type h = t1.my_handle;
00266 t1.my_handle = t2.my_handle;
00267 t2.my_handle = h;
00268 #if _WIN32||_WIN64
00269 DWORD i = t1.my_thread_id;
00270 t1.my_thread_id = t2.my_thread_id;
00271 t2.my_thread_id = i;
00272 #endif
00273 }
00274
00275 namespace this_tbb_thread {
00276 inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
00278 inline void yield() { internal::thread_yield_v3(); }
00280 inline void sleep(const tick_count::interval_t &i) {
00281 internal::thread_sleep_v3(i);
00282 }
00283 }
00284
00285 }
00286
00287 #endif