00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __TBB_tbb_thread_H
00030 #define __TBB_tbb_thread_H
00031
00032 #include "tbb_stddef.h"
00033 #if _WIN32||_WIN64
00034 #include "machine/windows_api.h"
00035 #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI
00036 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* )
00037 #if __TBB_WIN8UI_SUPPORT
00038 typedef size_t thread_id_type;
00039 #else // __TBB_WIN8UI_SUPPORT
00040 typedef DWORD thread_id_type;
00041 #endif // __TBB_WIN8UI_SUPPORT
00042 #else
00043 #define __TBB_NATIVE_THREAD_ROUTINE void*
00044 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* )
00045 #include <pthread.h>
00046 #endif // _WIN32||_WIN64
00047
00048 #include "tick_count.h"
00049
00050 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00051
00052 #pragma warning (push)
00053 #pragma warning (disable: 4530)
00054 #endif
00055
00056 #include <iosfwd>
00057
00058 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00059 #pragma warning (pop)
00060 #endif
00061
00062 namespace tbb {
00063
00065 namespace internal {
00066
00067 class tbb_thread_v3;
00068
00069 }
00070
00071 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 );
00072
00073 namespace internal {
00074
00076 void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
00078 void __TBB_EXPORTED_FUNC free_closure_v3( void* );
00079
00080 struct thread_closure_base {
00081 void* operator new( size_t size ) {return allocate_closure_v3(size);}
00082 void operator delete( void* ptr ) {free_closure_v3(ptr);}
00083 };
00084
00085 template<class F> struct thread_closure_0: thread_closure_base {
00086 F function;
00087
00088 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00089 thread_closure_0 *self = static_cast<thread_closure_0*>(c);
00090 self->function();
00091 delete self;
00092 return 0;
00093 }
00094 thread_closure_0( const F& f ) : function(f) {}
00095 };
00097 template<class F, class X> struct thread_closure_1: thread_closure_base {
00098 F function;
00099 X arg1;
00101 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00102 thread_closure_1 *self = static_cast<thread_closure_1*>(c);
00103 self->function(self->arg1);
00104 delete self;
00105 return 0;
00106 }
00107 thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
00108 };
00109 template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
00110 F function;
00111 X arg1;
00112 Y arg2;
00114 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
00115 thread_closure_2 *self = static_cast<thread_closure_2*>(c);
00116 self->function(self->arg1, self->arg2);
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
00187 static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
00188 private:
00189 native_handle_type my_handle;
00190 #if _WIN32||_WIN64
00191 thread_id_type my_thread_id;
00192 #endif // _WIN32||_WIN64
00193
00195 void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine),
00196 void* closure );
00197 friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00198 friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00199 };
00200
00201 class tbb_thread_v3::id {
00202 #if _WIN32||_WIN64
00203 thread_id_type my_id;
00204 id( thread_id_type id_ ) : my_id(id_) {}
00205 #else
00206 pthread_t my_id;
00207 id( pthread_t id_ ) : my_id(id_) {}
00208 #endif // _WIN32||_WIN64
00209 friend class tbb_thread_v3;
00210 public:
00211 id() : my_id(0) {}
00212
00213 friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y );
00214 friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00215 friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y );
00216 friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00217 friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y );
00218 friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y );
00219
00220 template<class charT, class traits>
00221 friend std::basic_ostream<charT, traits>&
00222 operator<< (std::basic_ostream<charT, traits> &out,
00223 tbb_thread_v3::id id)
00224 {
00225 out << id.my_id;
00226 return out;
00227 }
00228 friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00229 };
00230
00231 tbb_thread_v3::id tbb_thread_v3::get_id() const {
00232 #if _WIN32||_WIN64
00233 return id(my_thread_id);
00234 #else
00235 return id(my_handle);
00236 #endif // _WIN32||_WIN64
00237 }
00238 void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
00239 tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
00240 void __TBB_EXPORTED_FUNC thread_yield_v3();
00241 void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
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 inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y)
00260 {
00261 return x.my_id > y.my_id;
00262 }
00263 inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
00264 {
00265 return x.my_id >= y.my_id;
00266 }
00267
00268 }
00269
00271 typedef internal::tbb_thread_v3 tbb_thread;
00272
00273 using internal::operator==;
00274 using internal::operator!=;
00275 using internal::operator<;
00276 using internal::operator>;
00277 using internal::operator<=;
00278 using internal::operator>=;
00279
00280 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
00281 internal::move_v3(t1, t2);
00282 }
00283
00284 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) {
00285 tbb::tbb_thread::native_handle_type h = t1.my_handle;
00286 t1.my_handle = t2.my_handle;
00287 t2.my_handle = h;
00288 #if _WIN32||_WIN64
00289 thread_id_type i = t1.my_thread_id;
00290 t1.my_thread_id = t2.my_thread_id;
00291 t2.my_thread_id = i;
00292 #endif
00293 }
00294
00295 namespace this_tbb_thread {
00296 inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
00298 inline void yield() { internal::thread_yield_v3(); }
00300 inline void sleep(const tick_count::interval_t &i) {
00301 internal::thread_sleep_v3(i);
00302 }
00303 }
00304
00305 }
00306
00307 #endif