diff --git a/include/boost/thread/detail/config.hpp b/include/boost/thread/detail/config.hpp index 87aa135f..45cbf377 100644 --- a/include/boost/thread/detail/config.hpp +++ b/include/boost/thread/detail/config.hpp @@ -12,7 +12,6 @@ #include #include -//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC //#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS // ATTRIBUTE_MAY_ALIAS @@ -385,6 +384,23 @@ # endif #endif +#if defined(BOOST_THREAD_PLATFORM_WIN32) + #define BOOST_THREAD_HAS_MONO_CLOCK + #define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO +#elif defined(BOOST_THREAD_MACOS) + //#define BOOST_THREAD_HAS_MONO_CLOCK +#else + #include // check for CLOCK_MONOTONIC + #if defined(CLOCK_MONOTONIC) + #define BOOST_THREAD_HAS_MONO_CLOCK + #if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) + #define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO + #endif + #else + #undef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + #endif +#endif + #if defined(BOOST_THREAD_PLATFORM_WIN32) #elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC #if defined BOOST_PTHREAD_HAS_TIMEDLOCK @@ -395,17 +411,6 @@ #endif #endif -#if defined(BOOST_THREAD_PLATFORM_WIN32) -#define BOOST_THREAD_HAS_MONO_TIMESPEC -#elif defined(BOOST_THREAD_MACOS) -//#define BOOST_THREAD_HAS_MONO_TIMESPEC -#else -#include // check for CLOCK_MONOTONIC -#if defined(CLOCK_MONOTONIC) -#define BOOST_THREAD_HAS_MONO_TIMESPEC -#endif -#endif - // provided for backwards compatibility, since this // macro was used for several releases by mistake. #if defined(BOOST_THREAD_DYN_DLL) && ! defined(BOOST_THREAD_DYN_LINK) diff --git a/include/boost/thread/detail/internal_clock.hpp b/include/boost/thread/detail/internal_clock.hpp index 105d687d..5ea6d34c 100644 --- a/include/boost/thread/detail/internal_clock.hpp +++ b/include/boost/thread/detail/internal_clock.hpp @@ -20,9 +20,7 @@ namespace boost { namespace thread_detail { #ifdef BOOST_THREAD_USES_CHRONO - #if defined(BOOST_THREAD_PLATFORM_WIN32) - typedef chrono::steady_clock internal_clock_t; - #elif defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) + #ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO typedef chrono::steady_clock internal_clock_t; #else typedef chrono::system_clock internal_clock_t; diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index ca79c3bf..d8e884fe 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -469,20 +469,11 @@ namespace boost inline void join(); #ifdef BOOST_THREAD_USES_CHRONO -#if defined(BOOST_THREAD_PLATFORM_WIN32) - template - bool try_join_for(const chrono::duration& rel_time) - { - chrono::milliseconds rel_time2= chrono::ceil(rel_time); - return do_try_join_for(rel_time2.count()); - } -#else template bool try_join_for(const chrono::duration& rel_time) { return try_join_until(chrono::steady_clock::now() + rel_time); } -#endif template bool try_join_until(const chrono::time_point& t) @@ -501,36 +492,6 @@ namespace boost return true; } #endif -#if defined(BOOST_THREAD_PLATFORM_WIN32) - private: - bool do_try_join_for_noexcept(uintmax_t milli, bool& res); - inline bool do_try_join_for(uintmax_t milli); - public: -#if defined BOOST_THREAD_USES_DATETIME - bool timed_join(const system_time& abs_time) - { - posix_time::time_duration d = abs_time - get_system_time(); - d = (std::min)(d, posix_time::time_duration(posix_time::milliseconds(100))); - while ( ! do_try_join_for(d.total_milliseconds()) ) - { - d = abs_time - get_system_time(); - if ( d <= posix_time::milliseconds(0) ) return false; - d = (std::min)(d, posix_time::time_duration(posix_time::milliseconds(100))); - } - return true; - } -#endif - -#ifdef BOOST_THREAD_USES_CHRONO - template - bool try_join_until(const chrono::time_point& t) - { - return try_join_for(t - chrono::steady_clock::now()); - } -#endif - - -#else // ! defined(BOOST_THREAD_PLATFORM_WIN32) private: bool do_try_join_until_noexcept(detail::internal_timespec_timepoint const &timeout, bool& res); inline bool do_try_join_until(detail::internal_timespec_timepoint const &timeout); @@ -539,7 +500,7 @@ namespace boost bool timed_join(const system_time& abs_time) { const detail::real_timespec_timepoint ts(abs_time); -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_join_until(detail::internal_timespec_clock::now() + d) ) @@ -560,8 +521,6 @@ namespace boost { return do_try_join_until(boost::detail::internal_timespec_timepoint(t)); } -#endif // defined(BOOST_THREAD_PLATFORM_WIN32) - #endif public: @@ -569,12 +528,9 @@ namespace boost template inline bool timed_join(TimeDuration const& rel_time) { -#if defined(BOOST_THREAD_PLATFORM_WIN32) - return do_try_join_for(rel_time.total_milliseconds()); -#else detail::timespec_duration d(rel_time); if ( d < detail::timespec_duration::zero() ) return false; // d == zero() is valid -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_join_until(detail::internal_timespec_clock::now() + d) ) @@ -586,7 +542,6 @@ namespace boost return true; #else return do_try_join_until(detail::internal_timespec_clock::now() + d); -#endif #endif } #endif @@ -804,7 +759,6 @@ namespace boost ); } -#ifdef BOOST_THREAD_PLATFORM_PTHREAD bool thread::do_try_join_until(detail::internal_timespec_timepoint const &timeout) { if (this_thread::get_id() == get_id()) @@ -822,26 +776,6 @@ namespace boost ); } } -#else - bool thread::do_try_join_for(uintmax_t timeout) - { - if (this_thread::get_id() == get_id()) - boost::throw_exception(thread_resource_error(static_cast(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); - bool res; - if (do_try_join_for_noexcept(timeout, res)) - { - return res; - } - else - { - BOOST_THREAD_THROW_ELSE_RETURN( - (thread_resource_error(static_cast(system::errc::invalid_argument), "boost thread: thread not joinable")), - false - ); - } - } -#endif - #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template diff --git a/include/boost/thread/future.hpp b/include/boost/thread/future.hpp index 8a32c746..5db3851b 100644 --- a/include/boost/thread/future.hpp +++ b/include/boost/thread/future.hpp @@ -39,9 +39,7 @@ #include #include -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) #include -#endif #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL #include @@ -373,25 +371,25 @@ namespace boost boost::unique_lock lock(this->mutex); wait(lock, rethrow); } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) - bool do_wait_until(detail::internal_timespec_timepoint const &abs_time) - { - boost::unique_lock lock(this->mutex); - if (is_deferred_) - return false; - do_callback(lock); - while(!done) + bool do_wait_until(detail::internal_timespec_timepoint const &abs_time) { - bool const success=waiters.do_wait_until(lock, abs_time); - if(!success && !done) - { + boost::unique_lock lock(this->mutex); + if (is_deferred_) return false; + + do_callback(lock); + while(!done) + { + bool const success=waiters.do_wait_until(lock, abs_time); + if(!success && !done) + { + return false; + } } + return true; } - return true; - } -#endif + #if defined BOOST_THREAD_USES_DATETIME bool timed_wait_until(boost::system_time const& target_time) { @@ -1470,7 +1468,7 @@ namespace boost } return future_->unnotify_when_ready(h); } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) + bool do_wait_until(detail::internal_timespec_timepoint const &abs_time) const { if(!future_) @@ -1479,15 +1477,13 @@ namespace boost } return future_->do_wait_until(abs_time); } -#endif + #if defined BOOST_THREAD_USES_DATETIME template bool timed_wait(Duration const& rel_time) const { - -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) detail::timespec_duration d(rel_time); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_wait_until(detail::internal_timespec_clock::now() + d) ) @@ -1499,10 +1495,6 @@ namespace boost return true; #else return do_wait_until(detail::internal_timespec_clock::now() + d); -#endif -#else - // fixme: make use of internal_clock instead of get_system_time - return timed_wait_until(boost::get_system_time()+rel_time); #endif } diff --git a/include/boost/thread/pthread/condition_variable.hpp b/include/boost/thread/pthread/condition_variable.hpp index 4c3bd570..881e4917 100644 --- a/include/boost/thread/pthread/condition_variable.hpp +++ b/include/boost/thread/pthread/condition_variable.hpp @@ -222,7 +222,7 @@ namespace boost #else boost::system_time const& abs_time_fixed = abs_time; #endif -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO const detail::real_timespec_timepoint ts(abs_time_fixed); detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); @@ -248,7 +248,7 @@ namespace boost { if (wait_duration.is_pos_infinity()) { - wait(m); // or do_wait(m,detail::timeout::sentinel()); + wait(m); return true; } if (wait_duration.is_special()) @@ -256,7 +256,7 @@ namespace boost return true; } detail::timespec_duration d(wait_duration); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_wait_until(m, detail::internal_timespec_clock::now() + d) ) @@ -295,7 +295,7 @@ namespace boost { while (!pred()) { - wait(m); // or do_wait(m,detail::timeout::sentinel()); + wait(m); } return true; } @@ -304,7 +304,7 @@ namespace boost return pred(); } detail::timespec_duration d(wait_duration); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! pred() && ! do_wait_until(m, detail::internal_timespec_clock::now() + d) ) @@ -327,7 +327,7 @@ namespace boost lock_type& lock, const chrono::time_point& t) { - boost::detail::internal_timespec_timepoint ts = t; + const boost::detail::internal_timespec_timepoint& ts = t; if (do_wait_until(lock, ts)) return cv_status::no_timeout; else return cv_status::timeout; } diff --git a/include/boost/thread/pthread/condition_variable_fwd.hpp b/include/boost/thread/pthread/condition_variable_fwd.hpp index 3023acf1..0a8f9941 100644 --- a/include/boost/thread/pthread/condition_variable_fwd.hpp +++ b/include/boost/thread/pthread/condition_variable_fwd.hpp @@ -122,7 +122,7 @@ namespace boost #else boost::system_time const& abs_time_fixed = abs_time; #endif -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO const detail::real_timespec_timepoint ts(abs_time_fixed); detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); @@ -151,7 +151,7 @@ namespace boost { if (wait_duration.is_pos_infinity()) { - wait(m); // or do_wait(m,detail::timeout::sentinel()); + wait(m); return true; } if (wait_duration.is_special()) @@ -159,7 +159,7 @@ namespace boost return true; } detail::timespec_duration d(wait_duration); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_wait_until(m, detail::internal_timespec_clock::now() + d) ) @@ -204,7 +204,7 @@ namespace boost { while (!pred()) { - wait(m); // or do_wait(m,detail::timeout::sentinel()); + wait(m); } return true; } @@ -213,7 +213,7 @@ namespace boost return pred(); } detail::timespec_duration d(wait_duration); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! pred() && ! do_wait_until(m, detail::internal_timespec_clock::now() + d) ) @@ -237,7 +237,7 @@ namespace boost unique_lock& lock, const chrono::time_point& t) { - const boost::detail::internal_timespec_timepoint ts = t; + const detail::internal_timespec_timepoint& ts = t; if (do_wait_until(lock, ts)) return cv_status::no_timeout; else return cv_status::timeout; } diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp index 5b408a22..1dfb96cc 100644 --- a/include/boost/thread/pthread/mutex.hpp +++ b/include/boost/thread/pthread/mutex.hpp @@ -207,7 +207,7 @@ namespace boost return true; } detail::timespec_duration d(relative_time); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_until(detail::internal_timespec_clock::now() + d) ) @@ -326,7 +326,7 @@ namespace boost bool timed_lock(system_time const & abs_time) { const detail::real_timespec_timepoint ts(abs_time); -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_until(detail::internal_timespec_clock::now() + d) ) diff --git a/include/boost/thread/pthread/recursive_mutex.hpp b/include/boost/thread/pthread/recursive_mutex.hpp index 48cf2296..3f9b9500 100644 --- a/include/boost/thread/pthread/recursive_mutex.hpp +++ b/include/boost/thread/pthread/recursive_mutex.hpp @@ -252,7 +252,7 @@ namespace boost return true; } detail::timespec_duration d(relative_time); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_until(detail::internal_timespec_clock::now() + d) ) @@ -370,7 +370,7 @@ namespace boost bool timed_lock(system_time const & abs_time) { const detail::real_timespec_timepoint ts(abs_time); -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_until(detail::internal_timespec_clock::now() + d) ) diff --git a/include/boost/thread/pthread/shared_mutex.hpp b/include/boost/thread/pthread/shared_mutex.hpp index 42c39bef..fe328fac 100644 --- a/include/boost/thread/pthread/shared_mutex.hpp +++ b/include/boost/thread/pthread/shared_mutex.hpp @@ -21,9 +21,7 @@ #endif #include #include -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) #include -#endif #include @@ -211,9 +209,8 @@ namespace boost #if defined BOOST_THREAD_USES_DATETIME bool timed_lock_shared(system_time const& timeout) { -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) const detail::real_timespec_timepoint ts(timeout); -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_shared_until(detail::internal_timespec_clock::now() + d) ) @@ -225,22 +222,6 @@ namespace boost return true; #else return do_try_lock_shared_until(ts); -#endif -#else -#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; -#endif - boost::unique_lock lk(state_change); - - while(!state.can_lock_shared()) - { - if(!shared_cond.timed_wait(lk,timeout)) - { - return false; - } - } - state.lock_shared(); - return true; #endif } @@ -256,9 +237,8 @@ namespace boost { return true; } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) detail::timespec_duration d(relative_time); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_shared_until(detail::internal_timespec_clock::now() + d) ) @@ -270,9 +250,6 @@ namespace boost return true; #else return do_try_lock_shared_until(detail::internal_timespec_clock::now() + d); -#endif -#else - return timed_lock_shared(get_system_time()+relative_time); #endif } #endif @@ -282,7 +259,6 @@ namespace boost { return try_lock_shared_until(chrono::steady_clock::now() + rel_time); } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) template bool try_lock_shared_until(const chrono::time_point& t) { @@ -304,27 +280,6 @@ namespace boost } return true; } -#else // 0 - template - bool try_lock_shared_until(const chrono::time_point& abs_time) - { -#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; -#endif - boost::unique_lock lk(state_change); - - while(!state.can_lock_shared()) - //while(state.exclusive || state.exclusive_waiting_blocked) - { - if(cv_status::timeout==shared_cond.wait_until(lk,abs_time)) - { - return false; - } - } - state.lock_shared(); - return true; - } -#endif #endif void unlock_shared() { @@ -367,7 +322,6 @@ namespace boost } private: -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) // fixme: Shouldn't these functions be located on a .cpp file? bool do_try_lock_until(const detail::internal_timespec_timepoint& abs_time) { @@ -457,16 +411,14 @@ namespace boost state.shared_count=0; return true; } -#endif public: #if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const& timeout) { -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) const detail::real_timespec_timepoint ts(timeout); -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_until(detail::internal_timespec_clock::now() + d) ) @@ -478,29 +430,6 @@ namespace boost return true; #else return do_try_lock_until(ts); -#endif -#else -#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; -#endif - boost::unique_lock lk(state_change); - - while(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=true; - if(!exclusive_cond.timed_wait(lk,timeout)) - { - if(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=false; - release_waiters(); - return false; - } - break; - } - } - state.exclusive=true; - return true; #endif } @@ -516,9 +445,8 @@ namespace boost { return true; } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) detail::timespec_duration d(relative_time); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_until(detail::internal_timespec_clock::now() + d) ) @@ -530,9 +458,6 @@ namespace boost return true; #else return do_try_lock_until(detail::internal_timespec_clock::now() + d); -#endif -#else - return timed_lock(get_system_time()+relative_time); #endif } #endif @@ -542,7 +467,6 @@ namespace boost { return try_lock_until(chrono::steady_clock::now() + rel_time); } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) template bool try_lock_until(const chrono::time_point& t) { @@ -564,33 +488,6 @@ namespace boost } return true; } -#else // 0 - template - bool try_lock_until(const chrono::time_point& abs_time) - { -#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; -#endif - boost::unique_lock lk(state_change); - - while(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=true; - if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) - { - if(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=false; - release_waiters(); - return false; - } - break; - } - } - state.exclusive=true; - return true; - } -#endif //0 #endif bool try_lock() @@ -636,9 +533,8 @@ namespace boost #if defined BOOST_THREAD_USES_DATETIME bool timed_lock_upgrade(system_time const& timeout) { -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) const detail::real_timespec_timepoint ts(timeout); -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO detail::timespec_duration d = ts - detail::real_timespec_clock::now(); d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_upgrade_until(detail::internal_timespec_clock::now() + d) ) @@ -650,26 +546,6 @@ namespace boost return true; #else return do_try_lock_upgrade_until(ts); -#endif -#else -#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; -#endif - boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { - if(!shared_cond.timed_wait(lk,timeout)) - { - if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { - return false; - } - break; - } - } - state.lock_shared(); - state.upgrade=true; - return true; #endif } @@ -685,9 +561,8 @@ namespace boost { return true; } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) detail::timespec_duration d(relative_time); -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts = detail::mono_timespec_clock::now() + d; d = (std::min)(d, detail::timespec_milliseconds(100)); while ( ! do_try_lock_upgrade_until(detail::internal_timespec_clock::now() + d) ) @@ -699,9 +574,6 @@ namespace boost return true; #else return do_try_lock_upgrade_until(detail::internal_timespec_clock::now() + d); -#endif -#else - return timed_lock_upgrade(get_system_time()+relative_time); #endif } #endif @@ -711,7 +583,6 @@ namespace boost { return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time); } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) template bool try_lock_upgrade_until(const chrono::time_point& t) { @@ -733,30 +604,6 @@ namespace boost } return true; } -#else // 0 - template - bool try_lock_upgrade_until(const chrono::time_point& abs_time) - { -#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; -#endif - boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { - if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) - { - if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { - return false; - } - break; - } - } - state.lock_shared(); - state.upgrade=true; - return true; - } -#endif // 0 #endif bool try_lock_upgrade() { @@ -843,7 +690,6 @@ namespace boost { return try_unlock_upgrade_and_lock_until(chrono::steady_clock::now() + rel_time); } -#if defined(BOOST_THREAD_PLATFORM_PTHREAD) template bool try_unlock_upgrade_and_lock_until(const chrono::time_point& t) { @@ -865,35 +711,6 @@ namespace boost } return true; } -#else // 0 - template - bool - try_unlock_upgrade_and_lock_until( - const chrono::time_point& abs_time) - { -#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; -#endif - boost::unique_lock lk(state_change); - state.assert_lock_upgraded(); - if (state.shared_count != 1) - { - for (;;) - { - cv_status status = shared_cond.wait_until(lk,abs_time); - if (state.shared_count == 1) - break; - if(status == cv_status::timeout) - return false; - } - } - state.upgrade=false; - state.exclusive=true; - state.exclusive_waiting_blocked=false; - state.shared_count=0; - return true; - } -#endif // 0 #endif // Shared <-> Exclusive diff --git a/include/boost/thread/pthread/thread_data.hpp b/include/boost/thread/pthread/thread_data.hpp index 21ec71c1..5ab49bba 100644 --- a/include/boost/thread/pthread/thread_data.hpp +++ b/include/boost/thread/pthread/thread_data.hpp @@ -277,7 +277,7 @@ namespace boost unique_lock lock(mx); condition_variable cond; -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO detail::timespec_duration d = ts - detail::real_timespec_clock::now(); while (d > detail::timespec_duration::zero()) { diff --git a/include/boost/thread/pthread/timespec.hpp b/include/boost/thread/pthread/timespec.hpp index 9a3f56d5..4417b24a 100644 --- a/include/boost/thread/pthread/timespec.hpp +++ b/include/boost/thread/pthread/timespec.hpp @@ -23,6 +23,7 @@ #if defined(BOOST_THREAD_PLATFORM_WIN32) #include +#include #include #elif defined(BOOST_THREAD_MACOS) #include //for gettimeofday and timeval @@ -77,6 +78,21 @@ namespace boost timespec& get() { return value; } timespec const& get() const { return value; } boost::intmax_t getNs() const { return timespec_to_ns(value); } + inline boost::intmax_t getMs() const + { + const boost::intmax_t& ns = timespec_to_ns(value); + // ceil/floor away from zero + if (ns >= 0) + { + // return ceiling of positive numbers + return (ns + 999999) / 1000000; + } + else + { + // return floor of negative numbers + return (ns - 999999) / 1000000; + } + } static inline timespec_duration zero() { @@ -140,9 +156,9 @@ namespace boost } #endif - timespec& get() { return value; } - timespec const& get() const { return value; } - boost::intmax_t getNs() const { return timespec_to_ns(value); } + inline timespec& get() { return value; } + inline timespec const& get() const { return value; } + inline boost::intmax_t getNs() const { return timespec_to_ns(value); } private: timespec value; @@ -206,7 +222,7 @@ namespace boost timespec ts; if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) { - BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); + BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_REALTIME) Internal Error"); return real_timespec_timepoint(0); } return real_timespec_timepoint(ts); @@ -214,7 +230,7 @@ namespace boost } }; -#if defined(BOOST_THREAD_HAS_MONO_TIMESPEC) +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) class mono_timespec_timepoint { @@ -224,12 +240,21 @@ namespace boost #if defined BOOST_THREAD_USES_CHRONO template - inline mono_timespec_timepoint(chrono::time_point const& abs_time); + mono_timespec_timepoint(chrono::time_point const& abs_time); #endif - timespec& get() { return value; } - timespec const& get() const { return value; } - boost::intmax_t getNs() const { return timespec_to_ns(value); } + inline timespec& get() { return value; } + inline timespec const& get() const { return value; } + inline boost::intmax_t getNs() const { return timespec_to_ns(value); } + + // can't use max() since that is a macro on some Windows systems + static inline mono_timespec_timepoint getMax() + { + timespec ts; + ts.tv_sec = 0x7fffffff; + ts.tv_nsec = 0x7fffffff; + return mono_timespec_timepoint(ts); + } private: timespec value; @@ -278,20 +303,52 @@ namespace boost static inline mono_timespec_timepoint now() { #if defined(BOOST_THREAD_PLATFORM_WIN32) - win32::tick_types msec = win32::GetTickCount64_()(); +#if defined(BOOST_THREAD_USES_CHRONO) + // Use QueryPerformanceCounter() to match the implementation in Boost + // Chrono so that chrono::steady_clock::now() and this function share the + // same epoch and so can be converted between each other. + boost::detail::winapi::LARGE_INTEGER_ freq; + if ( !boost::detail::winapi::QueryPerformanceFrequency( &freq ) ) + { + BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error"); + return mono_timespec_timepoint(0); + } + if ( freq.QuadPart <= 0 ) + { + BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error"); + return mono_timespec_timepoint(0); + } + + boost::detail::winapi::LARGE_INTEGER_ pcount; + unsigned times=0; + while ( ! boost::detail::winapi::QueryPerformanceCounter( &pcount ) ) + { + if ( ++times > 3 ) + { + BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceCounter Internal Error"); + return mono_timespec_timepoint(0); + } + } + + long double ns = 1000000000.0L * pcount.QuadPart / freq.QuadPart; + return mono_timespec_timepoint(static_cast(ns)); +#else + // Use GetTickCount64() because it's more reliable on older + // systems like Windows XP and Windows Server 2003. + win32::ticks_type msec = win32::GetTickCount64_()(); return mono_timespec_timepoint(msec * 1000000); +#endif #elif defined(BOOST_THREAD_MACOS) // fixme: add support for mono_timespec_clock::now() on MAC OS X using code from // https://github.com/boostorg/chrono/blob/develop/include/boost/chrono/detail/inlined/mac/chrono.hpp - // Also update BOOST_THREAD_HAS_MONO_TIMESPEC in config.hpp + // Also update BOOST_THREAD_HAS_MONO_CLOCK in config.hpp return mono_timespec_timepoint(0); #else timespec ts; if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) ) { - ts.tv_sec = 0; - ts.tv_nsec = 0; BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_MONOTONIC) Internal Error"); + return mono_timespec_timepoint(0); } return mono_timespec_timepoint(ts); #endif @@ -302,13 +359,15 @@ namespace boost template mono_timespec_timepoint::mono_timespec_timepoint(chrono::time_point const& abs_time) { + // This conversion assumes that chrono::steady_clock::now() and + // mono_timespec_clock::now() share the same epoch. value = timespec_duration(abs_time.time_since_epoch()).get(); } #endif #endif -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) typedef mono_timespec_clock internal_timespec_clock; typedef mono_timespec_timepoint internal_timespec_timepoint; #else diff --git a/include/boost/thread/win32/condition_variable.hpp b/include/boost/thread/win32/condition_variable.hpp index 3281c9cb..185f78cd 100644 --- a/include/boost/thread/win32/condition_variable.hpp +++ b/include/boost/thread/win32/condition_variable.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -89,9 +91,9 @@ namespace boost return notified; } - bool wait(timeout abs_or_rel_time) + bool do_wait_until(detail::internal_timespec_timepoint const &timeout) { - return this_thread::interruptible_wait(semaphore,abs_or_rel_time); + return this_thread::interruptible_wait(semaphore, timeout); } bool woken() @@ -230,10 +232,20 @@ namespace boost } }; - protected: + basic_condition_variable(const basic_condition_variable& other); + basic_condition_variable& operator=(const basic_condition_variable& other); + + public: + basic_condition_variable(): + total_count(0),active_generation_count(0),wake_sem(0) + {} + + ~basic_condition_variable() + {} + template - bool do_wait(lock_type& lock,timeout abs_or_rel_time) + bool do_wait_until(lock_type& lock, detail::internal_timespec_timepoint const &timeout) { relocker locker(lock); entry_manager entry(get_wait_entry(), internal_mutex); @@ -242,7 +254,7 @@ namespace boost bool woken=false; while(!woken) { - if(!entry->wait(abs_or_rel_time)) + if(!entry->do_wait_until(timeout)) { return false; } @@ -255,28 +267,6 @@ namespace boost return woken; } - template - bool do_wait(lock_type& m,timeout const& abs_or_rel_time,predicate_type pred) - { - while (!pred()) - { - if(!do_wait(m, abs_or_rel_time)) - return pred(); - } - return true; - } - - basic_condition_variable(const basic_condition_variable& other); - basic_condition_variable& operator=(const basic_condition_variable& other); - - public: - basic_condition_variable(): - total_count(0),active_generation_count(0),wake_sem(0) - {} - - ~basic_condition_variable() - {} - void notify_one() BOOST_NOEXCEPT { if(detail::interlocked_read_acquire(&total_count)) @@ -330,12 +320,13 @@ namespace boost condition_variable() {} + using detail::basic_condition_variable::do_wait_until; using detail::basic_condition_variable::notify_one; using detail::basic_condition_variable::notify_all; void wait(unique_lock& m) { - do_wait(m,detail::timeout::sentinel()); + do_wait_until(m, detail::internal_timespec_timepoint::getMax()); } template @@ -348,37 +339,53 @@ namespace boost #if defined BOOST_THREAD_USES_DATETIME bool timed_wait(unique_lock& m,boost::system_time const& abs_time) { - return do_wait(m,abs_time); + const detail::real_timespec_timepoint ts(abs_time); + detail::timespec_duration d = ts - detail::real_timespec_clock::now(); + d = (std::min)(d, detail::timespec_milliseconds(100)); + while ( ! do_wait_until(m, detail::internal_timespec_clock::now() + d) ) + { + d = ts - detail::real_timespec_clock::now(); + if ( d <= detail::timespec_duration::zero() ) return false; + d = (std::min)(d, detail::timespec_milliseconds(100)); + } + return true; } bool timed_wait(unique_lock& m,boost::xtime const& abs_time) { - return do_wait(m,system_time(abs_time)); + return timed_wait(m, system_time(abs_time)); } template bool timed_wait(unique_lock& m,duration_type const& wait_duration) { - if (wait_duration.is_pos_infinity()) - { - wait(m); // or do_wait(m,detail::timeout::sentinel()); - return true; - } - if (wait_duration.is_special()) - { - return true; - } - return do_wait(m,wait_duration.total_milliseconds()); + if (wait_duration.is_pos_infinity()) + { + wait(m); + return true; + } + if (wait_duration.is_special()) + { + return true; + } + const detail::internal_timespec_timepoint& ts = detail::internal_timespec_clock::now() + + detail::timespec_duration(wait_duration); + return do_wait_until(m, ts); } template bool timed_wait(unique_lock& m,boost::system_time const& abs_time,predicate_type pred) { - return do_wait(m,abs_time,pred); + while (!pred()) + { + if(!timed_wait(m, abs_time)) + return pred(); + } + return true; } template bool timed_wait(unique_lock& m,boost::xtime const& abs_time,predicate_type pred) { - return do_wait(m,system_time(abs_time),pred); + return timed_wait(m, system_time(abs_time), pred); } template bool timed_wait(unique_lock& m,duration_type const& wait_duration,predicate_type pred) @@ -387,7 +394,7 @@ namespace boost { while (!pred()) { - wait(m); // or do_wait(m,detail::timeout::sentinel()); + wait(m); } return true; } @@ -395,10 +402,27 @@ namespace boost { return pred(); } - return do_wait(m,wait_duration.total_milliseconds(),pred); + const detail::internal_timespec_timepoint& ts = detail::internal_timespec_clock::now() + + detail::timespec_duration(wait_duration); + while (!pred()) + { + if(!do_wait_until(m, ts)) + return pred(); + } + return true; } #endif #ifdef BOOST_THREAD_USES_CHRONO + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + const detail::internal_timespec_timepoint& ts = t; + if (do_wait_until(lock, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } template cv_status @@ -407,13 +431,17 @@ namespace boost const chrono::time_point& t) { using namespace chrono; - chrono::time_point now = Clock::now(); - if (t<=now) { - return cv_status::timeout; + typedef typename common_type::type CD; + CD d = t - Clock::now(); + if ( d <= CD::zero() ) return cv_status::timeout; + d = (std::min)(d, CD(milliseconds(100))); + while (cv_status::timeout == wait_until(lock, thread_detail::internal_clock_t::now() + d)) + { + d = t - Clock::now(); + if ( d <= CD::zero() ) return cv_status::timeout; + d = (std::min)(d, CD(milliseconds(100))); } - do_wait(lock, ceil(t-now).count()); - return Clock::now() < t ? cv_status::no_timeout : - cv_status::timeout; + return cv_status::no_timeout; } template @@ -422,15 +450,7 @@ namespace boost unique_lock& lock, const chrono::duration& d) { - using namespace chrono; - if (d<=chrono::duration::zero()) { - return cv_status::timeout; - } - - steady_clock::time_point c_now = steady_clock::now(); - do_wait(lock, ceil(d).count()); - return steady_clock::now() - c_now < d ? cv_status::no_timeout : - cv_status::timeout; + return wait_until(lock, chrono::steady_clock::now() + d); } template @@ -447,6 +467,7 @@ namespace boost } return true; } + template bool wait_for( @@ -467,13 +488,14 @@ namespace boost condition_variable_any() {} + using detail::basic_condition_variable::do_wait_until; using detail::basic_condition_variable::notify_one; using detail::basic_condition_variable::notify_all; template void wait(lock_type& m) { - do_wait(m,detail::timeout::sentinel()); + do_wait_until(m, detail::internal_timespec_timepoint::getMax()); } template @@ -486,40 +508,94 @@ namespace boost template bool timed_wait(lock_type& m,boost::system_time const& abs_time) { - return do_wait(m,abs_time); + const detail::real_timespec_timepoint ts(abs_time); + detail::timespec_duration d = ts - detail::real_timespec_clock::now(); + d = (std::min)(d, detail::timespec_milliseconds(100)); + while ( ! do_wait_until(m, detail::internal_timespec_clock::now() + d) ) + { + d = ts - detail::real_timespec_clock::now(); + if ( d <= detail::timespec_duration::zero() ) return false; + d = (std::min)(d, detail::timespec_milliseconds(100)); + } + return true; } template bool timed_wait(lock_type& m,boost::xtime const& abs_time) { - return do_wait(m,system_time(abs_time)); + return timed_wait(m, system_time(abs_time)); } template bool timed_wait(lock_type& m,duration_type const& wait_duration) { - return do_wait(m,wait_duration.total_milliseconds()); + if (wait_duration.is_pos_infinity()) + { + wait(m); + return true; + } + if (wait_duration.is_special()) + { + return true; + } + const detail::internal_timespec_timepoint& ts = detail::internal_timespec_clock::now() + + detail::timespec_duration(wait_duration); + return do_wait_until(m, ts); } template bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred) { - return do_wait(m,abs_time,pred); + while (!pred()) + { + if(!timed_wait(m, abs_time)) + return pred(); + } + return true; } template bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred) { - return do_wait(m,system_time(abs_time),pred); + return timed_wait(m, system_time(abs_time), pred); } template bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) { - return do_wait(m,wait_duration.total_milliseconds(),pred); + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } + const detail::internal_timespec_timepoint& ts = detail::internal_timespec_clock::now() + + detail::timespec_duration(wait_duration); + while (!pred()) + { + if(!do_wait_until(m, ts)) + return pred(); + } + return true; } #endif #ifdef BOOST_THREAD_USES_CHRONO + template + cv_status + wait_until( + lock_type& lock, + const chrono::time_point& t) + { + const detail::internal_timespec_timepoint& ts = t; + if (do_wait_until(lock, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } template cv_status @@ -528,13 +604,17 @@ namespace boost const chrono::time_point& t) { using namespace chrono; - chrono::time_point now = Clock::now(); - if (t<=now) { - return cv_status::timeout; + typedef typename common_type::type CD; + CD d = t - Clock::now(); + if ( d <= CD::zero() ) return cv_status::timeout; + d = (std::min)(d, CD(milliseconds(100))); + while (cv_status::timeout == wait_until(lock, thread_detail::internal_clock_t::now() + d)) + { + d = t - Clock::now(); + if ( d <= CD::zero() ) return cv_status::timeout; + d = (std::min)(d, CD(milliseconds(100))); } - do_wait(lock, ceil(t-now).count()); - return Clock::now() < t ? cv_status::no_timeout : - cv_status::timeout; + return cv_status::no_timeout; } template @@ -543,14 +623,7 @@ namespace boost lock_type& lock, const chrono::duration& d) { - using namespace chrono; - if (d<=chrono::duration::zero()) { - return cv_status::timeout; - } - steady_clock::time_point c_now = steady_clock::now(); - do_wait(lock, ceil(d).count()); - return steady_clock::now() - c_now < d ? cv_status::no_timeout : - cv_status::timeout; + return wait_until(lock, chrono::steady_clock::now() + d); } template diff --git a/include/boost/thread/win32/thread_data.hpp b/include/boost/thread/win32/thread_data.hpp index 9bf2ba62..70a3a9c5 100644 --- a/include/boost/thread/win32/thread_data.hpp +++ b/include/boost/thread/win32/thread_data.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -174,131 +175,48 @@ namespace boost BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); typedef boost::intrusive_ptr thread_data_ptr; - - struct BOOST_SYMBOL_VISIBLE timeout - { - win32::ticks_type start; - uintmax_t milliseconds; - bool relative; - boost::system_time abs_time; - - static unsigned long const max_non_infinite_wait=0xfffffffe; - - timeout(uintmax_t milliseconds_): - start(win32::GetTickCount64_()()), - milliseconds(milliseconds_), - relative(true) - //, - // abs_time(boost::get_system_time()) - {} - - timeout(boost::system_time const& abs_time_): - start(win32::GetTickCount64_()()), - milliseconds(0), - relative(false), - abs_time(abs_time_) - {} - - struct BOOST_SYMBOL_VISIBLE remaining_time - { - bool more; - unsigned long milliseconds; - - remaining_time(uintmax_t remaining): - more(remaining>max_non_infinite_wait), - milliseconds(more?max_non_infinite_wait:(unsigned long)remaining) - {} - }; - - remaining_time remaining_milliseconds() const - { - if(is_sentinel()) - { - return remaining_time(win32::infinite); - } - else if(relative) - { - win32::ticks_type const now=win32::GetTickCount64_()(); - win32::ticks_type const elapsed=now-start; - return remaining_time((elapsed inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { - interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); + interruptible_wait(detail::win32::invalid_handle_value, detail::internal_timespec_clock::now() + detail::timespec_duration(rel_time)); } inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { - interruptible_wait(abs_time); + const detail::real_timespec_timepoint ts(abs_time); + detail::timespec_duration d = ts - detail::real_timespec_clock::now(); + while (d > detail::timespec_duration::zero()) + { + d = (std::min)(d, detail::timespec_milliseconds(100)); + interruptible_wait(detail::win32::invalid_handle_value, detail::internal_timespec_clock::now() + d); + d = ts - detail::real_timespec_clock::now(); + } } + namespace no_interruption_point { - bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); - inline void non_interruptible_wait(uintmax_t milliseconds) - { - non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds); - } - inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time) - { - non_interruptible_wait(detail::win32::invalid_handle_value,abs_time); - } + bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_timespec_timepoint const &timeout); template inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { - non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); + non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_timespec_clock::now() + detail::timespec_duration(rel_time)); } inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { - non_interruptible_wait(abs_time); + const detail::real_timespec_timepoint ts(abs_time); + detail::timespec_duration d = ts - detail::real_timespec_clock::now(); + while (d > detail::timespec_duration::zero()) + { + d = (std::min)(d, detail::timespec_milliseconds(100)); + non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_timespec_clock::now() + d); + d = ts - detail::real_timespec_clock::now(); + } } } } diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index b43041df..3f6b1dbd 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -467,7 +467,7 @@ namespace boost unique_lock lock(mx); condition_variable cond; -#if defined(CLOCK_MONOTONIC) && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) const detail::mono_timespec_timepoint& ts2 = detail::mono_timespec_clock::now() + ts; detail::timespec_duration d = ts; while (d > detail::timespec_duration::zero()) @@ -498,10 +498,6 @@ namespace boost // sleep(xt); // sleep_for(chrono::milliseconds(0)); # else -#error -// timespec ts; -// ts.tv_sec= 0; -// ts.tv_nsec= 0; hidden::sleep_for(detail::timespec_duration::zero()); # endif } diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index 84505d62..4cf64c8c 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -439,7 +439,7 @@ namespace boost detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { - this_thread::interruptible_wait(this->native_handle(),detail::timeout::sentinel()); + this_thread::interruptible_wait(this->native_handle(), detail::internal_timespec_timepoint::getMax()); release_handle(); return true; } @@ -449,12 +449,12 @@ namespace boost } } - bool thread::do_try_join_for_noexcept(uintmax_t milli, bool& res) + bool thread::do_try_join_until_noexcept(detail::internal_timespec_timepoint const &timeout, bool& res) { detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { - if(!this_thread::interruptible_wait(this->native_handle(),milli)) + if(!this_thread::interruptible_wait(this->native_handle(), timeout)) { res=false; return true; @@ -555,62 +555,6 @@ namespace boost namespace this_thread { - namespace - { - LARGE_INTEGER get_due_time(detail::timeout const& target_time) - { - LARGE_INTEGER due_time={{0,0}}; - if(target_time.relative) - { - detail::win32::ticks_type const elapsed_milliseconds=detail::win32::GetTickCount64_()()-target_time.start; - LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds); - LONGLONG const hundred_nanoseconds_in_one_millisecond=10000; - - if(remaining_milliseconds>0) - { - due_time.QuadPart=-(remaining_milliseconds*hundred_nanoseconds_in_one_millisecond); - } - } - else - { - SYSTEMTIME target_system_time={0,0,0,0,0,0,0,0}; - target_system_time.wYear=target_time.abs_time.date().year(); - target_system_time.wMonth=target_time.abs_time.date().month(); - target_system_time.wDay=target_time.abs_time.date().day(); - target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours(); - target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes(); - target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds(); - - if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time))) - { - due_time.QuadPart=0; - } - else - { - long const hundred_nanoseconds_in_one_second=10000000; - posix_time::time_duration::tick_type const ticks_per_second= - target_time.abs_time.time_of_day().ticks_per_second(); - if(ticks_per_second>hundred_nanoseconds_in_one_second) - { - posix_time::time_duration::tick_type const - ticks_per_hundred_nanoseconds= - ticks_per_second/hundred_nanoseconds_in_one_second; - due_time.QuadPart+= - target_time.abs_time.time_of_day().fractional_seconds()/ - ticks_per_hundred_nanoseconds; - } - else - { - due_time.QuadPart+= - target_time.abs_time.time_of_day().fractional_seconds()* - (hundred_nanoseconds_in_one_second/ticks_per_second); - } - } - } - return due_time; - } - } - #ifndef UNDER_CE #if !BOOST_PLAT_WINDOWS_RUNTIME namespace detail_ @@ -661,7 +605,7 @@ namespace boost } #endif #endif - bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) + bool interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_timespec_timepoint const &timeout) { detail::win32::handle handles[4]={0}; unsigned handle_count=0; @@ -687,16 +631,20 @@ namespace boost #ifndef UNDER_CE #if !BOOST_PLAT_WINDOWS_RUNTIME // Preferentially use coalescing timers for better power consumption and timer accuracy - if(!target_time.is_sentinel()) + if(timeout != detail::internal_timespec_timepoint::getMax()) { - detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); + boost::intmax_t const time_left_msec = (timeout - detail::internal_timespec_clock::now()).getMs(); timer_handle=CreateWaitableTimer(NULL,false,NULL); if(timer_handle!=0) { ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26 - if(time_left.milliseconds/20>tolerable) // 5% - tolerable=time_left.milliseconds/20; - LARGE_INTEGER due_time=get_due_time(target_time); + if(time_left_msec/20>tolerable) // 5% + tolerable=static_cast(time_left_msec/20); + LARGE_INTEGER due_time={{0,0}}; + if(time_left_msec>0) + { + due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time + } bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0; if(set_time_succeeded) { @@ -709,18 +657,21 @@ namespace boost #endif bool const using_timer=timeout_index!=~0u; - detail::timeout::remaining_time time_left(0); + boost::intmax_t time_left_msec(INFINITE); + if(!using_timer && timeout != detail::internal_timespec_timepoint::getMax()) + { + time_left_msec = (timeout - detail::internal_timespec_clock::now()).getMs(); + if(time_left_msec < 0) + { + time_left_msec = 0; + } + } do { - if(!using_timer) - { - time_left=target_time.remaining_milliseconds(); - } - if(handle_count) { - unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0); + unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast(time_left_msec), 0); if(notified_index(time_left_msec)); } - if(target_time.relative) + + if(!using_timer && timeout != detail::internal_timespec_timepoint::getMax()) { - target_time.milliseconds-=detail::timeout::max_non_infinite_wait; + time_left_msec = (timeout - detail::internal_timespec_clock::now()).getMs(); } } - while(time_left.more); + while(time_left_msec == INFINITE || time_left_msec > 0); return false; } namespace no_interruption_point { - bool non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time) + bool non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_timespec_timepoint const &timeout) { detail::win32::handle handles[3]={0}; unsigned handle_count=0; @@ -771,16 +723,20 @@ namespace boost #ifndef UNDER_CE #if !BOOST_PLAT_WINDOWS_RUNTIME // Preferentially use coalescing timers for better power consumption and timer accuracy - if(!target_time.is_sentinel()) + if(timeout != detail::internal_timespec_timepoint::getMax()) { - detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds(); + boost::intmax_t const time_left_msec = (timeout - detail::internal_timespec_clock::now()).getMs(); timer_handle=CreateWaitableTimer(NULL,false,NULL); if(timer_handle!=0) { ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26 - if(time_left.milliseconds/20>tolerable) // 5% - tolerable=time_left.milliseconds/20; - LARGE_INTEGER due_time=get_due_time(target_time); + if(time_left_msec/20>tolerable) // 5% + tolerable=static_cast(time_left_msec/20); + LARGE_INTEGER due_time={{0,0}}; + if(time_left_msec>0) + { + due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time + } bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0; if(set_time_succeeded) { @@ -793,18 +749,21 @@ namespace boost #endif bool const using_timer=timeout_index!=~0u; - detail::timeout::remaining_time time_left(0); + boost::intmax_t time_left_msec(INFINITE); + if(!using_timer && timeout != detail::internal_timespec_timepoint::getMax()) + { + time_left_msec = (timeout - detail::internal_timespec_clock::now()).getMs(); + if(time_left_msec < 0) + { + time_left_msec = 0; + } + } do { - if(!using_timer) - { - time_left=target_time.remaining_milliseconds(); - } - if(handle_count) { - unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0); + unsigned long const notified_index=detail::winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast(time_left_msec), 0); if(notified_index(time_left_msec)); } - if(target_time.relative) + + if(!using_timer && timeout != detail::internal_timespec_timepoint::getMax()) { - target_time.milliseconds-=detail::timeout::max_non_infinite_wait; + time_left_msec = (timeout - detail::internal_timespec_clock::now()).getMs(); } } - while(time_left.more); + while(time_left_msec == INFINITE || time_left_msec > 0); return false; } }