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 #include "tbb_stddef.h"
00025 #if _WIN32||_WIN64
00026 #include "machine/windows_api.h"
00027 #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI
00028 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* )
00029 #if __TBB_WIN8UI_SUPPORT
00030 typedef size_t thread_id_type;
00031 #else // __TBB_WIN8UI_SUPPORT
00032 typedef DWORD thread_id_type;
00033 #endif // __TBB_WIN8UI_SUPPORT
00034 #else
00035 #define __TBB_NATIVE_THREAD_ROUTINE void*
00036 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* )
00037 #include <pthread.h>
00038 #endif // _WIN32||_WIN64
00039
00040 #include "tick_count.h"
00041
00042 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00043
00044 #pragma warning (push)
00045 #pragma warning (disable: 4530)
00046 #endif
00047
00048 #include <iosfwd>
00049
00050 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00051 #pragma warning (pop)
00052 #endif
00053
00054 namespace tbb {
00055
00057 namespace internal {
00058
00059 class tbb_thread_v3;
00060
00061 }
00062
00063 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 );
00064
00065 namespace internal {
00066
00068 void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
00070 void __TBB_EXPORTED_FUNC free_closure_v3( void* );
00071
00072 struct thread_closure_base {
00073 void* operator new( size_t size ) {return allocate_closure_v3(size);}
00074 void operator delete( void* ptr ) {free_closure_v3(ptr);}
00075 };
00076
00077 template<class F> struct thread_closure_0: thread_closure_base {
00078 F function;
00079
00080 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00081 thread_closure_0 *self = static_cast<thread_closure_0*>(c);
00082 self->function();
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 self->function(self->arg1);
00096 delete self;
00097 return 0;
00098 }
00099 thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
00100 };
00101 template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
00102 F function;
00103 X arg1;
00104 Y arg2;
00106 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00107 thread_closure_2 *self = static_cast<thread_closure_2*>(c);
00108 self->function(self->arg1, self->arg2);
00109 delete self;
00110 return 0;
00111 }
00112 thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
00113 };
00114
00116 class tbb_thread_v3 {
00117 tbb_thread_v3(const tbb_thread_v3&);
00118 public:
00119 #if _WIN32||_WIN64
00120 typedef HANDLE native_handle_type;
00121 #else
00122 typedef pthread_t native_handle_type;
00123 #endif // _WIN32||_WIN64
00124
00125 class id;
00127 tbb_thread_v3() : my_handle(0)
00128 #if _WIN32||_WIN64
00129 , my_thread_id(0)
00130 #endif
00131 {}
00132
00134 template <class F> explicit tbb_thread_v3(F f) {
00135 typedef internal::thread_closure_0<F> closure_type;
00136 internal_start(closure_type::start_routine, new closure_type(f));
00137 }
00139 template <class F, class X> tbb_thread_v3(F f, X x) {
00140 typedef internal::thread_closure_1<F,X> closure_type;
00141 internal_start(closure_type::start_routine, new closure_type(f,x));
00142 }
00144 template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
00145 typedef internal::thread_closure_2<F,X,Y> closure_type;
00146 internal_start(closure_type::start_routine, new closure_type(f,x,y));
00147 }
00148
00149 tbb_thread_v3& operator=(tbb_thread_v3& x) {
00150 if (joinable()) detach();
00151 my_handle = x.my_handle;
00152 x.my_handle = 0;
00153 #if _WIN32||_WIN64
00154 my_thread_id = x.my_thread_id;
00155 x.my_thread_id = 0;
00156 #endif // _WIN32||_WIN64
00157 return *this;
00158 }
00159 void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );}
00160 bool joinable() const {return my_handle!=0; }
00162 void __TBB_EXPORTED_METHOD join();
00164 void __TBB_EXPORTED_METHOD detach();
00165 ~tbb_thread_v3() {if( joinable() ) detach();}
00166 inline id get_id() const;
00167 native_handle_type native_handle() { return my_handle; }
00168
00170
00179 static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
00180 private:
00181 native_handle_type my_handle;
00182 #if _WIN32||_WIN64
00183 thread_id_type my_thread_id;
00184 #endif // _WIN32||_WIN64
00185
00187 void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine),
00188 void* closure );
00189 friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00190 friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00191 };
00192
00193 class tbb_thread_v3::id {
00194 #if _WIN32||_WIN64
00195 thread_id_type my_id;
00196 id( thread_id_type id_ ) : my_id(id_) {}
00197 #else
00198 pthread_t my_id;
00199 id( pthread_t id_ ) : my_id(id_) {}
00200 #endif // _WIN32||_WIN64
00201 friend class tbb_thread_v3;
00202 public:
00203 id() : my_id(0) {}
00204
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 friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00211
00212 template<class charT, class traits>
00213 friend std::basic_ostream<charT, traits>&
00214 operator<< (std::basic_ostream<charT, traits> &out,
00215 tbb_thread_v3::id id)
00216 {
00217 out << id.my_id;
00218 return out;
00219 }
00220 friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00221 };
00222
00223 tbb_thread_v3::id tbb_thread_v3::get_id() const {
00224 #if _WIN32||_WIN64
00225 return id(my_thread_id);
00226 #else
00227 return id(my_handle);
00228 #endif // _WIN32||_WIN64
00229 }
00230 void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00231 tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00232 void __TBB_EXPORTED_FUNC thread_yield_v3();
00233 void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
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 inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00248 {
00249 return x.my_id <= y.my_id;
00250 }
00251 inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y)
00252 {
00253 return x.my_id > y.my_id;
00254 }
00255 inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00256 {
00257 return x.my_id >= y.my_id;
00258 }
00259
00260 }
00261
00263 typedef internal::tbb_thread_v3 tbb_thread;
00264
00265 using internal::operator==;
00266 using internal::operator!=;
00267 using internal::operator<;
00268 using internal::operator>;
00269 using internal::operator<=;
00270 using internal::operator>=;
00271
00272 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
00273 internal::move_v3(t1, t2);
00274 }
00275
00276 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) {
00277 tbb::tbb_thread::native_handle_type h = t1.my_handle;
00278 t1.my_handle = t2.my_handle;
00279 t2.my_handle = h;
00280 #if _WIN32||_WIN64
00281 thread_id_type i = t1.my_thread_id;
00282 t1.my_thread_id = t2.my_thread_id;
00283 t2.my_thread_id = i;
00284 #endif
00285 }
00286
00287 namespace this_tbb_thread {
00288 inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
00290 inline void yield() { internal::thread_yield_v3(); }
00292 inline void sleep(const tick_count::interval_t &i) {
00293 internal::thread_sleep_v3(i);
00294 }
00295 }
00296
00297 }
00298
00299 #endif