diff --git a/include/boost/thread/detail/config.hpp b/include/boost/thread/detail/config.hpp index 2987de66..6f216b27 100644 --- a/include/boost/thread/detail/config.hpp +++ b/include/boost/thread/detail/config.hpp @@ -382,6 +382,16 @@ # endif #endif +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#if defined BOOST_PTHREAD_HAS_TIMEDLOCK +#define BOOST_THREAD_USES_PTHREAD_TIMEDLOCK +#elif (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \ + || (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21) +#define BOOST_THREAD_USES_PTHREAD_TIMEDLOCK +#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 new file mode 100644 index 00000000..5a8abec1 --- /dev/null +++ b/include/boost/thread/detail/internal_clock.hpp @@ -0,0 +1,33 @@ +// Copyright (C) 2017 +// Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_DETAIL_INTERNAL_CLOCK_HPP +#define BOOST_THREAD_DETAIL_INTERNAL_CLOCK_HPP + +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#endif + +namespace boost { +namespace thread_detail { + + #ifdef BOOST_THREAD_USES_CHRONO + #if defined(BOOST_THREAD_PLATFORM_WIN32) + typedef chrono::system_clock internal_clock_t; + #elif defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) + typedef chrono::steady_clock internal_clock_t; + #else + typedef chrono::system_clock internal_clock_t; + #endif + #endif + +} // namespace thread_detail +} // namespace boost + +#endif // header diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index b91adee0..b639d0a5 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -37,6 +37,7 @@ #include #include #ifdef BOOST_THREAD_USES_CHRONO +#include #include #include #endif @@ -155,15 +156,15 @@ namespace boost }; #endif } -namespace thread_detail { -#ifdef BOOST_THREAD_USES_CHRONO -#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) - typedef chrono::steady_clock internal_clock_t; -#else - typedef chrono::system_clock internal_clock_t; -#endif -#endif -} +//namespace thread_detail { +//#ifdef BOOST_THREAD_USES_CHRONO +//#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) +// typedef chrono::steady_clock internal_clock_t; +//#else +// typedef chrono::system_clock internal_clock_t; +//#endif +//#endif +//} class BOOST_THREAD_DECL thread { public: @@ -481,13 +482,13 @@ namespace thread_detail { bool try_join_for(const chrono::duration& rel_time) { chrono::milliseconds rel_time2= chrono::ceil(rel_time); - return do_try_join_until(rel_time2.count()); + 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); + return try_join_until(thread_detail::internal_clock_t::now() + rel_time); } #endif @@ -515,7 +516,7 @@ namespace thread_detail { #if defined(BOOST_THREAD_PLATFORM_WIN32) private: bool do_try_join_until_noexcept(uintmax_t milli, bool& res); - inline bool do_try_join_until(uintmax_t milli); + inline bool do_try_join_for(uintmax_t milli); public: bool timed_join(const system_time& abs_time); //{ @@ -523,32 +524,31 @@ namespace thread_detail { //} #ifdef BOOST_THREAD_USES_CHRONO + // fixme. This shouldn't be internal_clock_t as bool try_join_until(const chrono::time_point& tp) { - chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); - return do_try_join_until(rel_time.count()); + chrono::milliseconds rel_time= chrono::ceil(tp-thread_detail::internal_clock_t::now()); + return do_try_join_for(rel_time.count()); } #endif #else private: - bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res); - inline bool do_try_join_until(struct timespec const &timeout); + bool do_try_join_until_noexcept(detail::real_timespec_timepoint const &timeout, bool& res); + inline bool do_try_join_until(detail::real_timespec_timepoint const &timeout); public: #if defined BOOST_THREAD_USES_DATETIME bool timed_join(const system_time& abs_time) { - struct timespec const ts=detail::to_timespec(abs_time); + const detail::real_timespec_timepoint ts = abs_time; return do_try_join_until(ts); } #endif #ifdef BOOST_THREAD_USES_CHRONO bool try_join_until(const chrono::time_point& tp) { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); + const boost::detail::real_timespec_timepoint ts = tp; return do_try_join_until(ts); } #endif @@ -560,6 +560,7 @@ namespace thread_detail { template inline bool timed_join(TimeDuration const& rel_time) { + // fixme: make use of internal_timespec_clock here return timed_join(get_system_time()+rel_time); } #endif @@ -778,10 +779,7 @@ namespace thread_detail { } #ifdef BOOST_THREAD_PLATFORM_PTHREAD - bool thread::do_try_join_until(struct timespec const &timeout) -#else - bool thread::do_try_join_until(uintmax_t timeout) -#endif + bool thread::do_try_join_until(detail::real_timespec_timepoint const &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")); @@ -798,6 +796,26 @@ namespace thread_detail { ); } } +#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/pthread/condition_variable.hpp b/include/boost/thread/pthread/condition_variable.hpp index 5dcb3a0e..392858fa 100644 --- a/include/boost/thread/pthread/condition_variable.hpp +++ b/include/boost/thread/pthread/condition_variable.hpp @@ -8,11 +8,14 @@ #include #include +#include + #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS #include #endif #include #ifdef BOOST_THREAD_USES_CHRONO +#include #include #include #endif @@ -97,7 +100,7 @@ namespace boost inline bool condition_variable::do_wait_until( unique_lock& m, - struct timespec const &timeout) + detail::real_timespec_timepoint const &timeout) { #if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED if (!m.owns_lock()) @@ -112,12 +115,12 @@ namespace boost 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,&timeout); + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.get()); check_for_interruption.check(); guard.deactivate(); #else pthread_mutex_t* the_mutex = m.mutex()->native_handle(); - cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.get()); #endif } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -164,11 +167,11 @@ namespace boost { boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init")); } - int const res2 = detail::monotonic_pthread_cond_init(cond); + int const res2 = pthread::cond_init(cond); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init")); + boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread::cond_init")); } } ~condition_variable_any() @@ -212,7 +215,7 @@ namespace boost template bool timed_wait(lock_type& m,boost::system_time const& abs_time) { - struct timespec const timeout=detail::to_timespec(abs_time); + detail::real_timespec_timepoint const timeout = abs_time; return do_wait_until(m, timeout); } template @@ -224,7 +227,17 @@ namespace boost template bool timed_wait(lock_type& m,duration_type const& wait_duration) { - return timed_wait(m,get_system_time()+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; + } + // fixme: make use of internal_timespec_clock here + return timed_wait(m,get_system_time()+wait_duration); } template @@ -247,6 +260,19 @@ namespace boost template bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) { + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } + // fixme: make use of internal_timespec_clock here return timed_wait(m,get_system_time()+wait_duration,pred); } #endif @@ -257,14 +283,13 @@ namespace boost cv_status wait_until( lock_type& lock, - const chrono::time_point& t) + const chrono::time_point& t) { using namespace chrono; - typedef time_point nano_sys_tmpt; - wait_until(lock, + typedef time_point nano_sys_tmpt; + return wait_until(lock, nano_sys_tmpt(ceil(t.time_since_epoch()))); - return system_clock::now() < t ? cv_status::no_timeout : - cv_status::timeout; + //return system_clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } template @@ -273,8 +298,9 @@ namespace boost lock_type& lock, const chrono::time_point& t) { + // fixme: we should iterate here until wait_until == cv_status::no_timeout or Clock::now() >= t using namespace chrono; - system_clock::time_point s_now = system_clock::now(); + thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now(); typename Clock::time_point c_now = Clock::now(); wait_until(lock, s_now + ceil(t - c_now)); return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; @@ -287,28 +313,25 @@ namespace boost const chrono::duration& d) { using namespace chrono; - system_clock::time_point s_now = system_clock::now(); - steady_clock::time_point c_now = steady_clock::now(); - wait_until(lock, s_now + ceil(d)); - return steady_clock::now() - c_now < d ? cv_status::no_timeout : - cv_status::timeout; + thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now(); + return wait_until(lock, s_now + ceil(d)); + //return steady_clock::now() - c_now < d ? cv_status::no_timeout : cv_status::timeout; } template cv_status wait_until( lock_type& lk, - chrono::time_point tp) + chrono::time_point tp) { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); + boost::detail::internal_timespec_timepoint ts = tp; if (do_wait_until(lk, ts)) return cv_status::no_timeout; else return cv_status::timeout; } #endif #else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC #ifdef BOOST_THREAD_USES_CHRONO + // todo this should be removed template cv_status @@ -355,9 +378,7 @@ namespace boost lock_type& lock, chrono::time_point tp) { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); + detail::real_timespec_timepoint ts = tp; if (do_wait_until(lock, ts)) return cv_status::no_timeout; else return cv_status::timeout; } @@ -388,7 +409,7 @@ namespace boost const chrono::duration& d, Predicate pred) { - return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + return wait_until(lock, thread_detail::internal_clock_t::now() + d, boost::move(pred)); } #endif @@ -408,7 +429,7 @@ namespace boost template bool do_wait_until( lock_type& m, - struct timespec const &timeout) + detail::real_timespec_timepoint const &timeout) { int res=0; { @@ -419,7 +440,7 @@ namespace boost boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); #endif guard.activate(m); - res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout.get()); check_for_interruption.check(); guard.deactivate(); } diff --git a/include/boost/thread/pthread/condition_variable_fwd.hpp b/include/boost/thread/pthread/condition_variable_fwd.hpp index 0ea34e23..9fdce998 100644 --- a/include/boost/thread/pthread/condition_variable_fwd.hpp +++ b/include/boost/thread/pthread/condition_variable_fwd.hpp @@ -14,11 +14,14 @@ #include #include #include +#include + #if defined BOOST_THREAD_USES_DATETIME #include #endif #ifdef BOOST_THREAD_USES_CHRONO +#include #include #include #endif @@ -29,26 +32,27 @@ namespace boost { - namespace detail { - inline int monotonic_pthread_cond_init(pthread_cond_t& cond) { - -#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC - pthread_condattr_t attr; - int res = pthread_condattr_init(&attr); - if (res) - { - return res; - } - pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); - res=pthread_cond_init(&cond,&attr); - pthread_condattr_destroy(&attr); - return res; -#else - return pthread_cond_init(&cond,NULL); -#endif - - } - } +// // todo: move to pthread_helpers.hpp and rename to internal_pthread_cond_init +// namespace detail { +// inline int monotonic_pthread_cond_init(pthread_cond_t& cond) { +// +//#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +// pthread_condattr_t attr; +// int res = pthread_condattr_init(&attr); +// if (res) +// { +// return res; +// } +// pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); +// res=pthread_cond_init(&cond,&attr); +// pthread_condattr_destroy(&attr); +// return res; +//#else +// return pthread_cond_init(&cond,NULL); +//#endif +// +// } +// } class condition_variable { @@ -63,18 +67,13 @@ namespace boost inline bool do_wait_until( unique_lock& lock, - struct timespec const &timeout); + detail::real_timespec_timepoint const &timeout); bool do_wait_for( unique_lock& lock, - struct timespec const &timeout) + detail::timespec_duration const &timeout) { -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC - return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_monotonic())); -#else - // old behavior was fine for monotonic - return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime())); -#endif + return do_wait_until(lock, timeout + detail::internal_timespec_clock::now()); } public: @@ -93,14 +92,14 @@ namespace boost boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); } //#endif - res = detail::monotonic_pthread_cond_init(cond); + res = pthread::cond_init(cond); if (res) { //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS // ditto BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); //#endif - boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread::cond_init")); } } ~condition_variable() @@ -133,12 +132,11 @@ namespace boost boost::system_time const& abs_time) { #if defined BOOST_THREAD_WAIT_BUG - struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG); - return do_wait_until(m, timeout); + detail::real_timespec_timepoint const timeout = abs_time + BOOST_THREAD_WAIT_BUG; #else - struct timespec const timeout=detail::to_timespec(abs_time); - return do_wait_until(m, timeout); + detail::real_timespec_timepoint const timeout = abs_time; #endif + return do_wait_until(m, timeout); } bool timed_wait( unique_lock& m, @@ -161,6 +159,7 @@ namespace boost { return true; } + // fixme: make use of internal_timespec_clock here return timed_wait(m,get_system_time()+wait_duration); } @@ -202,6 +201,7 @@ namespace boost { return pred(); } + // fixme: make use of internal_timespec_clock here return timed_wait(m,get_system_time()+wait_duration,pred); } #endif @@ -214,14 +214,13 @@ namespace boost cv_status wait_until( unique_lock& lock, - const chrono::time_point& t) + const chrono::time_point& t) { using namespace chrono; - typedef time_point nano_sys_tmpt; - wait_until(lock, + typedef time_point nano_sys_tmpt; + return wait_until(lock, nano_sys_tmpt(ceil(t.time_since_epoch()))); - return system_clock::now() < t ? cv_status::no_timeout : - cv_status::timeout; + //return system_clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } template @@ -230,15 +229,15 @@ namespace boost unique_lock& lock, const chrono::time_point& t) { + // fixme: we should iterate here until wait_until == cv_status::no_timeout or Clock::now() >= t using namespace chrono; - system_clock::time_point s_now = system_clock::now(); + thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now(); typename Clock::time_point c_now = Clock::now(); wait_until(lock, s_now + ceil(t - c_now)); return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } - template cv_status wait_for( @@ -246,21 +245,17 @@ namespace boost const chrono::duration& d) { using namespace chrono; - system_clock::time_point s_now = system_clock::now(); - steady_clock::time_point c_now = steady_clock::now(); - wait_until(lock, s_now + ceil(d)); - return steady_clock::now() - c_now < d ? cv_status::no_timeout : - cv_status::timeout; + thread_detail::internal_clock_t::time_point c_now = thread_detail::internal_clock_t::now(); + return wait_until(lock, c_now + ceil(d)); + //return steady_clock::now() - c_now < d ? cv_status::no_timeout : cv_status::timeout; } inline cv_status wait_until( unique_lock& lk, - chrono::time_point tp) + chrono::time_point tp) { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); + const boost::detail::internal_timespec_timepoint ts = tp; if (do_wait_until(lk, ts)) return cv_status::no_timeout; else return cv_status::timeout; } @@ -268,19 +263,19 @@ namespace boost #else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC #ifdef BOOST_THREAD_USES_CHRONO + // todo this should be removed with the if BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC as is the same template cv_status wait_until( unique_lock& lock, - const chrono::time_point& t) + const chrono::time_point& t) { using namespace chrono; - typedef time_point nano_sys_tmpt; - wait_until(lock, + typedef time_point nano_sys_tmpt; + return wait_until(lock, nano_sys_tmpt(ceil(t.time_since_epoch()))); - return steady_clock::now() < t ? cv_status::no_timeout : - cv_status::timeout; + //return thread_detail::internal_clock_t::now() < t ? cv_status::no_timeout : cv_status::timeout; } template @@ -289,8 +284,9 @@ namespace boost unique_lock& lock, const chrono::time_point& t) { + // fixme: we should iterate here until wait_until == cv_status::no_timeout or Clock::now() >= t using namespace chrono; - steady_clock::time_point s_now = steady_clock::now(); + thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now(); typename Clock::time_point c_now = Clock::now(); wait_until(lock, s_now + ceil(t - c_now)); return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; @@ -303,19 +299,16 @@ namespace boost const chrono::duration& d) { using namespace chrono; - steady_clock::time_point c_now = steady_clock::now(); - wait_until(lock, c_now + ceil(d)); - return steady_clock::now() - c_now < d ? cv_status::no_timeout : - cv_status::timeout; + thread_detail::internal_clock_t::time_point c_now = thread_detail::internal_clock_t::now(); + return wait_until(lock, c_now + ceil(d)); + //return steady_clock::now() - c_now < d ? cv_status::no_timeout : cv_status::timeout; } inline cv_status wait_until( unique_lock& lk, - chrono::time_point tp) + chrono::time_point tp) { - using namespace chrono; - nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); + boost::detail::internal_timespec_timepoint ts = tp; if (do_wait_until(lk, ts)) return cv_status::no_timeout; else return cv_status::timeout; } @@ -346,7 +339,7 @@ namespace boost const chrono::duration& d, Predicate pred) { - return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + return wait_until(lock, thread_detail::internal_clock_t::now() + d, boost::move(pred)); } #endif diff --git a/include/boost/thread/pthread/mutex.hpp b/include/boost/thread/pthread/mutex.hpp index 9ac808b6..23ead8ff 100644 --- a/include/boost/thread/pthread/mutex.hpp +++ b/include/boost/thread/pthread/mutex.hpp @@ -16,24 +16,21 @@ #include #endif #include +#if defined BOOST_THREAD_USES_DATETIME #include +#endif #include #include #include #include +#include #ifdef BOOST_THREAD_USES_CHRONO +#include #include #include #endif #include -#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \ - || (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21) -#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK -#define BOOST_PTHREAD_HAS_TIMEDLOCK -#endif -#endif - #include @@ -165,7 +162,7 @@ namespace boost { private: pthread_mutex_t m; -#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK pthread_cond_t cond; bool is_locked; #endif @@ -178,13 +175,13 @@ namespace boost { boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init")); } -#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK - int const res2=pthread_cond_init(&cond,NULL); +#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK + int const res2=pthread::cond_init(cond); if(res2) { BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); //BOOST_VERIFY(!pthread_mutex_destroy(&m)); - boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init")); + boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread::cond_init")); } is_locked=false; #endif @@ -192,7 +189,7 @@ namespace boost ~timed_mutex() { BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); -#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK BOOST_VERIFY(!pthread_cond_destroy(&cond)); #endif } @@ -201,6 +198,7 @@ namespace boost template bool timed_lock(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock(get_system_time()+relative_time); } bool timed_lock(boost::xtime const & absolute_time) @@ -208,7 +206,7 @@ namespace boost return timed_lock(system_time(absolute_time)); } #endif -#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK +#ifdef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK void lock() { int res = posix::pthread_mutex_lock(&m); @@ -246,9 +244,9 @@ namespace boost private: - bool do_try_lock_until(struct timespec const &timeout) + bool do_try_lock_until(detail::real_timespec_timepoint const &timeout) { - int const res=pthread_mutex_timedlock(&m,&timeout); + int const res=pthread_mutex_timedlock(&m,&timeout.get()); BOOST_ASSERT(!res || res==ETIMEDOUT); return !res; } @@ -284,12 +282,12 @@ namespace boost } private: - bool do_try_lock_until(struct timespec const &timeout) + bool do_try_lock_until(detail::real_timespec_timepoint const &timeout) { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); while(is_locked) { - int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout); + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.get()); if(cond_res==ETIMEDOUT) { return false; @@ -305,7 +303,7 @@ namespace boost #if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const & abs_time) { - struct timespec const ts=boost::detail::to_timespec(abs_time); + detail::internal_timespec_timepoint const ts = abs_time; return do_try_lock_until(ts); } #endif @@ -313,28 +311,27 @@ namespace boost template bool try_lock_for(const chrono::duration& rel_time) { - return try_lock_until(chrono::steady_clock::now() + rel_time); + return try_lock_until(thread_detail::internal_clock_t::now() + rel_time); } template bool try_lock_until(const chrono::time_point& t) { + // fixme: we should iterate here until wait_until == cv_status::no_timeout or Clock::now() >= t using namespace chrono; - system_clock::time_point s_now = system_clock::now(); + thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now(); typename Clock::time_point c_now = Clock::now(); return try_lock_until(s_now + ceil(t - c_now)); } template - bool try_lock_until(const chrono::time_point& t) + bool try_lock_until(const chrono::time_point& t) { using namespace chrono; - typedef time_point nano_sys_tmpt; + typedef time_point nano_sys_tmpt; return try_lock_until(nano_sys_tmpt(ceil(t.time_since_epoch()))); } - bool try_lock_until(const chrono::time_point& tp) + bool try_lock_until(const chrono::time_point& tp) { - //using namespace chrono; - chrono::nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); + detail::internal_timespec_timepoint ts = tp; return do_try_lock_until(ts); } #endif diff --git a/include/boost/thread/pthread/pthread_helpers.hpp b/include/boost/thread/pthread/pthread_helpers.hpp new file mode 100644 index 00000000..a99405a7 --- /dev/null +++ b/include/boost/thread/pthread/pthread_helpers.hpp @@ -0,0 +1,42 @@ +#ifndef BOOST_THREAD_PTHREAD_PTHREAD_HELPERS_HPP +#define BOOST_THREAD_PTHREAD_PTHREAD_HELPERS_HPP +// Copyright (C) 2017 +// Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include + +namespace boost +{ + namespace pthread + { + inline int cond_init(pthread_cond_t& cond) { + + #ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + pthread_condattr_t attr; + int res = pthread_condattr_init(&attr); + if (res) + { + return res; + } + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + res=pthread_cond_init(&cond,&attr); + pthread_condattr_destroy(&attr); + return res; + #else + return pthread_cond_init(&cond,NULL); + #endif + + } + } +} + +#include + +#endif diff --git a/include/boost/thread/pthread/recursive_mutex.hpp b/include/boost/thread/pthread/recursive_mutex.hpp index 4caae0b5..f81841f4 100644 --- a/include/boost/thread/pthread/recursive_mutex.hpp +++ b/include/boost/thread/pthread/recursive_mutex.hpp @@ -21,25 +21,21 @@ #include #include #include +#include #ifdef BOOST_THREAD_USES_CHRONO +#include #include #include #endif #include -#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \ - || (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21) -#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK -#define BOOST_PTHREAD_HAS_TIMEDLOCK -#endif -#endif #if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \ || defined __ANDROID__ #define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE #endif -#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK +#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_THREAD_USES_PTHREAD_TIMEDLOCK #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK #endif @@ -89,11 +85,11 @@ namespace boost { boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init")); } - int const res2=pthread_cond_init(&cond,NULL); + int const res2=pthread::cond_init(cond); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&m)); - boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init")); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread::cond_init")); } is_locked=false; count=0; @@ -224,11 +220,11 @@ namespace boost { boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init")); } - int const res2=pthread_cond_init(&cond,NULL); + int const res2=pthread::cond_init(cond); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&m)); - boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init")); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread::cond_init")); } is_locked=false; count=0; @@ -246,6 +242,7 @@ namespace boost template bool timed_lock(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock(get_system_time()+relative_time); } #endif @@ -268,9 +265,9 @@ namespace boost return !res; } private: - bool do_try_lock_until(struct timespec const &timeout) + bool do_try_lock_until(detail::real_timespec_timepoint const &timeout) { - int const res=pthread_mutex_timedlock(&m,&timeout); + int const res=pthread_mutex_timedlock(&m,&timeout.get()); BOOST_ASSERT(!res || res==ETIMEDOUT); return !res; } @@ -320,7 +317,7 @@ namespace boost } private: - bool do_try_lock_until(struct timespec const &timeout) + bool do_try_lock_until(detail::internal_timespec_timepoint const &timeout) { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); if(is_locked && pthread_equal(owner,pthread_self())) @@ -330,7 +327,7 @@ namespace boost } while(is_locked) { - int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout); + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.get()); if(cond_res==ETIMEDOUT) { return false; @@ -349,7 +346,8 @@ namespace boost #if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const & abs_time) { - struct timespec const ts=detail::to_timespec(abs_time); + // fixme + detail::internal_timespec_timepoint const ts = abs_time; return do_try_lock_until(ts); } #endif @@ -357,28 +355,26 @@ namespace boost template bool try_lock_for(const chrono::duration& rel_time) { - return try_lock_until(chrono::steady_clock::now() + rel_time); + return try_lock_until(thread_detail::internal_clock_t::now() + rel_time); } template bool try_lock_until(const chrono::time_point& t) { using namespace chrono; - system_clock::time_point s_now = system_clock::now(); + thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now(); typename Clock::time_point c_now = Clock::now(); return try_lock_until(s_now + ceil(t - c_now)); } template - bool try_lock_until(const chrono::time_point& t) + bool try_lock_until(const chrono::time_point& t) { using namespace chrono; - typedef time_point nano_sys_tmpt; + typedef time_point nano_sys_tmpt; return try_lock_until(nano_sys_tmpt(ceil(t.time_since_epoch()))); } - bool try_lock_until(const chrono::time_point& tp) + bool try_lock_until(const chrono::time_point& tp) { - //using namespace chrono; - chrono::nanoseconds d = tp.time_since_epoch(); - timespec ts = boost::detail::to_timespec(d); + detail::internal_timespec_timepoint ts = tp; return do_try_lock_until(ts); } #endif diff --git a/include/boost/thread/pthread/shared_mutex.hpp b/include/boost/thread/pthread/shared_mutex.hpp index e4ec24fe..9c692a3b 100644 --- a/include/boost/thread/pthread/shared_mutex.hpp +++ b/include/boost/thread/pthread/shared_mutex.hpp @@ -226,6 +226,7 @@ namespace boost template bool timed_lock_shared(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock_shared(get_system_time()+relative_time); } #endif @@ -324,6 +325,7 @@ namespace boost template bool timed_lock(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock(get_system_time()+relative_time); } #endif @@ -426,6 +428,7 @@ namespace boost template bool timed_lock_upgrade(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock_upgrade(get_system_time()+relative_time); } #endif diff --git a/include/boost/thread/pthread/thread_data.hpp b/include/boost/thread/pthread/thread_data.hpp index 41563ebc..d7768975 100644 --- a/include/boost/thread/pthread/thread_data.hpp +++ b/include/boost/thread/pthread/thread_data.hpp @@ -243,8 +243,8 @@ namespace boost { namespace hidden { - void BOOST_THREAD_DECL sleep_for(const timespec& ts); - void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts); + void BOOST_THREAD_DECL sleep_for(const detail::timespec_duration& ts); + void BOOST_THREAD_DECL sleep_until_realtime(const detail::real_timespec_timepoint& ts); } #ifdef BOOST_THREAD_USES_CHRONO @@ -255,7 +255,7 @@ namespace boost inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) { - return boost::this_thread::hidden::sleep_for(boost::detail::to_timespec(ns)); + return boost::this_thread::hidden::sleep_for(detail::timespec_duration(ns)); } #endif #endif // BOOST_THREAD_USES_CHRONO @@ -264,8 +264,8 @@ namespace boost { namespace hidden { - void BOOST_THREAD_DECL sleep_for(const timespec& ts); - void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts); + void BOOST_THREAD_DECL sleep_for(const detail::timespec_duration& ts); + void BOOST_THREAD_DECL sleep_until_realtime(const detail::real_timespec_timepoint& ts); } #ifdef BOOST_THREAD_USES_CHRONO @@ -276,7 +276,7 @@ namespace boost inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) { - return boost::this_thread::no_interruption_point::hidden::sleep_for(boost::detail::to_timespec(ns)); + return boost::this_thread::no_interruption_point::hidden::sleep_for(detail::timespec_duration(ns)); } #endif #endif // BOOST_THREAD_USES_CHRONO @@ -292,13 +292,14 @@ namespace boost #endif inline void sleep(system_time const& abs_time) { - return boost::this_thread::hidden::sleep_until_realtime(boost::detail::to_timespec(abs_time)); + boost::this_thread::hidden::sleep_until_realtime(detail::real_timespec_timepoint(abs_time)); } template inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { - this_thread::sleep(get_system_time()+rel_time); + // fixme: make use of internal_timespec_clock here + this_thread::sleep(get_system_time()+rel_time); } #endif // BOOST_THREAD_USES_DATETIME } // this_thread diff --git a/include/boost/thread/pthread/timespec.hpp b/include/boost/thread/pthread/timespec.hpp index 1fb8de94..c24248d0 100644 --- a/include/boost/thread/pthread/timespec.hpp +++ b/include/boost/thread/pthread/timespec.hpp @@ -18,6 +18,7 @@ #endif #ifdef BOOST_THREAD_USES_CHRONO #include +#include #endif #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) @@ -33,29 +34,8 @@ namespace boost { namespace detail { -#if defined BOOST_THREAD_USES_DATETIME - inline struct timespec to_timespec(boost::system_time const& abs_time) - { - struct timespec timeout = { 0,0}; - boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); - timeout.tv_sec=time_since_epoch.total_seconds(); - timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); - return timeout; - } -#endif -#if defined BOOST_THREAD_USES_CHRONO - inline timespec to_timespec(chrono::nanoseconds const& ns) - { - struct timespec ts; - ts.tv_sec = static_cast(chrono::duration_cast(ns).count()); - ts.tv_nsec = static_cast((ns - chrono::duration_cast(ns)).count()); - return ts; - } - -#endif - - inline timespec to_timespec(boost::intmax_t const& ns) + inline timespec int_to_timespec(boost::intmax_t const& ns) { boost::intmax_t s = ns / 1000000000l; struct timespec ts; @@ -67,68 +47,235 @@ namespace boost { return static_cast(ts.tv_sec) * 1000000000l + ts.tv_nsec; } - inline bool timespec_ge_zero(timespec const& ts) - { - return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0); - } -#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC - inline timespec timespec_now_monotonic() + class timespec_duration + { + public: + explicit timespec_duration(timespec const& v) : value(v) {} + +#if defined BOOST_THREAD_USES_CHRONO + timespec_duration(chrono::nanoseconds const& ns) + { + struct timespec d = { 0, 0 }; + d.tv_sec = static_cast(chrono::duration_cast(ns).count()); + d.tv_nsec = static_cast((ns - chrono::duration_cast(ns)).count()); + value = d; + } +#endif + timespec& get() { return value; } + timespec const& get() const { return value; } + + static inline timespec_duration zero() + { + timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + return timespec_duration(ts); + } + private: + timespec value; + }; + + inline bool operator==(timespec_duration const& lhs, timespec_duration const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) == to_nanoseconds_int_max(rhs.get()); + } + inline bool operator!=(timespec_duration const& lhs, timespec_duration const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) != to_nanoseconds_int_max(rhs.get()); + } + inline bool operator<(timespec_duration const& lhs, timespec_duration const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) < to_nanoseconds_int_max(rhs.get()); + } + inline bool operator<=(timespec_duration const& lhs, timespec_duration const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) <= to_nanoseconds_int_max(rhs.get()); + } + inline bool operator>(timespec_duration const& lhs, timespec_duration const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) > to_nanoseconds_int_max(rhs.get()); + } + inline bool operator>=(timespec_duration const& lhs, timespec_duration const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) >= to_nanoseconds_int_max(rhs.get()); + } + + class real_timespec_timepoint + { + public: + explicit real_timespec_timepoint(timespec const& v) : value(v) {} + +#if defined BOOST_THREAD_USES_DATETIME + 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); + + struct timespec t = { 0, 0 }; + t.tv_sec = time_since_epoch.total_seconds(); + t.tv_nsec = (long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); + value = t; + } +#endif +#if defined BOOST_THREAD_USES_CHRONO + real_timespec_timepoint(chrono::time_point const& abs_time) + { + using namespace chrono; + nanoseconds ns = abs_time.time_since_epoch(); + struct timespec d = { 0, 0 }; + d.tv_sec = static_cast(chrono::duration_cast(ns).count()); + d.tv_nsec = static_cast((ns - chrono::duration_cast(ns)).count()); + value = d; + + } +#endif + + timespec& get() { return value; } + timespec const& get() const { return value; } + private: + timespec value; + }; + + inline bool operator==(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) == to_nanoseconds_int_max(rhs.get()); + } + inline bool operator!=(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) != to_nanoseconds_int_max(rhs.get()); + } + inline bool operator<(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) < to_nanoseconds_int_max(rhs.get()); + } + inline bool operator<=(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) <= to_nanoseconds_int_max(rhs.get()); + } + inline bool operator>(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) > to_nanoseconds_int_max(rhs.get()); + } + inline bool operator>=(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) >= to_nanoseconds_int_max(rhs.get()); + } + + inline real_timespec_timepoint operator+(real_timespec_timepoint const& lhs, timespec_duration const& rhs) + { + // fixme: replace by to_timespec_duration + return real_timespec_timepoint(int_to_timespec(to_nanoseconds_int_max(lhs.get()) + to_nanoseconds_int_max(rhs.get()))); + } + inline real_timespec_timepoint operator+(timespec_duration const& lhs, real_timespec_timepoint const& rhs) + { + // fixme: replace by to_timespec_duration + return real_timespec_timepoint(int_to_timespec(to_nanoseconds_int_max(lhs.get()) + to_nanoseconds_int_max(rhs.get()))); + } + inline timespec_duration operator-(real_timespec_timepoint const& lhs, real_timespec_timepoint const& rhs) + { + // fixme: replace by to_timespec_duration + return timespec_duration(int_to_timespec(to_nanoseconds_int_max(lhs.get()) - to_nanoseconds_int_max(rhs.get()))); + } + + struct real_timespec_clock + { + static inline real_timespec_timepoint now() + { + timespec ts; + + #if defined(BOOST_THREAD_TIMESPEC_MAC_API) + timeval tv; + ::gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + #else + if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) + { + ts.tv_sec = 0; + ts.tv_nsec = 0; + BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); + } + #endif + return real_timespec_timepoint(ts); + } + }; + +#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + class mono_timespec_timepoint + { + public: + explicit mono_timespec_timepoint(timespec const& v) : value(v) {} + + timespec& get() { return value; } + timespec const& get() const { return value; } + private: + timespec value; + }; + + inline bool operator==(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) == to_nanoseconds_int_max(rhs.get()); + } + inline bool operator!=(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) != to_nanoseconds_int_max(rhs.get()); + } + inline bool operator<(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) < to_nanoseconds_int_max(rhs.get()); + } + inline bool operator<=(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) <= to_nanoseconds_int_max(rhs.get()); + } + inline bool operator>(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) > to_nanoseconds_int_max(rhs.get()); + } + inline bool operator>=(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) + { + return to_nanoseconds_int_max(lhs.get()) >= to_nanoseconds_int_max(rhs.get()); + } + + inline mono_timespec_timepoint operator+(mono_timespec_timepoint const& lhs, timespec_duration const& rhs) + { + // fixme: replace by to_timespec_duration + return mono_timespec_timepoint(int_to_timespec(to_nanoseconds_int_max(lhs.get()) + to_nanoseconds_int_max(rhs.get()))); + } + inline mono_timespec_timepoint operator+(timespec_duration const& lhs, mono_timespec_timepoint const& rhs) + { + // fixme: replace by to_timespec_duration + return mono_timespec_timepoint(int_to_timespec(to_nanoseconds_int_max(lhs.get()) + to_nanoseconds_int_max(rhs.get()))); + } + inline timespec_duration operator-(mono_timespec_timepoint const& lhs, mono_timespec_timepoint const& rhs) + { + // fixme: replace by to_timespec_duration + return timespec_duration(int_to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs))); + } + + struct mono_timespec_clock + { + static inline mono_timespec_timepoint now() { timespec ts; - if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) ) { ts.tv_sec = 0; ts.tv_nsec = 0; BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); } - return ts; + return mono_timespec_timepoint(ts); } + }; #endif - inline timespec timespec_now_realtime() - { - timespec ts; - -#if defined(BOOST_THREAD_TIMESPEC_MAC_API) - timeval tv; - ::gettimeofday(&tv, 0); - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; +#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + typedef mono_timespec_clock internal_timespec_clock; + typedef mono_timespec_timepoint internal_timespec_timepoint; #else - if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) - { - ts.tv_sec = 0; - ts.tv_nsec = 0; - BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); - } + typedef real_timespec_clock internal_timespec_clock; + typedef real_timespec_timepoint internal_timespec_timepoint; #endif - return ts; - } - inline timespec timespec_zero() - { - timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 0; - return ts; - } - inline timespec timespec_plus(timespec const& lhs, timespec const& rhs) - { - return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs)); - } - inline timespec timespec_minus(timespec const& lhs, timespec const& rhs) - { - return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs)); - } - inline bool timespec_gt(timespec const& lhs, timespec const& rhs) - { - return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs); - } - inline bool timespec_ge(timespec const& lhs, timespec const& rhs) - { - return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs); - } } } diff --git a/include/boost/thread/v2/shared_mutex.hpp b/include/boost/thread/v2/shared_mutex.hpp index 5acab4d8..96bdc583 100755 --- a/include/boost/thread/v2/shared_mutex.hpp +++ b/include/boost/thread/v2/shared_mutex.hpp @@ -227,12 +227,14 @@ namespace boost { template bool timed_lock(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock(get_system_time()+relative_time); } bool timed_lock_shared(system_time const& timeout); template bool timed_lock_shared(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock_shared(get_system_time()+relative_time); } #endif @@ -498,18 +500,21 @@ namespace boost { template bool timed_lock(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock(get_system_time()+relative_time); } inline bool timed_lock_shared(system_time const& abs_time); template bool timed_lock_shared(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock_shared(get_system_time()+relative_time); } inline bool timed_lock_upgrade(system_time const& abs_time); template bool timed_lock_upgrade(TimeDuration const & relative_time) { + // fixme: make use of internal_timespec_clock here return timed_lock_upgrade(get_system_time()+relative_time); } #endif diff --git a/include/boost/thread/win32/condition_variable.hpp b/include/boost/thread/win32/condition_variable.hpp index 7f670bb9..9edbb032 100644 --- a/include/boost/thread/win32/condition_variable.hpp +++ b/include/boost/thread/win32/condition_variable.hpp @@ -89,9 +89,9 @@ namespace boost return notified; } - bool wait(timeout abs_time) + bool wait(timeout abs_or_rel_time) { - return this_thread::interruptible_wait(semaphore,abs_time); + return this_thread::interruptible_wait(semaphore,abs_or_rel_time); } bool woken() @@ -233,7 +233,7 @@ namespace boost protected: template - bool do_wait(lock_type& lock,timeout abs_time) + bool do_wait(lock_type& lock,timeout abs_or_rel_time) { relocker locker(lock); entry_manager entry(get_wait_entry(), internal_mutex); @@ -242,7 +242,7 @@ namespace boost bool woken=false; while(!woken) { - if(!entry->wait(abs_time)) + if(!entry->wait(abs_or_rel_time)) { return false; } @@ -256,11 +256,11 @@ namespace boost } template - bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred) + bool do_wait(lock_type& m,timeout const& abs_or_rel_time,predicate_type pred) { while (!pred()) { - if(!do_wait(m, abs_time)) + if(!do_wait(m, abs_or_rel_time)) return pred(); } return true; diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index 5e51f8ea..7994b165 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -350,7 +350,7 @@ namespace boost } } - bool thread::do_try_join_until_noexcept(struct timespec const &timeout, bool& res) + bool thread::do_try_join_until_noexcept(detail::real_timespec_timepoint const &timeout, bool& res) { detail::thread_data_ptr const local_thread_info=(get_thread_info)(); if(local_thread_info) @@ -432,22 +432,21 @@ namespace boost { namespace hidden { - void BOOST_THREAD_DECL sleep_for(const timespec& ts) + void BOOST_THREAD_DECL sleep_for(const detail::timespec_duration& ts) { - if (boost::detail::timespec_ge(ts, boost::detail::timespec_zero())) + if (ts >= detail::timespec_duration::zero()) { - # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) && !defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) # if defined(__IBMCPP__) || defined(_AIX) - BOOST_VERIFY(!pthread_delay_np(const_cast(&ts))); + BOOST_VERIFY(!pthread_delay_np(const_cast(&ts.get()))); # else - BOOST_VERIFY(!pthread_delay_np(&ts)); + BOOST_VERIFY(!pthread_delay_np(&ts.get())); # endif - # elif defined(BOOST_HAS_NANOSLEEP) - // nanosleep takes a timespec that is an offset, not - // an absolute time. - nanosleep(&ts, 0); + # elif defined(BOOST_HAS_NANOSLEEP) && !defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) + nanosleep(&ts.get(), 0); # else mutex mx; unique_lock lock(mx); @@ -457,30 +456,28 @@ namespace boost } } - void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts) + void BOOST_THREAD_DECL sleep_until_realtime(const detail::real_timespec_timepoint& ts) { - timespec now = boost::detail::timespec_now_realtime(); - if (boost::detail::timespec_gt(ts, now)) + detail::real_timespec_timepoint now = detail::real_timespec_clock::now(); + if (ts > now) { for (int foo=0; foo < 5; ++foo) { # if defined(BOOST_HAS_PTHREAD_DELAY_NP) - timespec d = boost::detail::timespec_minus(ts, now); - BOOST_VERIFY(!pthread_delay_np(&d)); + detail::timespec_duration d = ts - now; + BOOST_VERIFY(!pthread_delay_np(&d.get())); # elif defined(BOOST_HAS_NANOSLEEP) - // nanosleep takes a timespec that is an offset, not - // an absolute time. - timespec d = boost::detail::timespec_minus(ts, now); - nanosleep(&d, 0); + detail::timespec_duration d = ts - now; + nanosleep(&d.get(), 0); # else mutex mx; unique_lock lock(mx); condition_variable cond; cond.do_wait_until(lock, ts); # endif - timespec now2 = boost::detail::timespec_now_realtime(); - if (boost::detail::timespec_ge(now2, ts)) + detail::real_timespec_timepoint now2 = detail::real_timespec_clock::now(); + if (now2 >= ts) { return; } @@ -491,7 +488,7 @@ namespace boost } namespace hidden { - void BOOST_THREAD_DECL sleep_for(const timespec& ts) + void BOOST_THREAD_DECL sleep_for(const detail::timespec_duration& ts) { boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); @@ -506,7 +503,7 @@ namespace boost } } - void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts) + void BOOST_THREAD_DECL sleep_until_realtime(const detail::real_timespec_timepoint& ts) { boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); @@ -538,10 +535,10 @@ namespace boost // sleep_for(chrono::milliseconds(0)); # else #error - timespec ts; - ts.tv_sec= 0; - ts.tv_nsec= 0; - hidden::sleep_for(ts); +// 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 988ee416..44813d59 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -462,10 +462,10 @@ namespace boost #if defined BOOST_THREAD_USES_DATETIME bool thread::timed_join(boost::system_time const& wait_until) { - return do_try_join_until(boost::detail::get_milliseconds_until(wait_until)); + return do_try_join_for(boost::detail::get_milliseconds_until(wait_until)); } #endif - bool thread::do_try_join_until_noexcept(uintmax_t milli, bool& res) + bool thread::do_try_join_for_noexcept(uintmax_t milli, bool& res) { detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info)