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