From 5ffca91e60bacda60c8e1b43231f6b3d52ef1d3d Mon Sep 17 00:00:00 2001 From: Austin Beer Date: Fri, 29 Sep 2017 10:22:01 -0600 Subject: [PATCH] * Hopefully fixed the build failure on Mac OS. * Refactored to use timespec as the internal storage with pthread and intmax_t with Windows. --- include/boost/thread/detail/timespec.hpp | 110 ++++++++++-------- .../thread/pthread/condition_variable.hpp | 8 +- include/boost/thread/pthread/mutex.hpp | 6 +- .../boost/thread/pthread/recursive_mutex.hpp | 6 +- src/pthread/thread.cpp | 7 +- 5 files changed, 74 insertions(+), 63 deletions(-) diff --git a/include/boost/thread/detail/timespec.hpp b/include/boost/thread/detail/timespec.hpp index 7a571774..4b58ddb1 100644 --- a/include/boost/thread/detail/timespec.hpp +++ b/include/boost/thread/detail/timespec.hpp @@ -57,39 +57,55 @@ namespace boost class timespec_duration { public: - explicit timespec_duration(boost::intmax_t const& ns) : value(ns) {} +#if defined BOOST_THREAD_PLATFORM_PTHREAD + explicit timespec_duration(timespec const& v) : ts_val(v) {} + inline timespec const& getTs() const { return ts_val; } + + explicit timespec_duration(boost::intmax_t const& ns = 0) : ts_val(ns_to_timespec(ns)) {} + inline boost::intmax_t getNs() const { return timespec_to_ns(ts_val); } +#else + explicit timespec_duration(boost::intmax_t const& ns = 0) : ns_val(ns) {} + inline boost::intmax_t getNs() const { return ns_val; } +#endif #if defined BOOST_THREAD_USES_DATETIME timespec_duration(boost::posix_time::time_duration const& rel_time) { - value = static_cast(rel_time.total_seconds()) * 1000000000l; - value += rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second()); +#if defined BOOST_THREAD_PLATFORM_PTHREAD + ts_val.tv_sec = rel_time.total_seconds(); + ts_val.tv_nsec = static_cast(rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second())); +#else + ns_val = static_cast(rel_time.total_seconds()) * 1000000000l; + ns_val += rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second()); +#endif } #endif + #if defined BOOST_THREAD_USES_CHRONO template timespec_duration(chrono::duration const& d) { - value = chrono::ceil(d).count(); +#if defined BOOST_THREAD_PLATFORM_PTHREAD + ts_val = ns_to_timespec(chrono::ceil(d).count()); +#else + ns_val = chrono::ceil(d).count(); +#endif } #endif -#if defined BOOST_THREAD_PLATFORM_PTHREAD - inline timespec getTs() const { return ns_to_timespec(value); } -#endif - inline boost::intmax_t getNs() const { return value; } inline boost::intmax_t getMs() const { + const boost::intmax_t ns = getNs(); // ceil/floor away from zero - if (value >= 0) + if (ns >= 0) { // return ceiling of positive numbers - return (value + 999999) / 1000000; + return (ns + 999999) / 1000000; } else { // return floor of negative numbers - return (value - 999999) / 1000000; + return (ns - 999999) / 1000000; } } @@ -97,8 +113,13 @@ namespace boost { return timespec_duration(0); } + private: - boost::intmax_t value; +#if defined BOOST_THREAD_PLATFORM_PTHREAD + timespec ts_val; +#else + boost::intmax_t ns_val; +#endif }; inline bool operator==(timespec_duration const& lhs, timespec_duration const& rhs) @@ -134,30 +155,27 @@ namespace boost class real_timespec_timepoint { public: - explicit real_timespec_timepoint(boost::intmax_t const& ns) : value(ns) {} +#if defined BOOST_THREAD_PLATFORM_PTHREAD + explicit real_timespec_timepoint(timespec const& v) : dur(v) {} + inline timespec const& getTs() const { return dur.getTs(); } +#endif + + explicit real_timespec_timepoint(boost::intmax_t const& ns) : dur(ns) {} + inline boost::intmax_t getNs() const { return dur.getNs(); } #if defined BOOST_THREAD_USES_DATETIME explicit real_timespec_timepoint(boost::system_time const& abs_time) - { - boost::posix_time::time_duration const time_since_epoch = abs_time-boost::posix_time::from_time_t(0); - value = timespec_duration(time_since_epoch).getNs(); - } + : dur(abs_time - boost::posix_time::from_time_t(0)) {} #endif + #if defined BOOST_THREAD_USES_CHRONO template explicit real_timespec_timepoint(chrono::time_point const& abs_time) - { - value = timespec_duration(abs_time.time_since_epoch()).getNs(); - } + : dur(abs_time.time_since_epoch()) {} #endif -#if defined BOOST_THREAD_PLATFORM_PTHREAD - inline timespec getTs() const { return ns_to_timespec(value); } -#endif - inline boost::intmax_t getNs() const { return value; } - private: - boost::intmax_t value; + timespec_duration dur; }; inline bool operator==(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) @@ -221,7 +239,7 @@ namespace boost BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_REALTIME) Internal Error"); return real_timespec_timepoint(0); } - return real_timespec_timepoint(timespec_to_ns(ts)); + return real_timespec_timepoint(ts); #endif } }; @@ -231,27 +249,37 @@ namespace boost class mono_timespec_timepoint { public: - explicit mono_timespec_timepoint(boost::intmax_t const& ns) : value(ns) {} +#if defined BOOST_THREAD_PLATFORM_PTHREAD + explicit mono_timespec_timepoint(timespec const& v) : dur(v) {} + inline timespec const& getTs() const { return dur.getTs(); } +#endif + + explicit mono_timespec_timepoint(boost::intmax_t const& ns) : dur(ns) {} + inline boost::intmax_t getNs() const { return dur.getNs(); } #if defined BOOST_THREAD_USES_CHRONO + // This conversion assumes that chrono::steady_clock::time_point and mono_timespec_timepoint share the same epoch. template - explicit mono_timespec_timepoint(chrono::time_point const& abs_time); + explicit mono_timespec_timepoint(chrono::time_point const& abs_time) + : dur(abs_time.time_since_epoch()) {} #endif -#if defined BOOST_THREAD_PLATFORM_PTHREAD - inline timespec getTs() const { return ns_to_timespec(value); } -#endif - inline boost::intmax_t getNs() const { return value; } - // can't name this max() since that is a macro on some Windows systems static inline mono_timespec_timepoint getMax() { +#if defined BOOST_THREAD_PLATFORM_PTHREAD + timespec ts; + ts.tv_sec = (std::numeric_limits::max)(); + ts.tv_nsec = 999999999; + return mono_timespec_timepoint(ts); +#else boost::intmax_t ns = (std::numeric_limits::max)(); return mono_timespec_timepoint(ns); +#endif } private: - boost::intmax_t value; + timespec_duration dur; }; inline bool operator==(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) @@ -344,21 +372,11 @@ namespace boost BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_MONOTONIC) Internal Error"); return mono_timespec_timepoint(0); } - return mono_timespec_timepoint(timespec_to_ns(ts)); + return mono_timespec_timepoint(ts); #endif } }; -#if defined BOOST_THREAD_USES_CHRONO - 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()).getNs(); - } -#endif - #endif #if defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) diff --git a/include/boost/thread/pthread/condition_variable.hpp b/include/boost/thread/pthread/condition_variable.hpp index b283b116..7c641d30 100644 --- a/include/boost/thread/pthread/condition_variable.hpp +++ b/include/boost/thread/pthread/condition_variable.hpp @@ -111,18 +111,17 @@ namespace boost #endif int cond_res; { - const timespec ts = timeout.getTs(); #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS thread_cv_detail::lock_on_exit > guard; detail::interruption_checker check_for_interruption(&internal_mutex,&cond); pthread_mutex_t* the_mutex = &internal_mutex; guard.activate(m); - cond_res=pthread_cond_timedwait(&cond,the_mutex,&ts); + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs()); check_for_interruption.check(); guard.deactivate(); #else pthread_mutex_t* the_mutex = m.mutex()->native_handle(); - cond_res=pthread_cond_timedwait(&cond,the_mutex,ts); + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs()); #endif } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -412,8 +411,7 @@ namespace boost boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); #endif guard.activate(m); - const timespec ts = timeout.getTs(); - res=pthread_cond_timedwait(&cond,&internal_mutex,&ts); + res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout.getTs()); check_for_interruption.check(); guard.deactivate(); } diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp index 4e116ac7..8f1e9182 100644 --- a/include/boost/thread/pthread/mutex.hpp +++ b/include/boost/thread/pthread/mutex.hpp @@ -266,8 +266,7 @@ namespace boost // fixme: Shouldn't this functions be located on a .cpp file? bool do_try_lock_until(detail::internal_timespec_timepoint const &timeout) { - const timespec ts = timeout.getTs(); - int const res=pthread_mutex_timedlock(&m,&ts); + int const res=pthread_mutex_timedlock(&m,&timeout.getTs()); BOOST_ASSERT(!res || res==ETIMEDOUT); return !res; } @@ -307,10 +306,9 @@ namespace boost bool do_try_lock_until(detail::internal_timespec_timepoint const &timeout) { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); - const timespec ts = timeout.getTs(); while(is_locked) { - int const cond_res=pthread_cond_timedwait(&cond,&m,&ts); + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs()); if(cond_res==ETIMEDOUT) { return false; diff --git a/include/boost/thread/pthread/recursive_mutex.hpp b/include/boost/thread/pthread/recursive_mutex.hpp index 3a1f06ae..6a179e26 100644 --- a/include/boost/thread/pthread/recursive_mutex.hpp +++ b/include/boost/thread/pthread/recursive_mutex.hpp @@ -288,8 +288,7 @@ namespace boost // fixme: Shouldn't this functions be located on a .cpp file? bool do_try_lock_until(detail::internal_timespec_timepoint const &timeout) { - const timespec ts = timeout.getTs(); - int const res=pthread_mutex_timedlock(&m,&ts); + int const res=pthread_mutex_timedlock(&m,&timeout.getTs()); BOOST_ASSERT(!res || res==ETIMEDOUT); return !res; } @@ -348,10 +347,9 @@ namespace boost ++count; return true; } - const timespec ts = timeout.getTs(); while(is_locked) { - int const cond_res=pthread_cond_timedwait(&cond,&m,&ts); + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs()); if(cond_res==ETIMEDOUT) { return false; diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index c3a78772..ce6f9ab1 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -439,15 +439,14 @@ namespace boost { // Use pthread_delay_np or nanosleep whenever possible here in the no_interruption_point // namespace because they do not provide an interruption point. - const timespec ts2 = ts.getTs(); # if defined(BOOST_HAS_PTHREAD_DELAY_NP) # if defined(__IBMCPP__) || defined(_AIX) - BOOST_VERIFY(!pthread_delay_np(const_cast(&ts2))); + BOOST_VERIFY(!pthread_delay_np(const_cast(&ts.getTs()))); # else - BOOST_VERIFY(!pthread_delay_np(&ts2)); + BOOST_VERIFY(!pthread_delay_np(&ts.getTs())); # endif # elif defined(BOOST_HAS_NANOSLEEP) - nanosleep(&ts2, 0); + nanosleep(&ts.getTs(), 0); # else // Fall back to using a condition variable even though it does provide an interruption point. const detail::internal_timespec_timepoint ts2 = detail::internal_timespec_clock::now() + ts;