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 friend inline 605 std::size_t hash_value(const thread::id & v)606 hash_value(const thread::id &v) 607 { 608 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID 609 return hash_value(v.thread_data); 610 #else 611 return hash_value(v.thread_data.get()); 612 #endif 613 } 614 615 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID 616 #if defined(BOOST_THREAD_PLATFORM_WIN32) 617 typedef unsigned int data; 618 #else 619 typedef thread::native_handle_type data; 620 #endif 621 #else 622 typedef detail::thread_data_ptr data; 623 #endif 624 data thread_data; 625 id(data thread_data_)626 id(data thread_data_): 627 thread_data(thread_data_) 628 {} 629 friend class thread; 630 friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT; 631 public: id()632 id() BOOST_NOEXCEPT: 633 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID 634 thread_data(0) 635 #else 636 thread_data() 637 #endif 638 {} 639 operator ==(const id & y) const640 bool operator==(const id& y) const BOOST_NOEXCEPT 641 { 642 return thread_data==y.thread_data; 643 } 644 operator !=(const id & y) const645 bool operator!=(const id& y) const BOOST_NOEXCEPT 646 { 647 return thread_data!=y.thread_data; 648 } 649 operator <(const id & y) const650 bool operator<(const id& y) const BOOST_NOEXCEPT 651 { 652 return thread_data<y.thread_data; 653 } 654 operator >(const id & y) const655 bool operator>(const id& y) const BOOST_NOEXCEPT 656 { 657 return y.thread_data<thread_data; 658 } 659 operator <=(const id & y) const660 bool operator<=(const id& y) const BOOST_NOEXCEPT 661 { 662 return !(y.thread_data<thread_data); 663 } 664 operator >=(const id & y) const665 bool operator>=(const id& y) const BOOST_NOEXCEPT 666 { 667 return !(thread_data<y.thread_data); 668 } 669 670 #ifndef BOOST_NO_IOSTREAM 671 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 672 template<class charT, class traits> 673 friend BOOST_SYMBOL_VISIBLE 674 std::basic_ostream<charT, traits>& operator <<(std::basic_ostream<charT,traits> & os,const id & x)675 operator<<(std::basic_ostream<charT, traits>& os, const id& x) 676 { 677 if(x.thread_data) 678 { 679 io::ios_flags_saver ifs( os ); 680 return os<< std::hex << x.thread_data; 681 } 682 else 683 { 684 return os<<"{Not-any-thread}"; 685 } 686 } 687 #else 688 template<class charT, class traits> 689 BOOST_SYMBOL_VISIBLE 690 std::basic_ostream<charT, traits>& print(std::basic_ostream<charT,traits> & os) const691 print(std::basic_ostream<charT, traits>& os) const 692 { 693 if(thread_data) 694 { 695 io::ios_flags_saver ifs( os ); 696 return os<< std::hex << thread_data; 697 } 698 else 699 { 700 return os<<"{Not-any-thread}"; 701 } 702 } 703 704 #endif 705 #endif 706 }; 707 708 #ifdef BOOST_THREAD_PLATFORM_PTHREAD get_id() const709 inline thread::id thread::get_id() const BOOST_NOEXCEPT 710 { 711 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID 712 return const_cast<thread*>(this)->native_handle(); 713 #else 714 detail::thread_data_ptr const local_thread_info=(get_thread_info)(); 715 return (local_thread_info? id(local_thread_info) : id()); 716 #endif 717 } 718 719 namespace this_thread 720 { get_id()721 inline thread::id get_id() BOOST_NOEXCEPT 722 { 723 #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID 724 return pthread_self(); 725 #else 726 boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); 727 return (thread_info?thread::id(thread_info->shared_from_this()):thread::id()); 728 #endif 729 } 730 } 731 #endif join()732 inline void thread::join() { 733 if (this_thread::get_id() == get_id()) 734 boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); 735 736 BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(), 737 thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable") 738 ); 739 } 740 do_try_join_until(detail::internal_platform_timepoint const & timeout)741 inline bool thread::do_try_join_until(detail::internal_platform_timepoint const &timeout) 742 { 743 if (this_thread::get_id() == get_id()) 744 boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); 745 bool res; 746 if (do_try_join_until_noexcept(timeout, res)) 747 { 748 return res; 749 } 750 else 751 { 752 BOOST_THREAD_THROW_ELSE_RETURN( 753 (thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")), 754 false 755 ); 756 } 757 } 758 759 #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) 760 template<class charT, class traits> 761 BOOST_SYMBOL_VISIBLE 762 std::basic_ostream<charT, traits>& operator <<(std::basic_ostream<charT,traits> & os,const thread::id & x)763 operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x) 764 { 765 return x.print(os); 766 } 767 #endif 768 769 #if defined BOOST_THREAD_PROVIDES_THREAD_EQ operator ==(const thread & other) const770 inline bool thread::operator==(const thread& other) const 771 { 772 return get_id()==other.get_id(); 773 } 774 operator !=(const thread & other) const775 inline bool thread::operator!=(const thread& other) const 776 { 777 return get_id()!=other.get_id(); 778 } 779 #endif 780 781 namespace detail 782 { 783 struct thread_exit_function_base 784 { ~thread_exit_function_baseboost::detail::thread_exit_function_base785 virtual ~thread_exit_function_base() 786 {} 787 virtual void operator()()=0; 788 }; 789 790 template<typename F> 791 struct thread_exit_function: 792 thread_exit_function_base 793 { 794 F f; 795 thread_exit_functionboost::detail::thread_exit_function796 thread_exit_function(F f_): 797 f(f_) 798 {} 799 operator ()boost::detail::thread_exit_function800 void operator()() 801 { 802 f(); 803 } 804 }; 805 806 void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); 807 //#ifndef BOOST_NO_EXCEPTIONS 808 struct shared_state_base; 809 #if defined(BOOST_THREAD_PLATFORM_WIN32) make_ready_at_thread_exit(shared_ptr<shared_state_base> as)810 inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) 811 { 812 detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); 813 if(current_thread_data) 814 { 815 current_thread_data->make_ready_at_thread_exit(as); 816 } 817 } 818 #else 819 void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as); 820 #endif 821 //#endif 822 } 823 824 namespace this_thread 825 { 826 template<typename F> at_thread_exit(F f)827 void at_thread_exit(F f) 828 { 829 detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f); 830 detail::add_thread_exit_function(thread_exit_func); 831 } 832 } 833 } 834 835 #ifdef BOOST_MSVC 836 #pragma warning(pop) 837 #endif 838 839 #include <boost/config/abi_suffix.hpp> 840 841 #endif 842