BRE12
tbb_thread.h
1 /*
2  Copyright 2005-2016 Intel Corporation. All Rights Reserved.
3 
4  This file is part of Threading Building Blocks. Threading Building Blocks is free software;
5  you can redistribute it and/or modify it under the terms of the GNU General Public License
6  version 2 as published by the Free Software Foundation. Threading Building Blocks is
7  distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9  See the GNU General Public License for more details. You should have received a copy of
10  the GNU General Public License along with Threading Building Blocks; if not, write to the
11  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12 
13  As a special exception, you may use this file as part of a free software library without
14  restriction. Specifically, if other files instantiate templates or use macros or inline
15  functions from this file, or you compile this file and link it with other files to produce
16  an executable, this file does not by itself cause the resulting executable to be covered
17  by the GNU General Public License. This exception does not however invalidate any other
18  reasons why the executable file might be covered by the GNU General Public License.
19 */
20 
21 #ifndef __TBB_tbb_thread_H
22 #define __TBB_tbb_thread_H
23 
24 #include "tbb_stddef.h"
25 
26 #if _WIN32||_WIN64
27 #include "machine/windows_api.h"
28 #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI
29 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* )
30 namespace tbb { namespace internal {
31 #if __TBB_WIN8UI_SUPPORT
32  typedef size_t thread_id_type;
33 #else // __TBB_WIN8UI_SUPPORT
34  typedef DWORD thread_id_type;
35 #endif // __TBB_WIN8UI_SUPPORT
36 }} //namespace tbb::internal
37 #else
38 #define __TBB_NATIVE_THREAD_ROUTINE void*
39 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* )
40 #include <pthread.h>
41 namespace tbb { namespace internal {
42  typedef pthread_t thread_id_type;
43 }} //namespace tbb::internal
44 #endif // _WIN32||_WIN64
45 
46 #include "atomic.h"
47 #include "internal/_tbb_hash_compare_impl.h"
48 #include "tick_count.h"
49 
50 #if !TBB_USE_EXCEPTIONS && _MSC_VER
51  // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
52  #pragma warning (push)
53  #pragma warning (disable: 4530)
54 #endif
55 
56 #include <utility> //for swap
57 #include <iosfwd>
58 
59 #if !TBB_USE_EXCEPTIONS && _MSC_VER
60  #pragma warning (pop)
61 #endif
62 
63 namespace tbb {
64 
65 namespace internal {
66  class tbb_thread_v3;
67 }
68 
69 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) __TBB_NOEXCEPT(true);
70 
71 namespace internal {
72 
74  void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
76  void __TBB_EXPORTED_FUNC free_closure_v3( void* );
77 
79  void* operator new( size_t size ) {return allocate_closure_v3(size);}
80  void operator delete( void* ptr ) {free_closure_v3(ptr);}
81  };
82 
83  template<class F> struct thread_closure_0: thread_closure_base {
84  F function;
85 
86  static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
87  thread_closure_0 *self = static_cast<thread_closure_0*>(c);
88  self->function();
89  delete self;
90  return 0;
91  }
92  thread_closure_0( const F& f ) : function(f) {}
93  };
95  template<class F, class X> struct thread_closure_1: thread_closure_base {
96  F function;
97  X arg1;
99  static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
100  thread_closure_1 *self = static_cast<thread_closure_1*>(c);
101  self->function(self->arg1);
102  delete self;
103  return 0;
104  }
105  thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
106  };
107  template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
108  F function;
109  X arg1;
110  Y arg2;
112  static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
113  thread_closure_2 *self = static_cast<thread_closure_2*>(c);
114  self->function(self->arg1, self->arg2);
115  delete self;
116  return 0;
117  }
118  thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
119  };
120 
123 #if __TBB_IF_NO_COPY_CTOR_MOVE_SEMANTICS_BROKEN
124  // Workaround for a compiler bug: declaring the copy constructor as public
125  // enables use of the moving constructor.
126  // The definition is not provided in order to prohibit copying.
127  public:
128 #endif
129  tbb_thread_v3(const tbb_thread_v3&); // = delete; // Deny access
130  public:
131 #if _WIN32||_WIN64
132  typedef HANDLE native_handle_type;
133 #else
134  typedef pthread_t native_handle_type;
135 #endif // _WIN32||_WIN64
136 
137  class id;
139  tbb_thread_v3() __TBB_NOEXCEPT(true) : my_handle(0)
140 #if _WIN32||_WIN64
141  , my_thread_id(0)
142 #endif // _WIN32||_WIN64
143  {}
144 
146  template <class F> explicit tbb_thread_v3(F f) {
147  typedef internal::thread_closure_0<F> closure_type;
148  internal_start(closure_type::start_routine, new closure_type(f));
149  }
151  template <class F, class X> tbb_thread_v3(F f, X x) {
152  typedef internal::thread_closure_1<F,X> closure_type;
153  internal_start(closure_type::start_routine, new closure_type(f,x));
154  }
156  template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
157  typedef internal::thread_closure_2<F,X,Y> closure_type;
158  internal_start(closure_type::start_routine, new closure_type(f,x,y));
159  }
160 
161 #if __TBB_CPP11_RVALUE_REF_PRESENT
162  tbb_thread_v3(tbb_thread_v3&& x) __TBB_NOEXCEPT(true)
163  : my_handle(x.my_handle)
164 #if _WIN32||_WIN64
165  , my_thread_id(x.my_thread_id)
166 #endif
167  {
168  x.internal_wipe();
169  }
170  tbb_thread_v3& operator=(tbb_thread_v3&& x) __TBB_NOEXCEPT(true) {
171  internal_move(x);
172  return *this;
173  }
174  private:
175  tbb_thread_v3& operator=(const tbb_thread_v3& x); // = delete;
176  public:
177 #else // __TBB_CPP11_RVALUE_REF_PRESENT
178  tbb_thread_v3& operator=(tbb_thread_v3& x) {
179  internal_move(x);
180  return *this;
181  }
182 #endif // __TBB_CPP11_RVALUE_REF_PRESENT
183 
184  void swap( tbb_thread_v3& t ) __TBB_NOEXCEPT(true) {tbb::swap( *this, t );}
185  bool joinable() const __TBB_NOEXCEPT(true) {return my_handle!=0; }
187  void __TBB_EXPORTED_METHOD join();
189  void __TBB_EXPORTED_METHOD detach();
190  ~tbb_thread_v3() {if( joinable() ) detach();}
191  inline id get_id() const __TBB_NOEXCEPT(true);
192  native_handle_type native_handle() { return my_handle; }
193 
195 
204  static unsigned __TBB_EXPORTED_FUNC hardware_concurrency() __TBB_NOEXCEPT(true);
205  private:
206  native_handle_type my_handle;
207 #if _WIN32||_WIN64
208  thread_id_type my_thread_id;
209 #endif // _WIN32||_WIN64
210 
211  void internal_wipe() __TBB_NOEXCEPT(true) {
212  my_handle = 0;
213 #if _WIN32||_WIN64
214  my_thread_id = 0;
215 #endif
216  }
217  void internal_move(tbb_thread_v3& x) __TBB_NOEXCEPT(true) {
218  if (joinable()) detach();
219  my_handle = x.my_handle;
220 #if _WIN32||_WIN64
221  my_thread_id = x.my_thread_id;
222 #endif // _WIN32||_WIN64
223  x.internal_wipe();
224  }
225 
227  void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine),
228  void* closure );
229  friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
230  friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 ) __TBB_NOEXCEPT(true);
231  };
232 
234  thread_id_type my_id;
235  id( thread_id_type id_ ) : my_id(id_) {}
236 
237  friend class tbb_thread_v3;
238  public:
239  id() __TBB_NOEXCEPT(true) : my_id(0) {}
240 
241  friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y ) __TBB_NOEXCEPT(true);
242  friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y ) __TBB_NOEXCEPT(true);
243  friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y ) __TBB_NOEXCEPT(true);
244  friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y ) __TBB_NOEXCEPT(true);
245  friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y ) __TBB_NOEXCEPT(true);
246  friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y ) __TBB_NOEXCEPT(true);
247 
248  template<class charT, class traits>
249  friend std::basic_ostream<charT, traits>&
250  operator<< (std::basic_ostream<charT, traits> &out,
252  {
253  out << id.my_id;
254  return out;
255  }
256  friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
257 
258  friend inline size_t tbb_hasher( const tbb_thread_v3::id& id ) {
259  __TBB_STATIC_ASSERT(sizeof(id.my_id) <= sizeof(size_t), "Implementaion assumes that thread_id_type fits into machine word");
260  return tbb::tbb_hasher(id.my_id);
261  }
262 
263  // A workaround for lack of tbb::atomic<id> (which would require id to be POD in C++03).
264  friend id atomic_compare_and_swap(id& location, const id& value, const id& comparand){
265  return as_atomic(location.my_id).compare_and_swap(value.my_id, comparand.my_id);
266  }
267  }; // tbb_thread_v3::id
268 
269  tbb_thread_v3::id tbb_thread_v3::get_id() const __TBB_NOEXCEPT(true) {
270 #if _WIN32||_WIN64
271  return id(my_thread_id);
272 #else
273  return id(my_handle);
274 #endif // _WIN32||_WIN64
275  }
276 
277  void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
278  tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
279  void __TBB_EXPORTED_FUNC thread_yield_v3();
280  void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
281 
282  inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_NOEXCEPT(true)
283  {
284  return x.my_id == y.my_id;
285  }
286  inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_NOEXCEPT(true)
287  {
288  return x.my_id != y.my_id;
289  }
290  inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_NOEXCEPT(true)
291  {
292  return x.my_id < y.my_id;
293  }
294  inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_NOEXCEPT(true)
295  {
296  return x.my_id <= y.my_id;
297  }
298  inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_NOEXCEPT(true)
299  {
300  return x.my_id > y.my_id;
301  }
302  inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_NOEXCEPT(true)
303  {
304  return x.my_id >= y.my_id;
305  }
306 
307 } // namespace internal;
308 
311 
312 using internal::operator==;
313 using internal::operator!=;
314 using internal::operator<;
315 using internal::operator>;
316 using internal::operator<=;
317 using internal::operator>=;
318 
319 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
320  internal::move_v3(t1, t2);
321 }
322 
323 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) __TBB_NOEXCEPT(true) {
324  std::swap(t1.my_handle, t2.my_handle);
325 #if _WIN32||_WIN64
326  std::swap(t1.my_thread_id, t2.my_thread_id);
327 #endif /* _WIN32||_WIN64 */
328 }
329 
330 namespace this_tbb_thread {
331  inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
333  inline void yield() { internal::thread_yield_v3(); }
335  inline void sleep(const tick_count::interval_t &i) {
336  internal::thread_sleep_v3(i);
337  }
338 } // namespace this_tbb_thread
339 
340 } // namespace tbb
341 
342 #endif /* __TBB_tbb_thread_H */
tbb_thread_v3(F f)
Constructs an object and executes f() in a new thread.
Definition: tbb_thread.h:146
tbb_thread_v3(F f, X x, Y y)
Constructs an object and executes f(x,y) in a new thread.
Definition: tbb_thread.h:156
Versioned thread class.
Definition: tbb_thread.h:122
Definition: tbb_thread.h:83
static __TBB_NATIVE_THREAD_ROUTINE start_routine(void *c)
Routine passed to Windows&#39;s _beginthreadex by thread::internal_start() inside tbb.dll.
Definition: tbb_thread.h:99
tbb_thread_v3() __TBB_NOEXCEPT(true)
Constructs a thread object that does not represent a thread of execution.
Definition: tbb_thread.h:139
Definition: tbb_thread.h:78
static __TBB_NATIVE_THREAD_ROUTINE start_routine(void *c)
Routine passed to Windows&#39;s _beginthreadex by thread::internal_start() inside tbb.dll.
Definition: tbb_thread.h:112
tbb_thread_v3(F f, X x)
Constructs an object and executes f(x) in a new thread.
Definition: tbb_thread.h:151
Structure used to pass user function with 1 argument to thread.
Definition: tbb_thread.h:95
Definition: _flow_graph_async_msg_impl.h:32
Definition: tbb_thread.h:233
The namespace tbb contains all components of the library.
Definition: parallel_for.h:44
Relative time interval.
Definition: tick_count.h:41
Definition: tbb_thread.h:107
internal::tbb_thread_v3 tbb_thread
Users reference thread class by name tbb_thread.
Definition: tbb_thread.h:310