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)
thread_data(BOOST_THREAD_RV_REF (F)f_,BOOST_THREAD_RV_REF (ArgTypes)...args_)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>
run2(tuple_indices<Indices...>)72           void run2(tuple_indices<Indices...>)
73           {
74 
75               invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
76           }
run()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 
159     class BOOST_THREAD_DECL thread
160     {
161     public:
162       typedef thread_attributes attributes;
163 
164       BOOST_THREAD_MOVABLE_ONLY(thread)
165     private:
166 
167         struct dummy;
168 
169         void release_handle();
170 
171         detail::thread_data_ptr thread_info;
172 
173     private:
174         bool start_thread_noexcept();
175         bool start_thread_noexcept(const attributes& attr);
176     //public:
start_thread()177         void start_thread()
178         {
179           if (!start_thread_noexcept())
180           {
181             boost::throw_exception(thread_resource_error());
182           }
183         }
start_thread(const attributes & attr)184         void start_thread(const attributes& attr)
185         {
186           if (!start_thread_noexcept(attr))
187           {
188             boost::throw_exception(thread_resource_error());
189           }
190         }
191 
192         explicit thread(detail::thread_data_ptr data);
193 
194         detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const;
195 
196 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
197 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
198         template<typename F, class ...ArgTypes>
make_thread_info(BOOST_THREAD_RV_REF (F)f,BOOST_THREAD_RV_REF (ArgTypes)...args)199         static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
200         {
201             return detail::thread_data_ptr(detail::heap_new<
202                   detail::thread_data<typename boost::remove_reference<F>::type, ArgTypes...>
203                   >(
204                     boost::forward<F>(f), boost::forward<ArgTypes>(args)...
205                   )
206                 );
207         }
208 #else
209         template<typename F>
make_thread_info(BOOST_THREAD_RV_REF (F)f)210         static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
211         {
212             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(
213                 boost::forward<F>(f)));
214         }
215 #endif
make_thread_info(void (* f)())216         static inline detail::thread_data_ptr make_thread_info(void (*f)())
217         {
218             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(
219                 boost::forward<void(*)()>(f)));
220         }
221 #else
222         template<typename F>
make_thread_info(F f,typename disable_if_c<is_same<typename decay<F>::type,thread>::value,dummy * >::type=0)223         static inline detail::thread_data_ptr make_thread_info(F f
224             , typename disable_if_c<
225                 //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value ||
226                 is_same<typename decay<F>::type, thread>::value,
227                 dummy* >::type=0
228                 )
229         {
230             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
231         }
232         template<typename F>
make_thread_info(BOOST_THREAD_RV_REF (F)f)233         static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
234         {
235             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
236         }
237 
238 #endif
239     public:
240 #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
241 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
242         thread(const volatile thread&);
243 #endif
244 #endif
245         thread() BOOST_NOEXCEPT;
~thread()246         ~thread()
247         {
248 
249     #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
250           if (joinable()) {
251             std::terminate();
252           }
253     #else
254             detach();
255     #endif
256         }
257 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
258         template <
259           class F
260         >
thread(BOOST_THREAD_RV_REF (F)f)261         explicit thread(BOOST_THREAD_RV_REF(F) f
262         //, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
263         ):
264           thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
265         {
266             start_thread();
267         }
268         template <
269           class F
270         >
thread(attributes const & attrs,BOOST_THREAD_RV_REF (F)f)271         thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
272           thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
273         {
274             start_thread(attrs);
275         }
276 
277 #else
278 #ifdef BOOST_NO_SFINAE
279         template <class F>
thread(F f)280         explicit thread(F f):
281             thread_info(make_thread_info(f))
282         {
283             start_thread();
284         }
285         template <class F>
thread(attributes const & attrs,F f)286         thread(attributes const& attrs, F f):
287             thread_info(make_thread_info(f))
288         {
289             start_thread(attrs);
290         }
291 #else
292         template <class F>
thread(F f,typename disable_if_c<boost::thread_detail::is_rv<F>::value,dummy * >::type=0)293         explicit thread(F f
294         , typename disable_if_c<
295         boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
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>
thread(attributes const & attrs,F f,typename disable_if<boost::thread_detail::is_rv<F>,dummy * >::type=0)305         thread(attributes const& attrs, F f
306             , typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
307             //, typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0
308         ):
309             thread_info(make_thread_info(f))
310         {
311             start_thread(attrs);
312         }
313 #endif
314         template <class F>
thread(BOOST_THREAD_RV_REF (F)f,typename disable_if<is_same<typename decay<F>::type,thread>,dummy * >::type=0)315         explicit thread(BOOST_THREAD_RV_REF(F) f
316         , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
317         ):
318 #ifdef BOOST_THREAD_USES_MOVE
319         thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
320 #else
321         thread_info(make_thread_info(f)) // todo : Add forward
322 #endif
323         {
324             start_thread();
325         }
326 
327         template <class F>
thread(attributes const & attrs,BOOST_THREAD_RV_REF (F)f)328         thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
329 #ifdef BOOST_THREAD_USES_MOVE
330             thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward
331 #else
332             thread_info(make_thread_info(f)) // todo : Add forward
333 #endif
334         {
335             start_thread(attrs);
336         }
337 #endif
thread(BOOST_THREAD_RV_REF (thread)x)338         thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT
339         {
340             thread_info=BOOST_THREAD_RV(x).thread_info;
341             BOOST_THREAD_RV(x).thread_info.reset();
342         }
343 #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
344 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
345         thread& operator=(thread x)
346         {
347             swap(x);
348             return *this;
349         }
350 #endif
351 #endif
352 
operator =(BOOST_THREAD_RV_REF (thread)other)353         thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT
354         {
355 
356 #if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
357             if (joinable()) std::terminate();
358 #endif
359             thread_info=BOOST_THREAD_RV(other).thread_info;
360             BOOST_THREAD_RV(other).thread_info.reset();
361             return *this;
362         }
363 
364 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
365         template <class F, class Arg, class ...Args>
thread(F && f,Arg && arg,Args &&...args)366         thread(F&& f, Arg&& arg, Args&&... args) :
367           thread_info(make_thread_info(
368               thread_detail::decay_copy(boost::forward<F>(f)),
369               thread_detail::decay_copy(boost::forward<Arg>(arg)),
370               thread_detail::decay_copy(boost::forward<Args>(args))...)
371           )
372 
373         {
374           start_thread();
375         }
376         template <class F, class Arg, class ...Args>
thread(attributes const & attrs,F && f,Arg && arg,Args &&...args)377         thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) :
378           thread_info(make_thread_info(
379               thread_detail::decay_copy(boost::forward<F>(f)),
380               thread_detail::decay_copy(boost::forward<Arg>(arg)),
381               thread_detail::decay_copy(boost::forward<Args>(args))...)
382           )
383 
384         {
385           start_thread(attrs);
386         }
387 #else
388         template <class F,class A1>
thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F &,thread_attributes>,dummy * >::type=0)389         thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0):
390             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
391         {
392             start_thread();
393         }
394         template <class F,class A1,class A2>
thread(F f,A1 a1,A2 a2)395         thread(F f,A1 a1,A2 a2):
396             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
397         {
398             start_thread();
399         }
400 
401         template <class F,class A1,class A2,class A3>
thread(F f,A1 a1,A2 a2,A3 a3)402         thread(F f,A1 a1,A2 a2,A3 a3):
403             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
404         {
405             start_thread();
406         }
407 
408         template <class F,class A1,class A2,class A3,class A4>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4)409         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
410             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
411         {
412             start_thread();
413         }
414 
415         template <class F,class A1,class A2,class A3,class A4,class A5>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5)416         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
417             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
418         {
419             start_thread();
420         }
421 
422         template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6)423         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
424             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
425         {
426             start_thread();
427         }
428 
429         template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7)430         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
431             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
432         {
433             start_thread();
434         }
435 
436         template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)437         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
438             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
439         {
440             start_thread();
441         }
442 
443         template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)444         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
445             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
446         {
447             start_thread();
448         }
449 #endif
swap(thread & x)450         void swap(thread& x) BOOST_NOEXCEPT
451         {
452             thread_info.swap(x.thread_info);
453         }
454 
455         class id;
456 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
457         inline id get_id()  const BOOST_NOEXCEPT;
458 #else
459         id get_id() const BOOST_NOEXCEPT;
460 #endif
461 
462 
463         bool joinable() const BOOST_NOEXCEPT;
464     private:
465         bool join_noexcept();
466     public:
467         inline void join();
468 
469 #ifdef BOOST_THREAD_USES_CHRONO
470 #if defined(BOOST_THREAD_PLATFORM_WIN32)
471         template <class Rep, class Period>
try_join_for(const chrono::duration<Rep,Period> & rel_time)472         bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
473         {
474           chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
475           return do_try_join_until(rel_time2.count());
476         }
477 #else
478         template <class Rep, class Period>
try_join_for(const chrono::duration<Rep,Period> & rel_time)479         bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
480         {
481           return try_join_until(chrono::steady_clock::now() + rel_time);
482         }
483 #endif
484         template <class Clock, class Duration>
try_join_until(const chrono::time_point<Clock,Duration> & t)485         bool try_join_until(const chrono::time_point<Clock, Duration>& t)
486         {
487           using namespace chrono;
488           system_clock::time_point     s_now = system_clock::now();
489           bool joined= false;
490           do {
491             typename Clock::duration   d = ceil<nanoseconds>(t-Clock::now());
492             if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
493             joined = try_join_until(s_now + d);
494           } while (! joined);
495           return true;
496         }
497         template <class Duration>
try_join_until(const chrono::time_point<chrono::system_clock,Duration> & t)498         bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
499         {
500           using namespace chrono;
501           typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
502           return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
503         }
504 #endif
505 #if defined(BOOST_THREAD_PLATFORM_WIN32)
506     private:
507         bool do_try_join_until_noexcept(uintmax_t milli, bool& res);
508         inline bool do_try_join_until(uintmax_t milli);
509     public:
510         bool timed_join(const system_time& abs_time);
511         //{
512         //  return do_try_join_until(get_milliseconds_until(wait_until));
513         //}
514 
515 #ifdef BOOST_THREAD_USES_CHRONO
try_join_until(const chrono::time_point<chrono::system_clock,chrono::nanoseconds> & tp)516         bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
517         {
518           chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
519           return do_try_join_until(rel_time.count());
520         }
521 #endif
522 
523 
524 #else
525     private:
526         bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res);
527         inline bool do_try_join_until(struct timespec const &timeout);
528     public:
529 #if defined BOOST_THREAD_USES_DATETIME
timed_join(const system_time & abs_time)530         bool timed_join(const system_time& abs_time)
531         {
532           struct timespec const ts=detail::to_timespec(abs_time);
533           return do_try_join_until(ts);
534         }
535 #endif
536 #ifdef BOOST_THREAD_USES_CHRONO
try_join_until(const chrono::time_point<chrono::system_clock,chrono::nanoseconds> & tp)537         bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
538         {
539           using namespace chrono;
540           nanoseconds d = tp.time_since_epoch();
541           timespec ts = boost::detail::to_timespec(d);
542           return do_try_join_until(ts);
543         }
544 #endif
545 
546 #endif
547       public:
548 
549 #if defined BOOST_THREAD_USES_DATETIME
550         template<typename TimeDuration>
timed_join(TimeDuration const & rel_time)551         inline bool timed_join(TimeDuration const& rel_time)
552         {
553             return timed_join(get_system_time()+rel_time);
554         }
555 #endif
556         void detach();
557 
558         static unsigned hardware_concurrency() BOOST_NOEXCEPT;
559         static unsigned physical_concurrency() BOOST_NOEXCEPT;
560 
561 #define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
562         typedef detail::thread_data_base::native_handle_type native_handle_type;
563         native_handle_type native_handle();
564 
565 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ
566         // Use thread::id when comparisions are needed
567         // backwards compatibility
568         bool operator==(const thread& other) const;
569         bool operator!=(const thread& other) const;
570 #endif
571 #if defined BOOST_THREAD_USES_DATETIME
yield()572         static inline void yield() BOOST_NOEXCEPT
573         {
574             this_thread::yield();
575         }
576 
sleep(const system_time & xt)577         static inline void sleep(const system_time& xt)
578         {
579             this_thread::sleep(xt);
580         }
581 #endif
582 
583 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
584         // extensions
585         void interrupt();
586         bool interruption_requested() const BOOST_NOEXCEPT;
587 #endif
588     };
589 
swap(thread & lhs,thread & rhs)590     inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
591     {
592         return lhs.swap(rhs);
593     }
594 
595 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
move(thread & t)596     inline thread&& move(thread& t) BOOST_NOEXCEPT
597     {
598         return static_cast<thread&&>(t);
599     }
600 #endif
601 
602     BOOST_THREAD_DCL_MOVABLE(thread)
603 
604     namespace this_thread
605     {
606 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
607         inline thread::id get_id() BOOST_NOEXCEPT;
608 #else
609         thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
610 #endif
611 
612 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
613         void BOOST_THREAD_DECL interruption_point();
614         bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
615         bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
616 #endif
617 
618 #if defined BOOST_THREAD_USES_DATETIME
sleep(xtime const & abs_time)619         inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
620         {
621             sleep(system_time(abs_time));
622         }
623 #endif
624     }
625 
626     class BOOST_SYMBOL_VISIBLE thread::id
627     {
628     private:
629         friend inline
630         std::size_t
hash_value(const thread::id & v)631         hash_value(const thread::id &v)
632         {
633 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
634           return hash_value(v.thread_data);
635 #else
636           return hash_value(v.thread_data.get());
637 #endif
638         }
639 
640 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
641 #if defined(BOOST_THREAD_PLATFORM_WIN32)
642         typedef unsigned int data;
643 #else
644         typedef thread::native_handle_type data;
645 #endif
646 #else
647         typedef detail::thread_data_ptr data;
648 #endif
649         data thread_data;
650 
id(data thread_data_)651         id(data thread_data_):
652             thread_data(thread_data_)
653         {}
654         friend class thread;
655         friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT;
656     public:
id()657         id() BOOST_NOEXCEPT:
658 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
659         thread_data(0)
660 #else
661         thread_data()
662 #endif
663         {}
664 
id(const id & other)665         id(const id& other) BOOST_NOEXCEPT :
666             thread_data(other.thread_data)
667         {}
668 
operator ==(const id & y) const669         bool operator==(const id& y) const BOOST_NOEXCEPT
670         {
671             return thread_data==y.thread_data;
672         }
673 
operator !=(const id & y) const674         bool operator!=(const id& y) const BOOST_NOEXCEPT
675         {
676             return thread_data!=y.thread_data;
677         }
678 
operator <(const id & y) const679         bool operator<(const id& y) const BOOST_NOEXCEPT
680         {
681             return thread_data<y.thread_data;
682         }
683 
operator >(const id & y) const684         bool operator>(const id& y) const BOOST_NOEXCEPT
685         {
686             return y.thread_data<thread_data;
687         }
688 
operator <=(const id & y) const689         bool operator<=(const id& y) const BOOST_NOEXCEPT
690         {
691             return !(y.thread_data<thread_data);
692         }
693 
operator >=(const id & y) const694         bool operator>=(const id& y) const BOOST_NOEXCEPT
695         {
696             return !(thread_data<y.thread_data);
697         }
698 
699 #ifndef BOOST_NO_IOSTREAM
700 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
701         template<class charT, class traits>
702         friend BOOST_SYMBOL_VISIBLE
703   std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT,traits> & os,const id & x)704         operator<<(std::basic_ostream<charT, traits>& os, const id& x)
705         {
706             if(x.thread_data)
707             {
708                 io::ios_flags_saver  ifs( os );
709                 return os<< std::hex << x.thread_data;
710             }
711             else
712             {
713                 return os<<"{Not-any-thread}";
714             }
715         }
716 #else
717         template<class charT, class traits>
718         BOOST_SYMBOL_VISIBLE
719   std::basic_ostream<charT, traits>&
print(std::basic_ostream<charT,traits> & os) const720         print(std::basic_ostream<charT, traits>& os) const
721         {
722             if(thread_data)
723             {
724               io::ios_flags_saver  ifs( os );
725               return os<< std::hex << thread_data;
726             }
727             else
728             {
729                 return os<<"{Not-any-thread}";
730             }
731         }
732 
733 #endif
734 #endif
735     };
736 
737 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
get_id() const738     thread::id thread::get_id() const BOOST_NOEXCEPT
739     {
740     #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
741         return const_cast<thread*>(this)->native_handle();
742     #else
743         detail::thread_data_ptr const local_thread_info=(get_thread_info)();
744         return (local_thread_info? id(local_thread_info) : id());
745     #endif
746     }
747 
748     namespace this_thread
749     {
get_id()750         inline thread::id get_id() BOOST_NOEXCEPT
751         {
752         #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
753              return pthread_self();
754         #else
755             boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
756             return (thread_info?thread::id(thread_info->shared_from_this()):thread::id());
757         #endif
758         }
759     }
760 #endif
join()761     void thread::join() {
762         if (this_thread::get_id() == get_id())
763           boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
764 
765         BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
766             thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")
767         );
768     }
769 
770 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
do_try_join_until(struct timespec const & timeout)771     bool thread::do_try_join_until(struct timespec const &timeout)
772 #else
773     bool thread::do_try_join_until(uintmax_t timeout)
774 #endif
775     {
776         if (this_thread::get_id() == get_id())
777           boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
778         bool res;
779         if (do_try_join_until_noexcept(timeout, res))
780         {
781           return res;
782         }
783         else
784         {
785           BOOST_THREAD_THROW_ELSE_RETURN(
786             (thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")),
787             false
788           );
789         }
790     }
791 
792 #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
793     template<class charT, class traits>
794     BOOST_SYMBOL_VISIBLE
795     std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT,traits> & os,const thread::id & x)796     operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
797     {
798         return x.print(os);
799     }
800 #endif
801 
802 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ
operator ==(const thread & other) const803     inline bool thread::operator==(const thread& other) const
804     {
805         return get_id()==other.get_id();
806     }
807 
operator !=(const thread & other) const808     inline bool thread::operator!=(const thread& other) const
809     {
810         return get_id()!=other.get_id();
811     }
812 #endif
813 
814     namespace detail
815     {
816         struct thread_exit_function_base
817         {
~thread_exit_function_baseboost::detail::thread_exit_function_base818             virtual ~thread_exit_function_base()
819             {}
820             virtual void operator()()=0;
821         };
822 
823         template<typename F>
824         struct thread_exit_function:
825             thread_exit_function_base
826         {
827             F f;
828 
thread_exit_functionboost::detail::thread_exit_function829             thread_exit_function(F f_):
830                 f(f_)
831             {}
832 
operator ()boost::detail::thread_exit_function833             void operator()()
834             {
835                 f();
836             }
837         };
838 
839         void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
840         struct shared_state_base;
841 #if defined(BOOST_THREAD_PLATFORM_WIN32)
make_ready_at_thread_exit(shared_ptr<shared_state_base> as)842         inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
843         {
844           detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
845           if(current_thread_data)
846           {
847             current_thread_data->make_ready_at_thread_exit(as);
848           }
849         }
850 #else
851         void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
852 #endif
853     }
854 
855     namespace this_thread
856     {
857         template<typename F>
at_thread_exit(F f)858         void at_thread_exit(F f)
859         {
860             detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
861             detail::add_thread_exit_function(thread_exit_func);
862         }
863     }
864 }
865 
866 #ifdef BOOST_MSVC
867 #pragma warning(pop)
868 #endif
869 
870 #include <boost/config/abi_suffix.hpp>
871 
872 #endif
873