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 #include <boost/thread/detail/platform_time.hpp>
40 #ifdef BOOST_THREAD_USES_CHRONO
41 #include <boost/chrono/system_clocks.hpp>
42 #include <boost/chrono/ceil.hpp>
43 #endif
44 
45 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
46 #include <tuple>
47 #endif
48 #include <boost/config/abi_prefix.hpp>
49 
50 #ifdef BOOST_MSVC
51 #pragma warning(push)
52 #pragma warning(disable:4251)
53 #endif
54 
55 namespace boost
56 {
57 
58     namespace detail
59     {
60 
61 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
62 
63       template<typename F, class ...ArgTypes>
64       class thread_data:
65           public detail::thread_data_base
66       {
67       public:
68           BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(BOOST_THREAD_RV_REF (F)f_,BOOST_THREAD_RV_REF (ArgTypes)...args_)69             thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_):
70               fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...)
71             {}
72           template <std::size_t ...Indices>
run2(tuple_indices<Indices...>)73           void run2(tuple_indices<Indices...>)
74           {
75 
76               detail::invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...);
77           }
run()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);
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 as 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 #else
359             detach();
360 #endif
361             thread_info=BOOST_THREAD_RV(other).thread_info;
362             BOOST_THREAD_RV(other).thread_info.reset();
363             return *this;
364         }
365 
366 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
367         template <class F, class Arg, class ...Args>
thread(F && f,Arg && arg,Args &&...args)368         thread(F&& f, Arg&& arg, Args&&... args) :
369           thread_info(make_thread_info(
370               thread_detail::decay_copy(boost::forward<F>(f)),
371               thread_detail::decay_copy(boost::forward<Arg>(arg)),
372               thread_detail::decay_copy(boost::forward<Args>(args))...)
373           )
374 
375         {
376           start_thread();
377         }
378         template <class F, class Arg, class ...Args>
thread(attributes const & attrs,F && f,Arg && arg,Args &&...args)379         thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) :
380           thread_info(make_thread_info(
381               thread_detail::decay_copy(boost::forward<F>(f)),
382               thread_detail::decay_copy(boost::forward<Arg>(arg)),
383               thread_detail::decay_copy(boost::forward<Args>(args))...)
384           )
385 
386         {
387           start_thread(attrs);
388         }
389 #else
390         template <class F,class A1>
thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F &,thread_attributes>,dummy * >::type=0)391         thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0):
392             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
393         {
394             start_thread();
395         }
396         template <class F,class A1,class A2>
thread(F f,A1 a1,A2 a2)397         thread(F f,A1 a1,A2 a2):
398             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
399         {
400             start_thread();
401         }
402 
403         template <class F,class A1,class A2,class A3>
thread(F f,A1 a1,A2 a2,A3 a3)404         thread(F f,A1 a1,A2 a2,A3 a3):
405             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
406         {
407             start_thread();
408         }
409 
410         template <class F,class A1,class A2,class A3,class A4>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4)411         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
412             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
413         {
414             start_thread();
415         }
416 
417         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)418         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
419             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
420         {
421             start_thread();
422         }
423 
424         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)425         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
426             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
427         {
428             start_thread();
429         }
430 
431         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)432         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
433             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
434         {
435             start_thread();
436         }
437 
438         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)439         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
440             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
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,class A9>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)446         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
447             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
448         {
449             start_thread();
450         }
451 #endif
swap(thread & x)452         void swap(thread& x) BOOST_NOEXCEPT
453         {
454             thread_info.swap(x.thread_info);
455         }
456 
457         class id;
458         id get_id() const BOOST_NOEXCEPT;
459 
460         bool joinable() const BOOST_NOEXCEPT;
461     private:
462         bool join_noexcept();
463         bool do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res);
464         bool do_try_join_until(detail::internal_platform_timepoint const &timeout);
465     public:
466         void join();
467 
468 #ifdef BOOST_THREAD_USES_CHRONO
469         template <class Duration>
try_join_until(const chrono::time_point<detail::internal_chrono_clock,Duration> & t)470         bool try_join_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
471         {
472           return do_try_join_until(boost::detail::internal_platform_timepoint(t));
473         }
474 
475         template <class Clock, class Duration>
try_join_until(const chrono::time_point<Clock,Duration> & t)476         bool try_join_until(const chrono::time_point<Clock, Duration>& t)
477         {
478           typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
479           common_duration d(t - Clock::now());
480           d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
481           while ( ! try_join_until(detail::internal_chrono_clock::now() + d) )
482           {
483             d = t - Clock::now();
484             if ( d <= common_duration::zero() ) return false; // timeout occurred
485             d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
486           }
487           return true;
488         }
489 
490         template <class Rep, class Period>
try_join_for(const chrono::duration<Rep,Period> & rel_time)491         bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
492         {
493           return try_join_until(chrono::steady_clock::now() + rel_time);
494         }
495 #endif
496 #if defined BOOST_THREAD_USES_DATETIME
timed_join(const system_time & abs_time)497         bool timed_join(const system_time& abs_time)
498         {
499           const detail::real_platform_timepoint ts(abs_time);
500 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
501           detail::platform_duration d(ts - detail::real_platform_clock::now());
502           d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
503           while ( ! do_try_join_until(detail::internal_platform_clock::now() + d) )
504           {
505             d = ts - detail::real_platform_clock::now();
506             if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
507             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
508           }
509           return true;
510 #else
511           return do_try_join_until(ts);
512 #endif
513         }
514 
515         template<typename TimeDuration>
timed_join(TimeDuration const & rel_time)516         bool timed_join(TimeDuration const& rel_time)
517         {
518           detail::platform_duration d(rel_time);
519 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
520           const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
521           d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
522           while ( ! do_try_join_until(detail::internal_platform_clock::now() + d) )
523           {
524             d = ts - detail::mono_platform_clock::now();
525             if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
526             d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
527           }
528           return true;
529 #else
530           return do_try_join_until(detail::internal_platform_clock::now() + d);
531 #endif
532         }
533 #endif
534         void detach();
535 
536         static unsigned hardware_concurrency() BOOST_NOEXCEPT;
537         static unsigned physical_concurrency() BOOST_NOEXCEPT;
538 
539 #define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
540         typedef detail::thread_data_base::native_handle_type native_handle_type;
541         native_handle_type native_handle();
542 
543 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ
544         // Use thread::id when comparisions are needed
545         // backwards compatibility
546         bool operator==(const thread& other) const;
547         bool operator!=(const thread& other) const;
548 #endif
549 #if defined BOOST_THREAD_USES_DATETIME
yield()550         static inline void yield() BOOST_NOEXCEPT
551         {
552             this_thread::yield();
553         }
554 
sleep(const system_time & xt)555         static inline void sleep(const system_time& xt)
556         {
557             this_thread::sleep(xt);
558         }
559 #endif
560 
561 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
562         // extensions
563         void interrupt();
564         bool interruption_requested() const BOOST_NOEXCEPT;
565 #endif
566     };
567 
swap(thread & lhs,thread & rhs)568     inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
569     {
570         return lhs.swap(rhs);
571     }
572 
573 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
move(thread & t)574     inline thread&& move(thread& t) BOOST_NOEXCEPT
575     {
576         return static_cast<thread&&>(t);
577     }
578 #endif
579 
580     BOOST_THREAD_DCL_MOVABLE(thread)
581 
582     namespace this_thread
583     {
584 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
585         thread::id get_id() BOOST_NOEXCEPT;
586 #else
587         thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
588 #endif
589 
590 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
591         void BOOST_THREAD_DECL interruption_point();
592         bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
593         bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
594 #endif
595 
596 #if defined BOOST_THREAD_USES_DATETIME
sleep(::boost::xtime const & abs_time)597         inline BOOST_SYMBOL_VISIBLE void sleep(::boost::xtime const& abs_time)
598         {
599             sleep(system_time(abs_time));
600         }
601 #endif
602     }
603 
604     class BOOST_SYMBOL_VISIBLE thread::id
605     {
606     private:
607         friend inline
608         std::size_t
hash_value(const thread::id & v)609         hash_value(const thread::id &v)
610         {
611 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
612           return hash_value(v.thread_data);
613 #else
614           return hash_value(v.thread_data.get());
615 #endif
616         }
617 
618 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
619 #if defined(BOOST_THREAD_PLATFORM_WIN32)
620         typedef unsigned int data;
621 #else
622         typedef thread::native_handle_type data;
623 #endif
624 #else
625         typedef detail::thread_data_ptr data;
626 #endif
627         data thread_data;
628 
id(data thread_data_)629         id(data thread_data_):
630             thread_data(thread_data_)
631         {}
632         friend class thread;
633         friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT;
634     public:
id()635         id() BOOST_NOEXCEPT:
636 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
637         thread_data(0)
638 #else
639         thread_data()
640 #endif
641         {}
642 
id(const id & other)643         id(const id& other) BOOST_NOEXCEPT :
644             thread_data(other.thread_data)
645         {}
646 
operator ==(const id & y) const647         bool operator==(const id& y) const BOOST_NOEXCEPT
648         {
649             return thread_data==y.thread_data;
650         }
651 
operator !=(const id & y) const652         bool operator!=(const id& y) const BOOST_NOEXCEPT
653         {
654             return thread_data!=y.thread_data;
655         }
656 
operator <(const id & y) const657         bool operator<(const id& y) const BOOST_NOEXCEPT
658         {
659             return thread_data<y.thread_data;
660         }
661 
operator >(const id & y) const662         bool operator>(const id& y) const BOOST_NOEXCEPT
663         {
664             return y.thread_data<thread_data;
665         }
666 
operator <=(const id & y) const667         bool operator<=(const id& y) const BOOST_NOEXCEPT
668         {
669             return !(y.thread_data<thread_data);
670         }
671 
operator >=(const id & y) const672         bool operator>=(const id& y) const BOOST_NOEXCEPT
673         {
674             return !(thread_data<y.thread_data);
675         }
676 
677 #ifndef BOOST_NO_IOSTREAM
678 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
679         template<class charT, class traits>
680         friend BOOST_SYMBOL_VISIBLE
681   std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT,traits> & os,const id & x)682         operator<<(std::basic_ostream<charT, traits>& os, const id& x)
683         {
684             if(x.thread_data)
685             {
686                 io::ios_flags_saver  ifs( os );
687                 return os<< std::hex << x.thread_data;
688             }
689             else
690             {
691                 return os<<"{Not-any-thread}";
692             }
693         }
694 #else
695         template<class charT, class traits>
696         BOOST_SYMBOL_VISIBLE
697   std::basic_ostream<charT, traits>&
print(std::basic_ostream<charT,traits> & os) const698         print(std::basic_ostream<charT, traits>& os) const
699         {
700             if(thread_data)
701             {
702               io::ios_flags_saver  ifs( os );
703               return os<< std::hex << thread_data;
704             }
705             else
706             {
707                 return os<<"{Not-any-thread}";
708             }
709         }
710 
711 #endif
712 #endif
713     };
714 
715 #ifdef BOOST_THREAD_PLATFORM_PTHREAD
get_id() const716     inline thread::id thread::get_id() const BOOST_NOEXCEPT
717     {
718     #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
719         return const_cast<thread*>(this)->native_handle();
720     #else
721         detail::thread_data_ptr const local_thread_info=(get_thread_info)();
722         return (local_thread_info? id(local_thread_info) : id());
723     #endif
724     }
725 
726     namespace this_thread
727     {
get_id()728         inline thread::id get_id() BOOST_NOEXCEPT
729         {
730         #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
731              return pthread_self();
732         #else
733             boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
734             return (thread_info?thread::id(thread_info->shared_from_this()):thread::id());
735         #endif
736         }
737     }
738 #endif
join()739     inline void thread::join() {
740         if (this_thread::get_id() == get_id())
741           boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
742 
743         BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(),
744             thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")
745         );
746     }
747 
do_try_join_until(detail::internal_platform_timepoint const & timeout)748     inline bool thread::do_try_join_until(detail::internal_platform_timepoint const &timeout)
749     {
750         if (this_thread::get_id() == get_id())
751           boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
752         bool res;
753         if (do_try_join_until_noexcept(timeout, res))
754         {
755           return res;
756         }
757         else
758         {
759           BOOST_THREAD_THROW_ELSE_RETURN(
760             (thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")),
761             false
762           );
763         }
764     }
765 
766 #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
767     template<class charT, class traits>
768     BOOST_SYMBOL_VISIBLE
769     std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT,traits> & os,const thread::id & x)770     operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
771     {
772         return x.print(os);
773     }
774 #endif
775 
776 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ
operator ==(const thread & other) const777     inline bool thread::operator==(const thread& other) const
778     {
779         return get_id()==other.get_id();
780     }
781 
operator !=(const thread & other) const782     inline bool thread::operator!=(const thread& other) const
783     {
784         return get_id()!=other.get_id();
785     }
786 #endif
787 
788     namespace detail
789     {
790         struct thread_exit_function_base
791         {
~thread_exit_function_baseboost::detail::thread_exit_function_base792             virtual ~thread_exit_function_base()
793             {}
794             virtual void operator()()=0;
795         };
796 
797         template<typename F>
798         struct thread_exit_function:
799             thread_exit_function_base
800         {
801             F f;
802 
thread_exit_functionboost::detail::thread_exit_function803             thread_exit_function(F f_):
804                 f(f_)
805             {}
806 
operator ()boost::detail::thread_exit_function807             void operator()()
808             {
809                 f();
810             }
811         };
812 
813         void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
814 //#ifndef BOOST_NO_EXCEPTIONS
815         struct shared_state_base;
816 #if defined(BOOST_THREAD_PLATFORM_WIN32)
make_ready_at_thread_exit(shared_ptr<shared_state_base> as)817         inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
818         {
819           detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
820           if(current_thread_data)
821           {
822             current_thread_data->make_ready_at_thread_exit(as);
823           }
824         }
825 #else
826         void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
827 #endif
828 //#endif
829     }
830 
831     namespace this_thread
832     {
833         template<typename F>
at_thread_exit(F 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
849