diff options
Diffstat (limited to 'libcxx')
-rw-r--r-- | libcxx/include/__mutex_base | 32 | ||||
-rw-r--r-- | libcxx/include/thread | 18 | ||||
-rw-r--r-- | libcxx/src/condition_variable.cpp | 16 | ||||
-rw-r--r-- | libcxx/src/thread.cpp | 18 |
4 files changed, 53 insertions, 31 deletions
diff --git a/libcxx/include/__mutex_base b/libcxx/include/__mutex_base index 4fdcb617fbc..1782e7c0b39 100644 --- a/libcxx/include/__mutex_base +++ b/libcxx/include/__mutex_base @@ -323,11 +323,6 @@ public: template <class _Predicate> void wait(unique_lock<mutex>& __lk, _Predicate __pred); - template <class _Duration> - cv_status - wait_until(unique_lock<mutex>& __lk, - const chrono::time_point<chrono::system_clock, _Duration>& __t); - template <class _Clock, class _Duration> cv_status wait_until(unique_lock<mutex>& __lk, @@ -382,28 +377,13 @@ condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) wait(__lk); } -template <class _Duration> -cv_status -condition_variable::wait_until(unique_lock<mutex>& __lk, - const chrono::time_point<chrono::system_clock, _Duration>& __t) -{ - using namespace chrono; - typedef time_point<system_clock, nanoseconds> __nano_sys_tmpt; - __do_timed_wait(__lk, - __nano_sys_tmpt(__ceil<nanoseconds>(__t.time_since_epoch()))); - return system_clock::now() < __t ? cv_status::no_timeout : - cv_status::timeout; -} - template <class _Clock, class _Duration> cv_status condition_variable::wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; - system_clock::time_point __s_now = system_clock::now(); - typename _Clock::time_point __c_now = _Clock::now(); - __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__t - __c_now)); + wait_for(__lk, __t - _Clock::now()); return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; } @@ -427,9 +407,17 @@ condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) { using namespace chrono; + if (__d <= __d.zero()) + return cv_status::timeout; + typedef time_point<system_clock, duration<long double, nano> > __sys_tpf; + typedef time_point<system_clock, nanoseconds> __sys_tpi; + __sys_tpf _Max = __sys_tpi::max(); system_clock::time_point __s_now = system_clock::now(); steady_clock::time_point __c_now = steady_clock::now(); - __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d)); + if (_Max - __d > __s_now) + __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d)); + else + __do_timed_wait(__lk, __sys_tpi::max()); return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; } diff --git a/libcxx/include/thread b/libcxx/include/thread index d81e8537888..94e7ab6c54c 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -410,10 +410,20 @@ void sleep_for(const chrono::duration<_Rep, _Period>& __d) { using namespace chrono; - nanoseconds __ns = duration_cast<nanoseconds>(__d); - if (__ns < __d) - ++__ns; - sleep_for(__ns); + if (__d > duration<_Rep, _Period>::zero()) + { + _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); + nanoseconds __ns; + if (__d < _Max) + { + __ns = duration_cast<nanoseconds>(__d); + if (__ns < __d) + ++__ns; + } + else + __ns = nanoseconds::max(); + sleep_for(__ns); + } } template <class _Clock, class _Duration> diff --git a/libcxx/src/condition_variable.cpp b/libcxx/src/condition_variable.cpp index 552bce3561d..de0f6f47dd1 100644 --- a/libcxx/src/condition_variable.cpp +++ b/libcxx/src/condition_variable.cpp @@ -51,10 +51,22 @@ condition_variable::__do_timed_wait(unique_lock<mutex>& lk, __throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked"); nanoseconds d = tp.time_since_epoch(); + if (d > nanoseconds(0x59682F000000E941)) + d = nanoseconds(0x59682F000000E941); timespec ts; seconds s = duration_cast<seconds>(d); - ts.tv_sec = static_cast<decltype(ts.tv_sec)>(s.count()); - ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); + typedef decltype(ts.tv_sec) ts_sec; + _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); + if (s.count() < ts_sec_max) + { + ts.tv_sec = static_cast<ts_sec>(s.count()); + ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); + } + else + { + ts.tv_sec = ts_sec_max; + ts.tv_nsec = giga::num - 1; + } int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); if (ec != 0 && ec != ETIMEDOUT) __throw_system_error(ec, "condition_variable timed_wait failed"); diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp index 4445b8dbb9c..8747adf0b59 100644 --- a/libcxx/src/thread.cpp +++ b/libcxx/src/thread.cpp @@ -11,6 +11,7 @@ #include "exception" #include "vector" #include "future" +#include "limits" #include <sys/types.h> #if !_WIN32 #if !__sun__ && !__linux__ @@ -83,11 +84,22 @@ void sleep_for(const chrono::nanoseconds& ns) { using namespace chrono; - if (ns >= nanoseconds::zero()) + if (ns > nanoseconds::zero()) { + seconds s = duration_cast<seconds>(ns); timespec ts; - ts.tv_sec = static_cast<decltype(ts.tv_sec)>(duration_cast<seconds>(ns).count()); - ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns - seconds(ts.tv_sec)).count()); + typedef decltype(ts.tv_sec) ts_sec; + _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); + if (s.count() < ts_sec_max) + { + ts.tv_sec = static_cast<ts_sec>(s.count()); + ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); + } + else + { + ts.tv_sec = ts_sec_max; + ts.tv_nsec = giga::num - 1; + } nanosleep(&ts, 0); } } |