2 Copyright 2005-2010 Intel Corporation. All Rights Reserved.
4 This file is part of Threading Building Blocks.
6 Threading Building Blocks is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public License
8 version 2 as published by the Free Software Foundation.
10 Threading Building Blocks is distributed in the hope that it will be
11 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with Threading Building Blocks; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 As a special exception, you may use this file as part of a free software
20 library without restriction. Specifically, if other files instantiate
21 templates or use macros or inline functions from this file, or you compile
22 this file and link it with other files to produce an executable, this
23 file does not by itself cause the resulting executable to be covered by
24 the GNU General Public License. This exception does not however
25 invalidate any other reasons why the executable file might be covered by
26 the GNU General Public License.
29 #ifndef __TBB_tbb_thread_H
30 #define __TBB_tbb_thread_H
34 #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI
35 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* )
37 #define __TBB_NATIVE_THREAD_ROUTINE void*
38 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* )
40 #endif // _WIN32||_WIN64
42 #include "tbb_stddef.h"
43 #include "tick_count.h"
44 #include <exception> // Need std::terminate from here.
46 #if !TBB_USE_EXCEPTIONS && _MSC_VER
47 // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
48 #pragma warning (push)
49 #pragma warning (disable: 4530)
54 #if !TBB_USE_EXCEPTIONS && _MSC_VER
65 } // namespace internal
67 void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 );
71 //! Allocate a closure
72 void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
73 //! Free a closure allocated by allocate_closure_v3
74 void __TBB_EXPORTED_FUNC free_closure_v3( void* );
76 struct thread_closure_base {
77 void* operator new( size_t size ) {return allocate_closure_v3(size);}
78 void operator delete( void* ptr ) {free_closure_v3(ptr);}
81 template<class F> struct thread_closure_0: thread_closure_base {
84 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
85 thread_closure_0 *self = static_cast<thread_closure_0*>(c);
88 } __TBB_CATCH( ... ) {
94 thread_closure_0( const F& f ) : function(f) {}
96 //! Structure used to pass user function with 1 argument to thread.
97 template<class F, class X> struct thread_closure_1: thread_closure_base {
100 //! Routine passed to Windows's _beginthreadex by thread::internal_start() inside tbb.dll
101 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
102 thread_closure_1 *self = static_cast<thread_closure_1*>(c);
104 self->function(self->arg1);
105 } __TBB_CATCH( ... ) {
111 thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
113 template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
117 //! Routine passed to Windows's _beginthreadex by thread::internal_start() inside tbb.dll
118 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
119 thread_closure_2 *self = static_cast<thread_closure_2*>(c);
121 self->function(self->arg1, self->arg2);
122 } __TBB_CATCH( ... ) {
128 thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
131 //! Versioned thread class.
132 class tbb_thread_v3 {
133 tbb_thread_v3(const tbb_thread_v3&); // = delete; // Deny access
136 typedef HANDLE native_handle_type;
138 typedef pthread_t native_handle_type;
139 #endif // _WIN32||_WIN64
142 //! Constructs a thread object that does not represent a thread of execution.
143 tbb_thread_v3() : my_handle(0)
146 #endif // _WIN32||_WIN64
149 //! Constructs an object and executes f() in a new thread
150 template <class F> explicit tbb_thread_v3(F f) {
151 typedef internal::thread_closure_0<F> closure_type;
152 internal_start(closure_type::start_routine, new closure_type(f));
154 //! Constructs an object and executes f(x) in a new thread
155 template <class F, class X> tbb_thread_v3(F f, X x) {
156 typedef internal::thread_closure_1<F,X> closure_type;
157 internal_start(closure_type::start_routine, new closure_type(f,x));
159 //! Constructs an object and executes f(x,y) in a new thread
160 template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
161 typedef internal::thread_closure_2<F,X,Y> closure_type;
162 internal_start(closure_type::start_routine, new closure_type(f,x,y));
165 tbb_thread_v3& operator=(tbb_thread_v3& x) {
166 if (joinable()) detach();
167 my_handle = x.my_handle;
170 my_thread_id = x.my_thread_id;
172 #endif // _WIN32||_WIN64
175 void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );}
176 bool joinable() const {return my_handle!=0; }
177 //! The completion of the thread represented by *this happens before join() returns.
178 void __TBB_EXPORTED_METHOD join();
179 //! When detach() returns, *this no longer represents the possibly continuing thread of execution.
180 void __TBB_EXPORTED_METHOD detach();
181 ~tbb_thread_v3() {if( joinable() ) detach();}
182 inline id get_id() const;
183 native_handle_type native_handle() { return my_handle; }
185 //! The number of hardware thread contexts.
186 static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
188 native_handle_type my_handle;
191 #endif // _WIN32||_WIN64
193 /** Runs start_routine(closure) on another thread and sets my_handle to the handle of the created thread. */
194 void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine),
196 friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
197 friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 );
200 class tbb_thread_v3::id {
203 id( DWORD id_ ) : my_id(id_) {}
206 id( pthread_t id_ ) : my_id(id_) {}
207 #endif // _WIN32||_WIN64
208 friend class tbb_thread_v3;
212 friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y );
213 friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y );
214 friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y );
215 friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y );
216 friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y );
217 friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y );
219 template<class charT, class traits>
220 friend std::basic_ostream<charT, traits>&
221 operator<< (std::basic_ostream<charT, traits> &out,
222 tbb_thread_v3::id id)
227 friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
228 }; // tbb_thread_v3::id
230 tbb_thread_v3::id tbb_thread_v3::get_id() const {
232 return id(my_thread_id);
234 return id(my_handle);
235 #endif // _WIN32||_WIN64
237 void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
238 tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
239 void __TBB_EXPORTED_FUNC thread_yield_v3();
240 void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
242 inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y)
244 return x.my_id == y.my_id;
246 inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y)
248 return x.my_id != y.my_id;
250 inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y)
252 return x.my_id < y.my_id;
254 inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y)
256 return x.my_id <= y.my_id;
258 inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y)
260 return x.my_id > y.my_id;
262 inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
264 return x.my_id >= y.my_id;
267 } // namespace internal;
269 //! Users reference thread class by name tbb_thread
270 typedef internal::tbb_thread_v3 tbb_thread;
272 using internal::operator==;
273 using internal::operator!=;
274 using internal::operator<;
275 using internal::operator>;
276 using internal::operator<=;
277 using internal::operator>=;
279 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
280 internal::move_v3(t1, t2);
283 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) {
284 tbb::tbb_thread::native_handle_type h = t1.my_handle;
285 t1.my_handle = t2.my_handle;
288 DWORD i = t1.my_thread_id;
289 t1.my_thread_id = t2.my_thread_id;
291 #endif /* _WIN32||_WIN64 */
294 namespace this_tbb_thread {
295 inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
296 //! Offers the operating system the opportunity to schedule another thread.
297 inline void yield() { internal::thread_yield_v3(); }
298 //! The current thread blocks at least until the time specified.
299 inline void sleep(const tick_count::interval_t &i) {
300 internal::thread_sleep_v3(i);
302 } // namespace this_tbb_thread
306 #endif /* __TBB_tbb_thread_H */