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