]> git.sesse.net Git - casparcg/blob - tbb/include/tbb/tbb_thread.h
2.0.0.2: Updated tbb version.
[casparcg] / tbb / include / tbb / tbb_thread.h
1 /*
2     Copyright 2005-2011 Intel Corporation.  All Rights Reserved.
3
4     This file is part of Threading Building Blocks.
5
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.
9
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.
14
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
18
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.
27 */
28
29 #ifndef __TBB_tbb_thread_H
30 #define __TBB_tbb_thread_H
31
32 #if _WIN32||_WIN64
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* )
36 #else
37 #define __TBB_NATIVE_THREAD_ROUTINE void*
38 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* )
39 #include <pthread.h>
40 #endif // _WIN32||_WIN64
41
42 #include "tbb_stddef.h"
43 #include "tick_count.h"
44
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)
49 #endif
50
51 #include <iosfwd>
52
53 #if !TBB_USE_EXCEPTIONS && _MSC_VER
54     #pragma warning (pop)
55 #endif
56
57 namespace tbb {
58
59 //! @cond INTERNAL
60 namespace internal {
61     
62     class tbb_thread_v3;
63
64 } // namespace internal
65
66 void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ); 
67
68 namespace internal {
69
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* );
74    
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);}
78     };
79
80     template<class F> struct thread_closure_0: thread_closure_base {
81         F function;
82
83         static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
84             thread_closure_0 *self = static_cast<thread_closure_0*>(c);
85             self->function();
86             delete self;
87             return 0;
88         }
89         thread_closure_0( const F& f ) : function(f) {}
90     };
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 {
93         F function;
94         X arg1;
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);
99             delete self;
100             return 0;
101         }
102         thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
103     };
104     template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
105         F function;
106         X arg1;
107         Y arg2;
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);
112             delete self;
113             return 0;
114         }
115         thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
116     };
117
118     //! Versioned thread class.
119     class tbb_thread_v3 {
120         tbb_thread_v3(const tbb_thread_v3&); // = delete;   // Deny access
121     public:
122 #if _WIN32||_WIN64
123         typedef HANDLE native_handle_type; 
124 #else
125         typedef pthread_t native_handle_type; 
126 #endif // _WIN32||_WIN64
127
128         class id;
129         //! Constructs a thread object that does not represent a thread of execution. 
130         tbb_thread_v3() : my_handle(0)
131 #if _WIN32||_WIN64
132             , my_thread_id(0)
133 #endif // _WIN32||_WIN64
134         {}
135         
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));
140         }
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));
145         }
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));
150         }
151
152         tbb_thread_v3& operator=(tbb_thread_v3& x) {
153             if (joinable()) detach();
154             my_handle = x.my_handle;
155             x.my_handle = 0;
156 #if _WIN32||_WIN64
157             my_thread_id = x.my_thread_id;
158             x.my_thread_id = 0;
159 #endif // _WIN32||_WIN64
160             return *this;
161         }
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; }
171     
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.
177             
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();
183     private:
184         native_handle_type my_handle; 
185 #if _WIN32||_WIN64
186         DWORD my_thread_id;
187 #endif // _WIN32||_WIN64
188
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), 
191                              void* closure );
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 ); 
194     };
195         
196     class tbb_thread_v3::id { 
197 #if _WIN32||_WIN64
198         DWORD my_id;
199         id( DWORD id_ ) : my_id(id_) {}
200 #else
201         pthread_t my_id;
202         id( pthread_t id_ ) : my_id(id_) {}
203 #endif // _WIN32||_WIN64
204         friend class tbb_thread_v3;
205     public:
206         id() : my_id(0) {}
207
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 );
214         
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)
219         {
220             out << id.my_id;
221             return out;
222         }
223         friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
224     }; // tbb_thread_v3::id
225
226     tbb_thread_v3::id tbb_thread_v3::get_id() const {
227 #if _WIN32||_WIN64
228         return id(my_thread_id);
229 #else
230         return id(my_handle);
231 #endif // _WIN32||_WIN64
232     }
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);
237
238     inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y)
239     {
240         return x.my_id == y.my_id;
241     }
242     inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y)
243     {
244         return x.my_id != y.my_id;
245     }
246     inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y)
247     {
248         return x.my_id < y.my_id;
249     }
250     inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y)
251     {
252         return x.my_id <= y.my_id;
253     }
254     inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y)
255     {
256         return x.my_id > y.my_id;
257     }
258     inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
259     {
260         return x.my_id >= y.my_id;
261     }
262
263 } // namespace internal;
264
265 //! Users reference thread class by name tbb_thread
266 typedef internal::tbb_thread_v3 tbb_thread;
267
268 using internal::operator==;
269 using internal::operator!=;
270 using internal::operator<;
271 using internal::operator>;
272 using internal::operator<=;
273 using internal::operator>=;
274
275 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
276     internal::move_v3(t1, t2);
277 }
278
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;
282     t2.my_handle = h;
283 #if _WIN32||_WIN64
284     DWORD i = t1.my_thread_id;
285     t1.my_thread_id = t2.my_thread_id;
286     t2.my_thread_id = i;
287 #endif /* _WIN32||_WIN64 */
288 }
289
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);  
297     }
298 }  // namespace this_tbb_thread
299
300 } // namespace tbb
301
302 #endif /* __TBB_tbb_thread_H */