Chris@16: #ifndef BOOST_THREAD_THREAD_COMMON_HPP Chris@16: #define BOOST_THREAD_THREAD_COMMON_HPP Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // (C) Copyright 2007-2010 Anthony Williams Chris@101: // (C) Copyright 2011-2012 Vicente J. Botet Escriba Chris@16: Chris@16: #include Chris@101: #include Chris@16: Chris@16: #include Chris@16: #ifndef BOOST_NO_IOSTREAM Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: #include Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4251) Chris@16: #endif Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: Chris@16: template Chris@16: class thread_data: Chris@16: public detail::thread_data_base Chris@16: { Chris@16: public: Chris@16: BOOST_THREAD_NO_COPYABLE(thread_data) Chris@16: thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_): Chris@16: fp(boost::forward(f_), boost::forward(args_)...) Chris@16: {} Chris@16: template Chris@16: void run2(tuple_indices) Chris@16: { Chris@16: Chris@16: invoke(std::move(std::get<0>(fp)), std::move(std::get(fp))...); Chris@16: } Chris@16: void run() Chris@16: { Chris@16: typedef typename make_tuple_indices >::value, 1>::type index_type; Chris@16: Chris@16: run2(index_type()); Chris@16: } Chris@16: Chris@16: private: Chris@16: std::tuple::type, typename decay::type...> fp; Chris@16: }; Chris@16: #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: Chris@16: template Chris@16: class thread_data: Chris@16: public detail::thread_data_base Chris@16: { Chris@16: public: Chris@16: BOOST_THREAD_NO_COPYABLE(thread_data) Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: thread_data(BOOST_THREAD_RV_REF(F) f_): Chris@16: f(boost::forward(f_)) Chris@16: {} Chris@16: // This overloading must be removed if we want the packaged_task's tests to pass. Chris@16: // thread_data(F& f_): Chris@16: // f(f_) Chris@16: // {} Chris@16: #else Chris@16: Chris@16: thread_data(BOOST_THREAD_RV_REF(F) f_): Chris@16: f(f_) Chris@16: {} Chris@16: thread_data(F f_): Chris@16: f(f_) Chris@16: {} Chris@16: #endif Chris@16: //thread_data() {} Chris@16: Chris@16: void run() Chris@16: { Chris@16: f(); Chris@16: } Chris@16: Chris@16: private: Chris@16: F f; Chris@16: }; Chris@16: Chris@16: template Chris@16: class thread_data >: Chris@16: public detail::thread_data_base Chris@16: { Chris@16: private: Chris@16: F& f; Chris@16: public: Chris@16: BOOST_THREAD_NO_COPYABLE(thread_data) Chris@16: thread_data(boost::reference_wrapper f_): Chris@16: f(f_) Chris@16: {} Chris@16: void run() Chris@16: { Chris@16: f(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: class thread_data >: Chris@16: public detail::thread_data_base Chris@16: { Chris@16: private: Chris@16: F& f; Chris@16: public: Chris@16: BOOST_THREAD_NO_COPYABLE(thread_data) Chris@16: thread_data(const boost::reference_wrapper f_): Chris@16: f(f_) Chris@16: {} Chris@16: void run() Chris@16: { Chris@16: f(); Chris@16: } Chris@16: }; Chris@16: #endif Chris@16: } Chris@16: Chris@16: class BOOST_THREAD_DECL thread Chris@16: { Chris@16: public: Chris@16: typedef thread_attributes attributes; Chris@16: Chris@16: BOOST_THREAD_MOVABLE_ONLY(thread) Chris@16: private: Chris@16: Chris@16: struct dummy; Chris@16: Chris@16: void release_handle(); Chris@16: Chris@16: detail::thread_data_ptr thread_info; Chris@16: Chris@16: private: Chris@16: bool start_thread_noexcept(); Chris@16: bool start_thread_noexcept(const attributes& attr); Chris@101: //public: Chris@16: void start_thread() Chris@16: { Chris@16: if (!start_thread_noexcept()) Chris@16: { Chris@16: boost::throw_exception(thread_resource_error()); Chris@16: } Chris@16: } Chris@16: void start_thread(const attributes& attr) Chris@16: { Chris@16: if (!start_thread_noexcept(attr)) Chris@16: { Chris@16: boost::throw_exception(thread_resource_error()); Chris@16: } Chris@16: } Chris@16: Chris@16: explicit thread(detail::thread_data_ptr data); Chris@16: Chris@16: detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args) Chris@16: { Chris@16: return detail::thread_data_ptr(detail::heap_new< Chris@16: detail::thread_data::type, ArgTypes...> Chris@16: >( Chris@16: boost::forward(f), boost::forward(args)... Chris@16: ) Chris@16: ); Chris@16: } Chris@16: #else Chris@16: template Chris@16: static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) Chris@16: { Chris@16: return detail::thread_data_ptr(detail::heap_new::type> >( Chris@16: boost::forward(f))); Chris@16: } Chris@16: #endif Chris@16: static inline detail::thread_data_ptr make_thread_info(void (*f)()) Chris@16: { Chris@16: return detail::thread_data_ptr(detail::heap_new >( Chris@16: boost::forward(f))); Chris@16: } Chris@16: #else Chris@16: template Chris@16: static inline detail::thread_data_ptr make_thread_info(F f Chris@16: , typename disable_if_c< Chris@16: //boost::thread_detail::is_convertible::value || Chris@16: is_same::type, thread>::value, Chris@16: dummy* >::type=0 Chris@16: ) Chris@16: { Chris@16: return detail::thread_data_ptr(detail::heap_new >(f)); Chris@16: } Chris@16: template Chris@16: static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) Chris@16: { Chris@16: return detail::thread_data_ptr(detail::heap_new >(f)); Chris@16: } Chris@16: Chris@16: #endif Chris@16: public: Chris@16: #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. Chris@16: #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) Chris@16: thread(const volatile thread&); Chris@16: #endif Chris@16: #endif Chris@16: thread() BOOST_NOEXCEPT; Chris@16: ~thread() Chris@16: { Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE Chris@16: if (joinable()) { Chris@16: std::terminate(); Chris@16: } Chris@16: #else Chris@16: detach(); Chris@16: #endif Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template < Chris@16: class F Chris@16: > Chris@16: explicit thread(BOOST_THREAD_RV_REF(F) f Chris@16: //, typename disable_if::type, thread>, dummy* >::type=0 Chris@16: ): Chris@16: thread_info(make_thread_info(thread_detail::decay_copy(boost::forward(f)))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: template < Chris@16: class F Chris@16: > Chris@16: thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): Chris@16: thread_info(make_thread_info(thread_detail::decay_copy(boost::forward(f)))) Chris@16: { Chris@16: start_thread(attrs); Chris@16: } Chris@16: Chris@16: #else Chris@16: #ifdef BOOST_NO_SFINAE Chris@16: template Chris@16: explicit thread(F f): Chris@16: thread_info(make_thread_info(f)) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: template Chris@16: thread(attributes const& attrs, F f): Chris@16: thread_info(make_thread_info(f)) Chris@16: { Chris@16: start_thread(attrs); Chris@16: } Chris@16: #else Chris@16: template Chris@16: explicit thread(F f Chris@16: , typename disable_if_c< Chris@101: boost::thread_detail::is_rv::value // todo ass a thread_detail::is_rv Chris@101: //boost::thread_detail::is_convertible::value Chris@16: //|| is_same::type, thread>::value Chris@16: , dummy* >::type=0 Chris@16: ): Chris@16: thread_info(make_thread_info(f)) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: template Chris@16: thread(attributes const& attrs, F f Chris@101: , typename disable_if, dummy* >::type=0 Chris@101: //, typename disable_if, dummy* >::type=0 Chris@16: ): Chris@16: thread_info(make_thread_info(f)) Chris@16: { Chris@16: start_thread(attrs); Chris@16: } Chris@16: #endif Chris@16: template Chris@16: explicit thread(BOOST_THREAD_RV_REF(F) f Chris@16: , typename disable_if::type, thread>, dummy* >::type=0 Chris@16: ): Chris@16: #ifdef BOOST_THREAD_USES_MOVE Chris@16: thread_info(make_thread_info(boost::move(f))) // todo : Add forward Chris@16: #else Chris@16: thread_info(make_thread_info(f)) // todo : Add forward Chris@16: #endif Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): Chris@16: #ifdef BOOST_THREAD_USES_MOVE Chris@16: thread_info(make_thread_info(boost::move(f))) // todo : Add forward Chris@16: #else Chris@16: thread_info(make_thread_info(f)) // todo : Add forward Chris@16: #endif Chris@16: { Chris@16: start_thread(attrs); Chris@16: } Chris@16: #endif Chris@101: thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT Chris@16: { Chris@16: thread_info=BOOST_THREAD_RV(x).thread_info; Chris@16: BOOST_THREAD_RV(x).thread_info.reset(); Chris@16: } Chris@16: #if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. Chris@16: #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) Chris@16: thread& operator=(thread x) Chris@16: { Chris@16: swap(x); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: #endif Chris@16: Chris@16: thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT Chris@16: { Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE Chris@16: if (joinable()) std::terminate(); Chris@16: #endif Chris@16: thread_info=BOOST_THREAD_RV(other).thread_info; Chris@16: BOOST_THREAD_RV(other).thread_info.reset(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) Chris@16: template Chris@16: thread(F&& f, Arg&& arg, Args&&... args) : Chris@16: thread_info(make_thread_info( Chris@16: thread_detail::decay_copy(boost::forward(f)), Chris@16: thread_detail::decay_copy(boost::forward(arg)), Chris@16: thread_detail::decay_copy(boost::forward(args))...) Chris@16: ) Chris@16: Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: template Chris@16: thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) : Chris@16: thread_info(make_thread_info( Chris@16: thread_detail::decay_copy(boost::forward(f)), Chris@16: thread_detail::decay_copy(boost::forward(arg)), Chris@16: thread_detail::decay_copy(boost::forward(args))...) Chris@16: ) Chris@16: Chris@16: { Chris@16: start_thread(attrs); Chris@16: } Chris@16: #else Chris@16: template Chris@16: thread(F f,A1 a1,typename disable_if, dummy* >::type=0): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2,A3 a3): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2,A3 a3,A4 a4): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6,a7))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6,a7,a8))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: Chris@16: template Chris@16: thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9): Chris@16: thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9))) Chris@16: { Chris@16: start_thread(); Chris@16: } Chris@16: #endif Chris@16: void swap(thread& x) BOOST_NOEXCEPT Chris@16: { Chris@16: thread_info.swap(x.thread_info); Chris@16: } Chris@16: Chris@16: class id; Chris@16: #ifdef BOOST_THREAD_PLATFORM_PTHREAD Chris@16: inline id get_id() const BOOST_NOEXCEPT; Chris@16: #else Chris@16: id get_id() const BOOST_NOEXCEPT; Chris@16: #endif Chris@16: Chris@16: Chris@16: bool joinable() const BOOST_NOEXCEPT; Chris@16: private: Chris@16: bool join_noexcept(); Chris@16: public: Chris@16: inline void join(); Chris@16: Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@101: #if defined(BOOST_THREAD_PLATFORM_WIN32) Chris@101: template Chris@101: bool try_join_for(const chrono::duration& rel_time) Chris@101: { Chris@101: chrono::milliseconds rel_time2= chrono::ceil(rel_time); Chris@101: return do_try_join_until(rel_time2.count()); Chris@101: } Chris@101: #else Chris@16: template Chris@16: bool try_join_for(const chrono::duration& rel_time) Chris@16: { Chris@16: return try_join_until(chrono::steady_clock::now() + rel_time); Chris@16: } Chris@101: #endif Chris@16: template Chris@16: bool try_join_until(const chrono::time_point& t) Chris@16: { Chris@16: using namespace chrono; Chris@16: system_clock::time_point s_now = system_clock::now(); Chris@16: bool joined= false; Chris@16: do { Chris@16: typename Clock::duration d = ceil(t-Clock::now()); Chris@16: if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached Chris@16: joined = try_join_until(s_now + d); Chris@16: } while (! joined); Chris@16: return true; Chris@16: } Chris@16: template Chris@16: bool try_join_until(const chrono::time_point& t) Chris@16: { Chris@16: using namespace chrono; Chris@16: typedef time_point nano_sys_tmpt; Chris@16: return try_join_until(nano_sys_tmpt(ceil(t.time_since_epoch()))); Chris@16: } Chris@16: #endif Chris@16: #if defined(BOOST_THREAD_PLATFORM_WIN32) Chris@16: private: Chris@16: bool do_try_join_until_noexcept(uintmax_t milli, bool& res); Chris@16: inline bool do_try_join_until(uintmax_t milli); Chris@16: public: Chris@16: bool timed_join(const system_time& abs_time); Chris@16: //{ Chris@16: // return do_try_join_until(get_milliseconds_until(wait_until)); Chris@16: //} Chris@16: Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: bool try_join_until(const chrono::time_point& tp) Chris@16: { Chris@16: chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); Chris@16: return do_try_join_until(rel_time.count()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: Chris@16: #else Chris@16: private: Chris@16: bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res); Chris@16: inline bool do_try_join_until(struct timespec const &timeout); Chris@16: public: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: bool timed_join(const system_time& abs_time) Chris@16: { Chris@16: struct timespec const ts=detail::to_timespec(abs_time); Chris@16: return do_try_join_until(ts); Chris@16: } Chris@16: #endif Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: bool try_join_until(const chrono::time_point& tp) Chris@16: { Chris@16: using namespace chrono; Chris@16: nanoseconds d = tp.time_since_epoch(); Chris@16: timespec ts = boost::detail::to_timespec(d); Chris@16: return do_try_join_until(ts); Chris@16: } Chris@16: #endif Chris@16: Chris@16: #endif Chris@16: public: Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: template Chris@16: inline bool timed_join(TimeDuration const& rel_time) Chris@16: { Chris@16: return timed_join(get_system_time()+rel_time); Chris@16: } Chris@16: #endif Chris@16: void detach(); Chris@16: Chris@16: static unsigned hardware_concurrency() BOOST_NOEXCEPT; Chris@101: static unsigned physical_concurrency() BOOST_NOEXCEPT; Chris@16: Chris@16: #define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE Chris@16: typedef detail::thread_data_base::native_handle_type native_handle_type; Chris@16: native_handle_type native_handle(); Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_THREAD_EQ Chris@16: // Use thread::id when comparisions are needed Chris@16: // backwards compatibility Chris@16: bool operator==(const thread& other) const; Chris@16: bool operator!=(const thread& other) const; Chris@16: #endif Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: static inline void yield() BOOST_NOEXCEPT Chris@16: { Chris@16: this_thread::yield(); Chris@16: } Chris@16: Chris@16: static inline void sleep(const system_time& xt) Chris@16: { Chris@16: this_thread::sleep(xt); Chris@16: } Chris@16: #endif Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: // extensions Chris@16: void interrupt(); Chris@16: bool interruption_requested() const BOOST_NOEXCEPT; Chris@16: #endif Chris@16: }; Chris@16: Chris@16: inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: return lhs.swap(rhs); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: inline thread&& move(thread& t) BOOST_NOEXCEPT Chris@16: { Chris@16: return static_cast(t); Chris@16: } Chris@16: #endif Chris@16: Chris@16: BOOST_THREAD_DCL_MOVABLE(thread) Chris@16: Chris@16: namespace this_thread Chris@16: { Chris@16: #ifdef BOOST_THREAD_PLATFORM_PTHREAD Chris@16: inline thread::id get_id() BOOST_NOEXCEPT; Chris@16: #else Chris@16: thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT; Chris@16: #endif Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: void BOOST_THREAD_DECL interruption_point(); Chris@16: bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT; Chris@16: bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT; Chris@16: #endif Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time) Chris@16: { Chris@16: sleep(system_time(abs_time)); Chris@16: } Chris@16: #endif Chris@16: } Chris@16: Chris@16: class BOOST_SYMBOL_VISIBLE thread::id Chris@16: { Chris@16: private: Chris@16: friend inline Chris@16: std::size_t Chris@16: hash_value(const thread::id &v) Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID Chris@16: return hash_value(v.thread_data); Chris@16: #else Chris@16: return hash_value(v.thread_data.get()); Chris@16: #endif Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID Chris@16: #if defined(BOOST_THREAD_PLATFORM_WIN32) Chris@16: typedef unsigned int data; Chris@16: #else Chris@16: typedef thread::native_handle_type data; Chris@16: #endif Chris@16: #else Chris@16: typedef detail::thread_data_ptr data; Chris@16: #endif Chris@16: data thread_data; Chris@16: Chris@16: id(data thread_data_): Chris@16: thread_data(thread_data_) Chris@16: {} Chris@16: friend class thread; Chris@16: friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT; Chris@16: public: Chris@16: id() BOOST_NOEXCEPT: Chris@16: #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID Chris@16: thread_data(0) Chris@16: #else Chris@16: thread_data() Chris@16: #endif Chris@16: {} Chris@16: Chris@16: id(const id& other) BOOST_NOEXCEPT : Chris@16: thread_data(other.thread_data) Chris@16: {} Chris@16: Chris@16: bool operator==(const id& y) const BOOST_NOEXCEPT Chris@16: { Chris@16: return thread_data==y.thread_data; Chris@16: } Chris@16: Chris@16: bool operator!=(const id& y) const BOOST_NOEXCEPT Chris@16: { Chris@16: return thread_data!=y.thread_data; Chris@16: } Chris@16: Chris@16: bool operator<(const id& y) const BOOST_NOEXCEPT Chris@16: { Chris@16: return thread_data(const id& y) const BOOST_NOEXCEPT Chris@16: { Chris@16: return y.thread_data=(const id& y) const BOOST_NOEXCEPT Chris@16: { Chris@16: return !(thread_data Chris@16: friend BOOST_SYMBOL_VISIBLE Chris@16: std::basic_ostream& Chris@16: operator<<(std::basic_ostream& os, const id& x) Chris@16: { Chris@16: if(x.thread_data) Chris@16: { Chris@16: io::ios_flags_saver ifs( os ); Chris@16: return os<< std::hex << x.thread_data; Chris@16: } Chris@16: else Chris@16: { Chris@16: return os<<"{Not-any-thread}"; Chris@16: } Chris@16: } Chris@16: #else Chris@16: template Chris@16: BOOST_SYMBOL_VISIBLE Chris@16: std::basic_ostream& Chris@16: print(std::basic_ostream& os) const Chris@16: { Chris@16: if(thread_data) Chris@16: { Chris@16: io::ios_flags_saver ifs( os ); Chris@16: return os<< std::hex << thread_data; Chris@16: } Chris@16: else Chris@16: { Chris@16: return os<<"{Not-any-thread}"; Chris@16: } Chris@16: } Chris@16: Chris@16: #endif Chris@16: #endif Chris@16: }; Chris@16: Chris@16: #ifdef BOOST_THREAD_PLATFORM_PTHREAD Chris@16: thread::id thread::get_id() const BOOST_NOEXCEPT Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID Chris@16: return const_cast(this)->native_handle(); Chris@16: #else Chris@16: detail::thread_data_ptr const local_thread_info=(get_thread_info)(); Chris@16: return (local_thread_info? id(local_thread_info) : id()); Chris@16: #endif Chris@16: } Chris@16: Chris@16: namespace this_thread Chris@16: { Chris@16: inline thread::id get_id() BOOST_NOEXCEPT Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID Chris@16: return pthread_self(); Chris@16: #else Chris@16: boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); Chris@16: return (thread_info?thread::id(thread_info->shared_from_this()):thread::id()); Chris@16: #endif Chris@16: } Chris@16: } Chris@16: #endif Chris@16: void thread::join() { Chris@16: if (this_thread::get_id() == get_id()) Chris@101: boost::throw_exception(thread_resource_error(static_cast(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); Chris@16: Chris@16: BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(), Chris@101: thread_resource_error(static_cast(system::errc::invalid_argument), "boost thread: thread not joinable") Chris@16: ); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_THREAD_PLATFORM_PTHREAD Chris@16: bool thread::do_try_join_until(struct timespec const &timeout) Chris@16: #else Chris@16: bool thread::do_try_join_until(uintmax_t timeout) Chris@16: #endif Chris@16: { Chris@16: if (this_thread::get_id() == get_id()) Chris@101: boost::throw_exception(thread_resource_error(static_cast(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); Chris@16: bool res; Chris@16: if (do_try_join_until_noexcept(timeout, res)) Chris@16: { Chris@16: return res; Chris@16: } Chris@16: else Chris@16: { Chris@16: BOOST_THREAD_THROW_ELSE_RETURN( Chris@101: (thread_resource_error(static_cast(system::errc::invalid_argument), "boost thread: thread not joinable")), Chris@16: false Chris@16: ); Chris@16: } Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: template Chris@16: BOOST_SYMBOL_VISIBLE Chris@16: std::basic_ostream& Chris@16: operator<<(std::basic_ostream& os, const thread::id& x) Chris@16: { Chris@16: return x.print(os); Chris@16: } Chris@16: #endif Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_THREAD_EQ Chris@16: inline bool thread::operator==(const thread& other) const Chris@16: { Chris@16: return get_id()==other.get_id(); Chris@16: } Chris@16: Chris@16: inline bool thread::operator!=(const thread& other) const Chris@16: { Chris@16: return get_id()!=other.get_id(); Chris@16: } Chris@16: #endif Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: struct thread_exit_function_base Chris@16: { Chris@16: virtual ~thread_exit_function_base() Chris@16: {} Chris@16: virtual void operator()()=0; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct thread_exit_function: Chris@16: thread_exit_function_base Chris@16: { Chris@16: F f; Chris@16: Chris@16: thread_exit_function(F f_): Chris@16: f(f_) Chris@16: {} Chris@16: Chris@16: void operator()() Chris@16: { Chris@16: f(); Chris@16: } Chris@16: }; Chris@16: Chris@16: void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); Chris@16: struct shared_state_base; Chris@16: #if defined(BOOST_THREAD_PLATFORM_WIN32) Chris@16: inline void make_ready_at_thread_exit(shared_ptr as) Chris@16: { Chris@16: detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); Chris@16: if(current_thread_data) Chris@16: { Chris@16: current_thread_data->make_ready_at_thread_exit(as); Chris@16: } Chris@16: } Chris@16: #else Chris@16: void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr as); Chris@16: #endif Chris@16: } Chris@16: Chris@16: namespace this_thread Chris@16: { Chris@16: template Chris@16: void at_thread_exit(F f) Chris@16: { Chris@16: detail::thread_exit_function_base* const thread_exit_func=detail::heap_new >(f); Chris@16: detail::add_thread_exit_function(thread_exit_func); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: #endif