]> git.sesse.net Git - casparcg/blob - tbb30_20100406oss/include/tbb/tbb_thread.h
2.0.2: Updated to boost 1.48.
[casparcg] / tbb30_20100406oss / include / tbb / tbb_thread.h
1 /*
2     Copyright 2005-2010 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 <windows.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 #include <exception>             // Need std::terminate from here.
45
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)
50 #endif
51
52 #include <iosfwd>
53
54 #if !TBB_USE_EXCEPTIONS && _MSC_VER
55     #pragma warning (pop)
56 #endif
57
58 namespace tbb {
59
60 //! @cond INTERNAL
61 namespace internal {
62     
63     class tbb_thread_v3;
64
65 } // namespace internal
66
67 void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ); 
68
69 namespace internal {
70
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* );
75    
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);}
79     };
80
81     template<class F> struct thread_closure_0: thread_closure_base {
82         F function;
83
84         static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
85             thread_closure_0 *self = static_cast<thread_closure_0*>(c);
86             __TBB_TRY {
87                 self->function();
88             } __TBB_CATCH( ... ) {
89                 std::terminate();
90             }
91             delete self;
92             return 0;
93         }
94         thread_closure_0( const F& f ) : function(f) {}
95     };
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 {
98         F function;
99         X arg1;
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);
103             __TBB_TRY {
104                 self->function(self->arg1);
105             } __TBB_CATCH( ... ) {
106                 std::terminate();
107             }
108             delete self;
109             return 0;
110         }
111         thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
112     };
113     template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
114         F function;
115         X arg1;
116         Y arg2;
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);
120             __TBB_TRY {
121                 self->function(self->arg1, self->arg2);
122             } __TBB_CATCH( ... ) {
123                 std::terminate();
124             }
125             delete self;
126             return 0;
127         }
128         thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
129     };
130
131     //! Versioned thread class.
132     class tbb_thread_v3 {
133         tbb_thread_v3(const tbb_thread_v3&); // = delete;   // Deny access
134     public:
135 #if _WIN32||_WIN64
136         typedef HANDLE native_handle_type; 
137 #else
138         typedef pthread_t native_handle_type; 
139 #endif // _WIN32||_WIN64
140
141         class id;
142         //! Constructs a thread object that does not represent a thread of execution. 
143         tbb_thread_v3() : my_handle(0)
144 #if _WIN32||_WIN64
145             , my_thread_id(0)
146 #endif // _WIN32||_WIN64
147         {}
148         
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));
153         }
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));
158         }
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));
163         }
164
165         tbb_thread_v3& operator=(tbb_thread_v3& x) {
166             if (joinable()) detach();
167             my_handle = x.my_handle;
168             x.my_handle = 0;
169 #if _WIN32||_WIN64
170             my_thread_id = x.my_thread_id;
171             x.my_thread_id = 0;
172 #endif // _WIN32||_WIN64
173             return *this;
174         }
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; }
184     
185         //! The number of hardware thread contexts.
186         static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
187     private:
188         native_handle_type my_handle; 
189 #if _WIN32||_WIN64
190         DWORD my_thread_id;
191 #endif // _WIN32||_WIN64
192
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), 
195                              void* closure );
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 ); 
198     };
199         
200     class tbb_thread_v3::id { 
201 #if _WIN32||_WIN64
202         DWORD my_id;
203         id( DWORD id_ ) : my_id(id_) {}
204 #else
205         pthread_t my_id;
206         id( pthread_t id_ ) : my_id(id_) {}
207 #endif // _WIN32||_WIN64
208         friend class tbb_thread_v3;
209     public:
210         id() : my_id(0) {}
211
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 );
218         
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)
223         {
224             out << id.my_id;
225             return out;
226         }
227         friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
228     }; // tbb_thread_v3::id
229
230     tbb_thread_v3::id tbb_thread_v3::get_id() const {
231 #if _WIN32||_WIN64
232         return id(my_thread_id);
233 #else
234         return id(my_handle);
235 #endif // _WIN32||_WIN64
236     }
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);
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     inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
263     {
264         return x.my_id >= y.my_id;
265     }
266
267 } // namespace internal;
268
269 //! Users reference thread class by name tbb_thread
270 typedef internal::tbb_thread_v3 tbb_thread;
271
272 using internal::operator==;
273 using internal::operator!=;
274 using internal::operator<;
275 using internal::operator>;
276 using internal::operator<=;
277 using internal::operator>=;
278
279 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
280     internal::move_v3(t1, t2);
281 }
282
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;
286     t2.my_handle = h;
287 #if _WIN32||_WIN64
288     DWORD i = t1.my_thread_id;
289     t1.my_thread_id = t2.my_thread_id;
290     t2.my_thread_id = i;
291 #endif /* _WIN32||_WIN64 */
292 }
293
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);  
301     }
302 }  // namespace this_tbb_thread
303
304 } // namespace tbb
305
306 #endif /* __TBB_tbb_thread_H */