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