Ticket #9078: thread.hpp

File thread.hpp, 24.9 KB (added by avinash_march1988@…, 9 years ago)

The mentioned header file. There are many such instances of missing function definitions.

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-2010 Anthony Williams
7// (C) Copyright 20011-2012 Vicente J. Botet Escriba
8
9#include <boost/thread/detail/config.hpp>
10
11#include <boost/thread/exceptions.hpp>
12#ifndef BOOST_NO_IOSTREAM
13#include <ostream>
14#endif
15#include <boost/thread/detail/move.hpp>
16#include <boost/thread/mutex.hpp>
17#if defined BOOST_THREAD_USES_DATETIME
18#include <boost/thread/xtime.hpp>
19#endif
20#include <boost/thread/detail/thread_heap_alloc.hpp>
21#include <boost/thread/detail/make_tuple_indices.hpp>
22#include <boost/thread/detail/invoke.hpp>
23#include <boost/thread/detail/is_convertible.hpp>
24#include <boost/assert.hpp>
25#include <list>
26#include <algorithm>
27#include <boost/ref.hpp>
28#include <boost/cstdint.hpp>
29#include <boost/bind.hpp>
30#include <stdlib.h>
31#include <memory>
32#include <boost/utility/enable_if.hpp>
33#include <boost/type_traits/remove_reference.hpp>
34#include <boost/io/ios_state.hpp>
35#include <boost/type_traits/is_same.hpp>
36#include <boost/type_traits/decay.hpp>
37#include <boost/functional/hash.hpp>
38#ifdef BOOST_THREAD_USES_CHRONO
39#include <boost/chrono/system_clocks.hpp>
40#include <boost/chrono/ceil.hpp>
41#endif
42
43#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
44#include <tuple>
45#endif
46#include <boost/config/abi_prefix.hpp>
47
48#ifdef BOOST_MSVC
49#pragma warning(push)
50#pragma warning(disable:4251)
51#endif
52
53namespace boost
54{
55
56 namespace detail
57 {
58
59#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
60
61 template<typename F, class ...ArgTypes>
62 class thread_data:
63 public detail::thread_data_base
64 {
65 public:
66 BOOST_THREAD_NO_COPYABLE(thread_data)
67#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
68 thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_):
69 fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...)
70 {}
71#endif
72 template <std::size_t ...Indices>
73 void run2(tuple_indices<Indices...>)
74 {
75
76 invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
77 }
78 void run()
79 {
80 typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, ArgTypes...> >::value, 1>::type index_type;
81
82 run2(index_type());
83 }
84
85 private:
86 std::tuple<typename decay<F>::type, typename decay<ArgTypes>::type...> fp;
87 };
88#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
89
90 template<typename F>
91 class thread_data:
92 public detail::thread_data_base
93 {
94 public:
95 BOOST_THREAD_NO_COPYABLE(thread_data)
96#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
97 thread_data(BOOST_THREAD_RV_REF(F) f_):
98 f(boost::forward<F>(f_))
99 {}
100// This overloading must be removed if we want the packaged_task's tests to pass.
101// thread_data(F& f_):
102// f(f_)
103// {}
104#else
105
106 thread_data(BOOST_THREAD_RV_REF(F) f_):
107 f(f_)
108 {}
109 thread_data(F f_):
110 f(f_)
111 {}
112#endif
113 //thread_data() {}
114
115 void run()
116 {
117 f();
118 }
119
120 private:
121 F f;
122 };
123
124 template<typename F>
125 class thread_data<boost::reference_wrapper<F> >:
126 public detail::thread_data_base
127 {
128 private:
129 F& f;
130 public:
131 BOOST_THREAD_NO_COPYABLE(thread_data)
132 thread_data(boost::reference_wrapper<F> f_):
133 f(f_)
134 {}
135 void run()
136 {
137 f();
138 }
139 };
140
141 template<typename F>
142 class thread_data<const boost::reference_wrapper<F> >:
143 public detail::thread_data_base
144 {
145 private:
146 F& f;
147 public:
148 BOOST_THREAD_NO_COPYABLE(thread_data)
149 thread_data(const boost::reference_wrapper<F> f_):
150 f(f_)
151 {}
152 void run()
153 {
154 f();
155 }
156 };
157#endif
158 }
159
160 class BOOST_THREAD_DECL thread
161 {
162 public:
163 typedef thread_attributes attributes;
164
165 BOOST_THREAD_MOVABLE_ONLY(thread)
166 private:
167
168 struct dummy;
169
170 void release_handle();
171
172 detail::thread_data_ptr thread_info;
173
174 private:
175 bool start_thread_noexcept();
176 bool start_thread_noexcept(const attributes& attr);
177 public:
178 void start_thread()
179 {
180 if (!start_thread_noexcept())
181 {
182 boost::throw_exception(thread_resource_error());
183 }
184 }
185 void start_thread(const attributes& attr)
186 {
187 if (!start_thread_noexcept(attr))
188 {
189 boost::throw_exception(thread_resource_error());
190 }
191 }
192
193 explicit thread(detail::thread_data_ptr data);
194
195 detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
196
197#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
198#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
199 template<typename F, class ...ArgTypes>
200 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
201 {
202 return detail::thread_data_ptr(detail::heap_new<
203 detail::thread_data<typename boost::remove_reference<F>::type, ArgTypes...>
204 >(
205 boost::forward<F>(f), boost::forward<ArgTypes>(args)...
206 )
207 );
208 }
209#else
210 template<typename F>
211 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
212 {
213 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(
214 boost::forward<F>(f)));
215 }
216#endif
217 static inline detail::thread_data_ptr make_thread_info(void (*f)())
218 {
219 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(
220 boost::forward<void(*)()>(f)));
221 }
222#else
223 template<typename F>
224 static inline detail::thread_data_ptr make_thread_info(F f
225 , typename disable_if_c<
226 //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value ||
227 is_same<typename decay<F>::type, thread>::value,
228 dummy* >::type=0
229 )
230 {
231 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
232 }
233 template<typename F>
234 static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
235 {
236 return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
237 }
238
239#endif
240 public:
241#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
242#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
243 thread(const volatile thread&);
244#endif
245#endif
246 thread() BOOST_NOEXCEPT;
247 ~thread()
248 {
249
250 #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
251 if (joinable()) {
252 std::terminate();
253 }
254 #else
255 detach();
256 #endif
257 }
258#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
259 template <
260 class F
261 >
262 explicit thread(BOOST_THREAD_RV_REF(F) f
263 //, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
264 ):
265 thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
266 {
267 start_thread();
268 }
269 template <
270 class F
271 >
272 thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
273 thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
274 {
275 start_thread(attrs);
276 }
277
278#else
279#ifdef BOOST_NO_SFINAE
280 template <class F>
281 explicit thread(F f):
282 thread_info(make_thread_info(f))
283 {
284 start_thread();
285 }
286 template <class F>
287 thread(attributes const& attrs, F f):
288 thread_info(make_thread_info(f))
289 {
290 start_thread(attrs);
291 }
292#else
293 template <class F>
294 explicit thread(F f
295 , typename disable_if_c<
296 boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
297 //|| is_same<typename decay<F>::type, thread>::value
298 , dummy* >::type=0
299 ):
300 thread_info(make_thread_info(f))
301 {
302 start_thread();
303 }
304 template <class F>
305 thread(attributes const& attrs, F f
306 , typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
307 ):
308 thread_info(make_thread_info(f))
309 {
310 start_thread(attrs);
311 }
312#endif
313 template <class F>
314 explicit thread(BOOST_THREAD_RV_REF(F) f
315 , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
316 ):
317#ifdef BOOST_THREAD_USES_MOVE
318 thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
319#else
320 thread_info(make_thread_info(f)) // todo : Add forward
321#endif
322 {
323 start_thread();
324 }
325
326 template <class F>
327 thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
328#ifdef BOOST_THREAD_USES_MOVE
329 thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
330#else
331 thread_info(make_thread_info(f)) // todo : Add forward
332#endif
333 {
334 start_thread(attrs);
335 }
336#endif
337 thread(BOOST_THREAD_RV_REF(thread) x)
338 {
339 thread_info=BOOST_THREAD_RV(x).thread_info;
340 BOOST_THREAD_RV(x).thread_info.reset();
341 }
342#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
343#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
344 thread& operator=(thread x)
345 {
346 swap(x);
347 return *this;
348 }
349#endif
350#endif
351
352 thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT
353 {
354
355#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
356 if (joinable()) std::terminate();
357#endif
358 thread_info=BOOST_THREAD_RV(other).thread_info;
359 BOOST_THREAD_RV(other).thread_info.reset();
360 return *this;
361 }
362
363#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
364 template <class F, class Arg, class ...Args>
365 thread(F&& f, Arg&& arg, Args&&... args) :
366 thread_info(make_thread_info(
367 thread_detail::decay_copy(boost::forward<F>(f)),
368 thread_detail::decay_copy(boost::forward<Arg>(arg)),
369 thread_detail::decay_copy(boost::forward<Args>(args))...)
370 )
371
372 {
373 start_thread();
374 }
375 template <class F, class Arg, class ...Args>
376 thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) :
377 thread_info(make_thread_info(
378 thread_detail::decay_copy(boost::forward<F>(f)),
379 thread_detail::decay_copy(boost::forward<Arg>(arg)),
380 thread_detail::decay_copy(boost::forward<Args>(args))...)
381 )
382
383 {
384 start_thread(attrs);
385 }
386#else
387 template <class F,class A1>
388 thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0):
389 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
390 {
391 start_thread();
392 }
393 template <class F,class A1,class A2>
394 thread(F f,A1 a1,A2 a2):
395 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
396 {
397 start_thread();
398 }
399
400 template <class F,class A1,class A2,class A3>
401 thread(F f,A1 a1,A2 a2,A3 a3):
402 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
403 {
404 start_thread();
405 }
406
407 template <class F,class A1,class A2,class A3,class A4>
408 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
409 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
410 {
411 start_thread();
412 }
413
414 template <class F,class A1,class A2,class A3,class A4,class A5>
415 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
416 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
417 {
418 start_thread();
419 }
420
421 template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
422 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
423 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
424 {
425 start_thread();
426 }
427
428 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
429 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
430 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
431 {
432 start_thread();
433 }
434
435 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
436 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
437 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
438 {
439 start_thread();
440 }
441
442 template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
443 thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
444 thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
445 {
446 start_thread();
447 }
448#endif
449 void swap(thread& x) BOOST_NOEXCEPT
450 {
451 thread_info.swap(x.thread_info);
452 }
453
454 class id;
455#ifdef BOOST_THREAD_PLATFORM_PTHREAD
456 inline id get_id() const BOOST_NOEXCEPT;
457#else
458 id get_id() const BOOST_NOEXCEPT;
459#endif
460
461
462 bool joinable() const BOOST_NOEXCEPT;
463 private:
464 bool join_noexcept();
465 public:
466 inline void join();
467
468#ifdef BOOST_THREAD_USES_CHRONO
469 template <class Rep, class Period>
470 bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
471 {
472 return try_join_until(chrono::steady_clock::now() + rel_time);
473 }
474 template <class Clock, class Duration>
475 bool try_join_until(const chrono::time_point<Clock, Duration>& t)
476 {
477 using namespace chrono;
478 system_clock::time_point s_now = system_clock::now();
479 bool joined= false;
480 do {
481 typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
482 if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
483 joined = try_join_until(s_now + d);
484 } while (! joined);
485 return true;
486 }
487 template <class Duration>
488 bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
489 {
490 using namespace chrono;
491 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
492 return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
493 }
494#endif
495#if defined(BOOST_THREAD_PLATFORM_WIN32)
496 private:
497 bool do_try_join_until_noexcept(uintmax_t milli, bool& res);
498 inline bool do_try_join_until(uintmax_t milli);
499 public:
500 bool timed_join(const system_time& abs_time);
501 //{
502 // return do_try_join_until(get_milliseconds_until(wait_until));
503 //}
504
505#ifdef BOOST_THREAD_USES_CHRONO
506 bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
507 {
508 chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
509 return do_try_join_until(rel_time.count());
510 }
511#endif
512
513
514#else
515 private:
516 bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res);
517 inline bool do_try_join_until(struct timespec const &timeout);
518 public:
519#if defined BOOST_THREAD_USES_DATETIME
520 bool timed_join(const system_time& abs_time)
521 {
522 struct timespec const ts=detail::to_timespec(abs_time);
523 return do_try_join_until(ts);
524 }
525#endif
526#ifdef BOOST_THREAD_USES_CHRONO
527 bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
528 {
529 using namespace chrono;
530 nanoseconds d = tp.time_since_epoch();
531 timespec ts = boost::detail::to_timespec(d);
532 return do_try_join_until(ts);
533 }
534#endif
535
536#endif
537 public:
538
539#if defined BOOST_THREAD_USES_DATETIME
540 template<typename TimeDuration>
541 inline bool timed_join(TimeDuration const& rel_time)
542 {
543 return timed_join(get_system_time()+rel_time);
544 }
545#endif
546 void detach();
547
548 static unsigned hardware_concurrency() BOOST_NOEXCEPT;
549
550#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
551 typedef detail::thread_data_base::native_handle_type native_handle_type;
552 native_handle_type native_handle();
553
554#if defined BOOST_THREAD_PROVIDES_THREAD_EQ
555 // Use thread::id when comparisions are needed
556 // backwards compatibility
557 bool operator==(const thread& other) const;
558 bool operator!=(const thread& other) const;
559#endif
560#if defined BOOST_THREAD_USES_DATETIME
561 static inline void yield() BOOST_NOEXCEPT
562 {
563 this_thread::yield();
564 }
565
566 static inline void sleep(const system_time& xt)
567 {
568 this_thread::sleep(xt);
569 }
570#endif
571
572#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
573 // extensions
574 void interrupt();
575 bool interruption_requested() const BOOST_NOEXCEPT;
576#endif
577 };
578
579 inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
580 {
581 return lhs.swap(rhs);
582 }
583
584#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
585 inline thread&& move(thread& t) BOOST_NOEXCEPT
586 {
587 return static_cast<thread&&>(t);
588 }
589#endif
590
591 BOOST_THREAD_DCL_MOVABLE(thread)
592
593 namespace this_thread
594 {
595#ifdef BOOST_THREAD_PLATFORM_PTHREAD
596 inline thread::id get_id() BOOST_NOEXCEPT;
597#else
598 thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
599#endif
600
601#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
602 void BOOST_THREAD_DECL interruption_point();
603 bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
604 bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
605#endif
606
607#if defined BOOST_THREAD_USES_DATETIME
608 inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
609 {
610 sleep(system_time(abs_time));
611 }
612#endif
613 }
614
615 class BOOST_SYMBOL_VISIBLE thread::id
616 {
617 private:
618 friend inline
619 std::size_t
620 hash_value(const thread::id &v)
621 {
622#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
623 return hash_value(v.thread_data);
624#else
625 return hash_value(v.thread_data.get());
626#endif
627 }
628
629#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
630#if defined(BOOST_THREAD_PLATFORM_WIN32)
631 typedef unsigned int data;
632#else
633 typedef thread::native_handle_type data;
634#endif
635#else
636 typedef detail::thread_data_ptr data;
637#endif
638 data thread_data;
639
640 id(data thread_data_):
641 thread_data(thread_data_)
642 {}
643 friend class thread;
644 friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT;
645 public:
646 id() BOOST_NOEXCEPT:
647#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
648 thread_data(0)
649#else
650 thread_data()
651#endif
652 {}
653
654 id(const id& other) BOOST_NOEXCEPT :
655 thread_data(other.thread_data)
656 {}
657
658 bool operator==(const id& y) const BOOST_NOEXCEPT
659 {
660 return thread_data==y.thread_data;
661 }
662
663 bool operator!=(const id& y) const BOOST_NOEXCEPT
664 {
665 return thread_data!=y.thread_data;
666 }
667
668 bool operator<(const id& y) const BOOST_NOEXCEPT
669 {
670 return thread_data<y.thread_data;
671 }
672
673 bool operator>(const id& y) const BOOST_NOEXCEPT
674 {
675 return y.thread_data<thread_data;
676 }
677
678 bool operator<=(const id& y) const BOOST_NOEXCEPT
679 {
680 return !(y.thread_data<thread_data);
681 }
682
683 bool operator>=(const id& y) const BOOST_NOEXCEPT
684 {
685 return !(thread_data<y.thread_data);
686 }
687
688#ifndef BOOST_NO_IOSTREAM
689#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
690 template<class charT, class traits>
691 friend BOOST_SYMBOL_VISIBLE
692 std::basic_ostream<charT, traits>&
693 operator<<(std::basic_ostream<charT, traits>& os, const id& x)
694 {
695 if(x.thread_data)
696 {
697 io::ios_flags_saver ifs( os );
698 return os<< std::hex << x.thread_data;
699 }
700 else
701 {
702 return os<<"{Not-any-thread}";
703 }
704 }
705#else
706 template<class charT, class traits>
707 BOOST_SYMBOL_VISIBLE
708 std::basic_ostream<charT, traits>&
709 print(std::basic_ostream<charT, traits>& os) const
710 {
711 if(thread_data)
712 {
713 io::ios_flags_saver ifs( os );
714 return os<< std::hex << thread_data;
715 }
716 else
717 {
718 return os<<"{Not-any-thread}";
719 }
720 }
721
722#endif
723#endif
724 };
725
726#ifdef BOOST_THREAD_PLATFORM_PTHREAD
727 thread::id thread::get_id() const BOOST_NOEXCEPT
728 {
729 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
730 return const_cast<thread*>(this)->native_handle();
731 #else
732 detail::thread_data_ptr const local_thread_info=(get_thread_info)();
733 return (local_thread_info? id(local_thread_info) : id());
734 #endif
735 }
736
737 namespace this_thread
738 {
739 inline thread::id get_id() BOOST_NOEXCEPT
740 {
741 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
742 return pthread_self();
743 #else
744 boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
745 return (thread_info?thread::id(thread_info->shared_from_this()):thread::id());
746 #endif
747 }
748 }
749#endif
750 void thread::join() {
751 if (this_thread::get_id() == get_id())
752 boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
753
754 BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
755 thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")
756 );
757 }
758
759#ifdef BOOST_THREAD_PLATFORM_PTHREAD
760 bool thread::do_try_join_until(struct timespec const &timeout)
761#else
762 bool thread::do_try_join_until(uintmax_t timeout)
763#endif
764 {
765 if (this_thread::get_id() == get_id())
766 boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
767 bool res;
768 if (do_try_join_until_noexcept(timeout, res))
769 {
770 return res;
771 }
772 else
773 {
774 BOOST_THREAD_THROW_ELSE_RETURN(
775 (thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")),
776 false
777 );
778 }
779 }
780
781#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
782 template<class charT, class traits>
783 BOOST_SYMBOL_VISIBLE
784 std::basic_ostream<charT, traits>&
785 operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
786 {
787 return x.print(os);
788 }
789#endif
790
791#if defined BOOST_THREAD_PROVIDES_THREAD_EQ
792 inline bool thread::operator==(const thread& other) const
793 {
794 return get_id()==other.get_id();
795 }
796
797 inline bool thread::operator!=(const thread& other) const
798 {
799 return get_id()!=other.get_id();
800 }
801#endif
802
803 namespace detail
804 {
805 struct thread_exit_function_base
806 {
807 virtual ~thread_exit_function_base()
808 {}
809 virtual void operator()()=0;
810 };
811
812 template<typename F>
813 struct thread_exit_function:
814 thread_exit_function_base
815 {
816 F f;
817
818 thread_exit_function(F f_):
819 f(f_)
820 {}
821
822 void operator()()
823 {
824 f();
825 }
826 };
827
828 void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
829 }
830
831 namespace this_thread
832 {
833 template<typename F>
834 void at_thread_exit(F f)
835 {
836 detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
837 detail::add_thread_exit_function(thread_exit_func);
838 }
839 }
840}
841
842#ifdef BOOST_MSVC
843#pragma warning(pop)
844#endif
845
846#include <boost/config/abi_suffix.hpp>
847
848#endif