Ticket #4562: thread.hpp

File thread.hpp, 14.3 KB (added by anonymous, 12 years ago)
Line 
1#ifndef BOOST_THREAD_THREAD_COMMON_HPP
2#define BOOST_THREAD_THREAD_COMMON_HPP
3// Distributed under the Boost Software License, Version 1.0. (See
4// accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6// (C) Copyright 2007-10 Anthony Williams
7
8#include <boost/thread/exceptions.hpp>
9#ifndef BOOST_NO_IOSTREAM
10#include <ostream>
11#endif
12#include <boost/thread/detail/move.hpp>
13#include <boost/thread/mutex.hpp>
14#include <boost/thread/xtime.hpp>
15#include <boost/thread/detail/thread_heap_alloc.hpp>
16#include <boost/utility.hpp>
17#include <boost/assert.hpp>
18#include <list>
19#include <algorithm>
20#include <boost/ref.hpp>
21#include <boost/cstdint.hpp>
22#include <boost/bind.hpp>
23#include <stdlib.h>
24#include <memory>
25#include <boost/utility/enable_if.hpp>
26#include <boost/type_traits/remove_reference.hpp>
27
28#include <boost/config/abi_prefix.hpp>
29
30#ifdef BOOST_MSVC
31#pragma warning(push)
32#pragma warning(disable:4251)
33#endif
34
35namespace boost
36{
37 namespace detail
38 {
39 template<typename F>
40 class thread_data:
41 public detail::thread_data_base
42 {
43 public:
44#ifndef BOOST_NO_RVALUE_REFERENCES
45 thread_data(F&& f_):
46 f(static_cast<F&&>(f_))
47 {}
48 thread_data(F& f_):
49 f(f_)
50 {}
51#else
52 thread_data(F f_):
53 f(f_)
54 {}
55 thread_data(detail::thread_move_t<F> f_):
56 f(f_)
57 {}
58#endif
59 void run()
60 {
61 f();
62 }
63 private:
64 F f;
65
66 void operator=(thread_data&);
67 thread_data(thread_data&);
68 };
69
70 template<typename F>
71 class thread_data<boost::reference_wrapper<F> >:
72 public detail::thread_data_base
73 {
74 private:
75 F& f;
76
77 void operator=(thread_data&);
78 thread_data(thread_data&);
79 public:
80 thread_data(boost::reference_wrapper<F> f_):
81 f(f_)
82 {}
83
84 void run()
85 {
86 f();
87 }
88 };
89
90 template<typename F>
91 class thread_data<const boost::reference_wrapper<F> >:
92 public detail::thread_data_base
93 {
94 private:
95 F& f;
96 void operator=(thread_data&);
97 thread_data(thread_data&);
98 public:
99 thread_data(const boost::reference_wrapper<F> f_):
100 f(f_)
101 {}
102
103 void run()
104 {
105 f();
106 }
107 };
108 }
109
110 class BOOST_THREAD_DECL thread
111 {
112 private:
113 thread(thread&);
114 thread& operator=(thread&);
115
116 void release_handle();
117
118 detail::thread_data_ptr thread_info;
119
120 void start_thread();
121
122 explicit thread(detail::thread_data_ptr data);
123
124 detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
125
126#ifndef BOOST_NO_RVALUE_REFERENCES
127 template<typename F>
128 static inline detail::thread_data_ptr make_thread_info(F&& f)
129 {
130 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f)));
131 }
132 static inline detail::thread_data_ptr make_thread_info(void (*f)())
133 {
134 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f)));
135 }
136#else
137 template<typename F>
138 static inline detail::thread_data_ptr make_thread_info(F f)
139 {
140 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
141 }
142 template<typename F>
143 static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f)
144 {
145 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
146 }
147
148#endif
149 struct dummy;
150 public:
151#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
152 thread(const volatile thread&);
153#endif
154 thread();
155 ~thread();
156
157#ifndef BOOST_NO_RVALUE_REFERENCES
158#ifdef BOOST_MSVC
159 template <class F>
160 explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
161 thread_info(make_thread_info(static_cast<F&&>(f)))
162 {
163 start_thread();
164 }
165#else
166 template <class F>
167 thread(F&& f):
168 thread_info(make_thread_info(static_cast<F&&>(f)))
169 {
170 start_thread();
171 }
172#endif
173
174 thread(thread&& other)
175 {
176 thread_info.swap(other.thread_info);
177 }
178
179 thread& operator=(thread&& other)
180 {
181 thread_info=other.thread_info;
182 other.thread_info.reset();
183 return *this;
184 }
185
186 thread&& move()
187 {
188 return static_cast<thread&&>(*this);
189 }
190
191#else
192#ifdef BOOST_NO_SFINAE
193 template <class F>
194 explicit thread(F f):
195 thread_info(make_thread_info(f))
196 {
197 start_thread();
198 }
199#else
200 template <class F>
201 explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
202 thread_info(make_thread_info(f))
203 {
204 start_thread();
205 }
206#endif
207
208 template <class F>
209 explicit thread(detail::thread_move_t<F> f):
210 thread_info(make_thread_info(f))
211 {
212 start_thread();
213 }
214
215 thread(detail::thread_move_t<thread> x)
216 {
217 thread_info=x->thread_info;
218 x->thread_info.reset();
219 }
220
221#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
222 thread& operator=(thread x)
223 {
224 swap(x);
225 return *this;
226 }
227#else
228 thread& operator=(detail::thread_move_t<thread> x)
229 {
230 thread new_thread(x);
231 swap(new_thread);
232 return *this;
233 }
234#endif
235 operator detail::thread_move_t<thread>()
236 {
237 return move();
238 }
239
240 detail::thread_move_t<thread> move()
241 {
242 detail::thread_move_t<thread> x(*this);
243 return x;
244 }
245
246#endif
247
248 template <class F,class A1>
249 thread(F f,A1 a1):
250 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
251 {
252 start_thread();
253 }
254 template <class F,class A1,class A2>
255 thread(F f,A1 a1,A2 a2):
256 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
257 {
258 start_thread();
259 }
260
261 template <class F,class A1,class A2,class A3>
262 thread(F f,A1 a1,A2 a2,A3 a3):
263 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
264 {
265 start_thread();
266 }
267
268 template <class F,class A1,class A2,class A3,class A4>
269 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
270 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
271 {
272 start_thread();
273 }
274
275 template <class F,class A1,class A2,class A3,class A4,class A5>
276 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
277 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
278 {
279 start_thread();
280 }
281
282 template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
283 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
284 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
285 {
286 start_thread();
287 }
288
289 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
290 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
291 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
292 {
293 start_thread();
294 }
295
296 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
297 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
298 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
299 {
300 start_thread();
301 }
302
303 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
304 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
305 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
306 {
307 start_thread();
308 }
309
310 void swap(thread& x)
311 {
312 thread_info.swap(x.thread_info);
313 }
314
315 class id;
316 id get_id() const;
317
318
319 bool joinable() const;
320 void join();
321 bool timed_join(const system_time& wait_until);
322
323 template<typename TimeDuration>
324 inline bool timed_join(TimeDuration const& rel_time)
325 {
326 return timed_join(get_system_time()+rel_time);
327 }
328 void detach();
329
330 static unsigned hardware_concurrency();
331
332 typedef detail::thread_data_base::native_handle_type native_handle_type;
333 native_handle_type native_handle();
334
335 // backwards compatibility
336 bool operator==(const thread& other) const;
337 bool operator!=(const thread& other) const;
338
339 static inline void yield()
340 {
341 this_thread::yield();
342 }
343
344 static inline void sleep(const system_time& xt)
345 {
346 this_thread::sleep(xt);
347 }
348
349 // extensions
350 void interrupt();
351 bool interruption_requested() const;
352 };
353
354 inline void swap(thread& lhs,thread& rhs)
355 {
356 return lhs.swap(rhs);
357 }
358
359#ifndef BOOST_NO_RVALUE_REFERENCES
360 inline thread&& move(thread& t)
361 {
362 return static_cast<thread&&>(t);
363 }
364 inline thread&& move(thread&& t)
365 {
366 return static_cast<thread&&>(t);
367 }
368#else
369 inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
370 {
371 return t;
372 }
373#endif
374
375 namespace this_thread
376 {
377 thread::id BOOST_THREAD_DECL get_id();
378
379 void BOOST_THREAD_DECL interruption_point();
380 bool BOOST_THREAD_DECL interruption_enabled();
381 bool BOOST_THREAD_DECL interruption_requested();
382
383 inline void sleep(xtime const& abs_time)
384 {
385 sleep(system_time(abs_time));
386 }
387 }
388
389 class thread::id
390 {
391 private:
392 detail::thread_data_ptr thread_data;
393
394 id(detail::thread_data_ptr thread_data_):
395 thread_data(thread_data_)
396 {}
397 friend class thread;
398 friend id BOOST_THREAD_DECL this_thread::get_id();
399 public:
400 id():
401 thread_data()
402 {}
403
404 bool operator==(const id& y) const
405 {
406 return thread_data==y.thread_data;
407 }
408
409 bool operator!=(const id& y) const
410 {
411 return thread_data!=y.thread_data;
412 }
413
414 bool operator<(const id& y) const
415 {
416 return thread_data<y.thread_data;
417 }
418
419 bool operator>(const id& y) const
420 {
421 return y.thread_data<thread_data;
422 }
423
424 bool operator<=(const id& y) const
425 {
426 return !(y.thread_data<thread_data);
427 }
428
429 bool operator>=(const id& y) const
430 {
431 return !(thread_data<y.thread_data);
432 }
433
434#ifndef BOOST_NO_IOSTREAM
435#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
436 template<class charT, class traits>
437 friend std::basic_ostream<charT, traits>&
438 operator<<(std::basic_ostream<charT, traits>& os, const id& x)
439 {
440 if(x.thread_data)
441 {
442 return os<<x.thread_data;
443 }
444 else
445 {
446 return os<<"{Not-any-thread}";
447 }
448 }
449#else
450 template<class charT, class traits>
451 std::basic_ostream<charT, traits>&
452 print(std::basic_ostream<charT, traits>& os)
453 {
454 if(thread_data)
455 {
456 return os<<thread_data;
457 }
458 else
459 {
460 return os<<"{Not-any-thread}";
461 }
462 }
463
464#endif
465#endif
466 };
467
468#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
469 template<class charT, class traits>
470 std::basic_ostream<charT, traits>&
471 operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
472 {
473 return x.print(os);
474 }
475#endif
476
477 inline bool thread::operator==(const thread& other) const
478 {
479 return get_id()==other.get_id();
480 }
481
482 inline bool thread::operator!=(const thread& other) const
483 {
484 return get_id()!=other.get_id();
485 }
486
487 namespace detail
488 {
489 struct thread_exit_function_base
490 {
491 virtual ~thread_exit_function_base()
492 {}
493 virtual void operator()()=0;
494 };
495
496 template<typename F>
497 struct thread_exit_function:
498 thread_exit_function_base
499 {
500 F f;
501
502 thread_exit_function(F f_):
503 f(f_)
504 {}
505
506 void operator()()
507 {
508 f();
509 }
510 };
511
512 void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
513 }
514
515 namespace this_thread
516 {
517 template<typename F>
518 void at_thread_exit(F f)
519 {
520 detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
521 detail::add_thread_exit_function(thread_exit_func);
522 }
523 }
524}
525
526#ifdef BOOST_MSVC
527#pragma warning(pop)
528#endif
529
530#include <boost/config/abi_suffix.hpp>
531
532#endif