diff --git a/include/boost/thread/v2/thread.hpp b/include/boost/thread/v2/thread.hpp index de84512f..245c7c50 100644 --- a/include/boost/thread/v2/thread.hpp +++ b/include/boost/thread/v2/thread.hpp @@ -23,6 +23,7 @@ namespace boost { #ifdef BOOST_THREAD_USES_CHRONO +#if !defined BOOST_THREAD_SLEEP_FOR_IS_STEADY template void sleep_until(const chrono::time_point& t) { @@ -47,7 +48,11 @@ namespace boost d = t - Clock::now(); } } -#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#endif + +// Use pthread_delay_np or nanosleep whenever possible here in the no_interruption_point +// namespace because they do not provide an interruption point. +#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY template void sleep_for(const chrono::duration& d) @@ -76,6 +81,20 @@ namespace boost using namespace chrono; sleep_for(t - steady_clock::now()); } + + template + void sleep_until(const chrono::time_point& t) + { + using namespace chrono; + Duration d = t - Clock::now(); + while (d > Duration::zero()) + { + Duration d100 = (std::min)(d, Duration(milliseconds(100))); + sleep_for(d100); + d = t - Clock::now(); + } + } + #else template void sleep_for(const chrono::duration& d) @@ -117,38 +136,6 @@ namespace boost d = t - Clock::now(); } } - -#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY && !defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC - - template - void sleep_for(const chrono::duration& d) - { - using namespace chrono; - if (d > duration::zero()) - { - const duration Max = (nanoseconds::max)(); - nanoseconds ns; - if (d < Max) - { - ns = ceil(d); - } - else - { - // fixme: it is normal to sleep less than requested? Shouldn't we need to iterate until d has been elapsed? - ns = (nanoseconds::max)(); - } - sleep_for(ns); - } - } - - template - inline BOOST_SYMBOL_VISIBLE - void sleep_until(const chrono::time_point& t) - { - using namespace chrono; - sleep_for(t - steady_clock::now()); - } -#else template void sleep_for(const chrono::duration& d) { @@ -159,7 +146,6 @@ namespace boost } } -#endif #endif } } diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index ace00fa3..504230c9 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -437,25 +437,23 @@ namespace boost if (ts > detail::timespec_duration::zero()) { - # if defined(BOOST_HAS_PTHREAD_DELAY_NP) && !defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) + // Use pthread_delay_np or nanosleep whenever possible here in the no_interruption_point + // namespace because they do not provide an interruption point. + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) # if defined(__IBMCPP__) || defined(_AIX) BOOST_VERIFY(!pthread_delay_np(const_cast(&ts.get()))); # else BOOST_VERIFY(!pthread_delay_np(&ts.get())); # endif - # elif defined(BOOST_HAS_NANOSLEEP) && !defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) + # elif defined(BOOST_HAS_NANOSLEEP) nanosleep(&ts.get(), 0); - # elif defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) + # 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; mutex mx; unique_lock lock(mx); condition_variable cond; while (cond.do_wait_until(lock, ts2)) {} - # else - mutex mx; - unique_lock lock(mx); - condition_variable cond; - cond.do_wait_for(lock, ts); # endif } } @@ -493,21 +491,11 @@ namespace boost { void BOOST_THREAD_DECL sleep_for(const detail::timespec_duration& ts) { -#if 0 - boost::this_thread::no_interruption_point::hidden::sleep_for(ts); -#else // VBE - boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); - - if(thread_info) - { - unique_lock lk(thread_info->sleep_mutex); - while( thread_info->sleep_condition.do_wait_for(lk,ts)) {} - } - else - { - boost::this_thread::no_interruption_point::hidden::sleep_for(ts); - } -#endif + const detail::internal_timespec_timepoint& ts2 = detail::internal_timespec_clock::now() + ts; + mutex mx; + unique_lock lock(mx); + condition_variable cond; + while (cond.do_wait_until(lock, ts2)) {} } void BOOST_THREAD_DECL sleep_until(const detail::internal_timespec_timepoint& ts)