2 Copyright 2005-2011 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
33 #include "machine/windows_api.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"
45 #if !TBB_USE_EXCEPTIONS && _MSC_VER
46 // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
47 #pragma warning (push)
48 #pragma warning (disable: 4530)
53 #if !TBB_USE_EXCEPTIONS && _MSC_VER
64 } // namespace internal
66 void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 );
70 //! Allocate a closure
71 void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
72 //! Free a closure allocated by allocate_closure_v3
73 void __TBB_EXPORTED_FUNC free_closure_v3( void* );
75 struct thread_closure_base {
76 void* operator new( size_t size ) {return allocate_closure_v3(size);}
77 void operator delete( void* ptr ) {free_closure_v3(ptr);}
80 template<class F> struct thread_closure_0: thread_closure_base {
83 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
84 thread_closure_0 *self = static_cast<thread_closure_0*>(c);
89 thread_closure_0( const F& f ) : function(f) {}
91 //! Structure used to pass user function with 1 argument to thread.
92 template<class F, class X> struct thread_closure_1: thread_closure_base {
95 //! Routine passed to Windows's _beginthreadex by thread::internal_start() inside tbb.dll
96 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
97 thread_closure_1 *self = static_cast<thread_closure_1*>(c);
98 self->function(self->arg1);
102 thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
104 template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
108 //! Routine passed to Windows's _beginthreadex by thread::internal_start() inside tbb.dll
109 static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
110 thread_closure_2 *self = static_cast<thread_closure_2*>(c);
111 self->function(self->arg1, self->arg2);
115 thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
118 //! Versioned thread class.
119 class tbb_thread_v3 {
120 tbb_thread_v3(const tbb_thread_v3&); // = delete; // Deny access
123 typedef HANDLE native_handle_type;
125 typedef pthread_t native_handle_type;
126 #endif // _WIN32||_WIN64
129 //! Constructs a thread object that does not represent a thread of execution.
130 tbb_thread_v3() : my_handle(0)
133 #endif // _WIN32||_WIN64
136 //! Constructs an object and executes f() in a new thread
137 template <class F> explicit tbb_thread_v3(F f) {
138 typedef internal::thread_closure_0<F> closure_type;
139 internal_start(closure_type::start_routine, new closure_type(f));
141 //! Constructs an object and executes f(x) in a new thread
142 template <class F, class X> tbb_thread_v3(F f, X x) {
143 typedef internal::thread_closure_1<F,X> closure_type;
144 internal_start(closure_type::start_routine, new closure_type(f,x));
146 //! Constructs an object and executes f(x,y) in a new thread
147 template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
148 typedef internal::thread_closure_2<F,X,Y> closure_type;
149 internal_start(closure_type::start_routine, new closure_type(f,x,y));
152 tbb_thread_v3& operator=(tbb_thread_v3& x) {
153 if (joinable()) detach();
154 my_handle = x.my_handle;
157 my_thread_id = x.my_thread_id;
159 #endif // _WIN32||_WIN64
162 void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );}
163 bool joinable() const {return my_handle!=0; }
164 //! The completion of the thread represented by *this happens before join() returns.
165 void __TBB_EXPORTED_METHOD join();
166 //! When detach() returns, *this no longer represents the possibly continuing thread of execution.
167 void __TBB_EXPORTED_METHOD detach();
168 ~tbb_thread_v3() {if( joinable() ) detach();}
169 inline id get_id() const;
170 native_handle_type native_handle() { return my_handle; }
172 //! The number of hardware thread contexts.
173 /** Before TBB 3.0 U4 this methods returned the number of logical CPU in
174 the system. Currently on Windows, Linux and FreeBSD it returns the
175 number of logical CPUs available to the current process in accordance
176 with its affinity mask.
178 NOTE: The return value of this method never changes after its first
179 invocation. This means that changes in the process affinity mask that
180 took place after this method was first invoked will not affect the
181 number of worker threads in the TBB worker threads pool. **/
182 static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
184 native_handle_type my_handle;
187 #endif // _WIN32||_WIN64
189 /** Runs start_routine(closure) on another thread and sets my_handle to the handle of the created thread. */
190 void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine),
192 friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
193 friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 );
196 class tbb_thread_v3::id {
199 id( DWORD id_ ) : my_id(id_) {}
202 id( pthread_t id_ ) : my_id(id_) {}
203 #endif // _WIN32||_WIN64
204 friend class tbb_thread_v3;
208 friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y );
209 friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y );
210 friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y );
211 friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y );
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 );
215 template<class charT, class traits>
216 friend std::basic_ostream<charT, traits>&
217 operator<< (std::basic_ostream<charT, traits> &out,
218 tbb_thread_v3::id id)
223 friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
224 }; // tbb_thread_v3::id
226 tbb_thread_v3::id tbb_thread_v3::get_id() const {
228 return id(my_thread_id);
230 return id(my_handle);
231 #endif // _WIN32||_WIN64
233 void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
234 tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
235 void __TBB_EXPORTED_FUNC thread_yield_v3();
236 void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
238 inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y)
240 return x.my_id == y.my_id;
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;
263 } // namespace internal;
265 //! Users reference thread class by name tbb_thread
266 typedef internal::tbb_thread_v3 tbb_thread;
268 using internal::operator==;
269 using internal::operator!=;
270 using internal::operator<;
271 using internal::operator>;
272 using internal::operator<=;
273 using internal::operator>=;
275 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
276 internal::move_v3(t1, t2);
279 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) {
280 tbb::tbb_thread::native_handle_type h = t1.my_handle;
281 t1.my_handle = t2.my_handle;
284 DWORD i = t1.my_thread_id;
285 t1.my_thread_id = t2.my_thread_id;
287 #endif /* _WIN32||_WIN64 */
290 namespace this_tbb_thread {
291 inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
292 //! Offers the operating system the opportunity to schedule another thread.
293 inline void yield() { internal::thread_yield_v3(); }
294 //! The current thread blocks at least until the time specified.
295 inline void sleep(const tick_count::interval_t &i) {
296 internal::thread_sleep_v3(i);
298 } // namespace this_tbb_thread
302 #endif /* __TBB_tbb_thread_H */