diff options
Diffstat (limited to 'boost/thread/pthread/thread_data.hpp')
-rw-r--r-- | boost/thread/pthread/thread_data.hpp | 161 |
1 files changed, 126 insertions, 35 deletions
diff --git a/boost/thread/pthread/thread_data.hpp b/boost/thread/pthread/thread_data.hpp index f6575f1c22..859ccfbd2a 100644 --- a/boost/thread/pthread/thread_data.hpp +++ b/boost/thread/pthread/thread_data.hpp @@ -16,6 +16,7 @@ #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/assert.hpp> +#include <boost/thread/detail/platform_time.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> #endif @@ -111,8 +112,6 @@ namespace boost pthread_t thread_handle; boost::mutex data_mutex; boost::condition_variable done_condition; - boost::mutex sleep_mutex; - boost::condition_variable sleep_condition; bool done; bool join_started; bool joined; @@ -241,66 +240,158 @@ namespace boost namespace this_thread { + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; + namespace hidden { - void BOOST_THREAD_DECL sleep_for(const timespec& ts); - void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts); + inline bool always_false() + { + return false; + } + } + +#if defined BOOST_THREAD_USES_DATETIME +#ifdef __DECXXX + /// Workaround of DECCXX issue of incorrect template substitution + template<> +#endif + inline void sleep(system_time const& abs_time) + { + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.timed_wait(lock, abs_time, hidden::always_false); } + template<typename TimeDuration> + void sleep(TimeDuration const& rel_time) + { + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.timed_wait(lock, rel_time, hidden::always_false); + } +#endif + #ifdef BOOST_THREAD_USES_CHRONO - template <class Rep, class Period> - void sleep_for(const chrono::duration<Rep, Period>& d); -#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + template <class Clock, class Duration> + void sleep_until(const chrono::time_point<Clock, Duration>& t) + { + mutex mut; + unique_lock<mutex> lk(mut); + condition_variable cv; + cv.wait_until(lk, t, hidden::always_false); + } - inline - void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + template <class Rep, class Period> + void sleep_for(const chrono::duration<Rep, Period>& d) { - return boost::this_thread::hidden::sleep_for(boost::detail::to_timespec(ns)); + mutex mut; + unique_lock<mutex> lk(mut); + condition_variable cv; + cv.wait_for(lk, d, hidden::always_false); } #endif -#endif // BOOST_THREAD_USES_CHRONO namespace no_interruption_point { +#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY +// Use pthread_delay_np or nanosleep when available +// because they do not provide an interruption point. + 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_internal(const detail::platform_duration& ts); } - #ifdef BOOST_THREAD_USES_CHRONO +#if defined BOOST_THREAD_USES_DATETIME +#ifdef __DECXXX + /// Workaround of DECCXX issue of incorrect template substitution + template<> +#endif + inline void sleep(system_time const& abs_time) + { + const detail::real_platform_timepoint ts(abs_time); + detail::platform_duration d(ts - detail::real_platform_clock::now()); + while (d > detail::platform_duration::zero()) + { + d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)); + hidden::sleep_for_internal(d); + d = ts - detail::real_platform_clock::now(); + } + } + + template<typename TimeDuration> + void sleep(TimeDuration const& rel_time) + { + hidden::sleep_for_internal(detail::platform_duration(rel_time)); + } +#endif + +#ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> - void sleep_for(const chrono::duration<Rep, Period>& d); - #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + void sleep_for(const chrono::duration<Rep, Period>& d) + { + hidden::sleep_for_internal(detail::platform_duration(d)); + } - inline - void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + template <class Duration> + void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t) { - return boost::this_thread::no_interruption_point::hidden::sleep_for(boost::detail::to_timespec(ns)); + sleep_for(t - chrono::steady_clock::now()); } - #endif - #endif // BOOST_THREAD_USES_CHRONO - } // no_interruption_point + template <class Clock, class Duration> + void sleep_until(const chrono::time_point<Clock, Duration>& t) + { + typedef typename common_type<Duration, typename Clock::duration>::type common_duration; + common_duration d(t - Clock::now()); + while (d > common_duration::zero()) + { + d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS))); + hidden::sleep_for_internal(detail::platform_duration(d)); + d = t - Clock::now(); + } + } +#endif - void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; +#else // BOOST_THREAD_SLEEP_FOR_IS_STEADY +// When pthread_delay_np and nanosleep are not available, +// fall back to using the interruptible sleep functions. #if defined BOOST_THREAD_USES_DATETIME #ifdef __DECXXX - /// Workaround of DECCXX issue of incorrect template substitution - template<> + /// Workaround of DECCXX issue of incorrect template substitution + template<> #endif - inline void sleep(system_time const& abs_time) - { - return boost::this_thread::hidden::sleep_until_realtime(boost::detail::to_timespec(abs_time)); - } + inline void sleep(system_time const& abs_time) + { + this_thread::sleep(abs_time); + } - template<typename TimeDuration> - inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) - { - this_thread::sleep(get_system_time()+rel_time); - } -#endif // BOOST_THREAD_USES_DATETIME + template<typename TimeDuration> + void sleep(TimeDuration const& rel_time) + { + this_thread::sleep(rel_time); + } +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> + void sleep_until(const chrono::time_point<Clock, Duration>& t) + { + this_thread::sleep_until(t); + } + + template <class Rep, class Period> + void sleep_for(const chrono::duration<Rep, Period>& d) + { + this_thread::sleep_for(d); + } +#endif + +#endif // BOOST_THREAD_SLEEP_FOR_IS_STEADY + } // no_interruption_point } // this_thread } |