Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -1007,6 +1007,14 @@ # endif // _LIBCPP_HAS_THREAD_API #endif // _LIBCPP_HAS_NO_THREADS +#if defined(__ANDROID__) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +# if defined(__LP64__) +# define _LIBCPP_HAS_COND_INITIALIZER_MONOTONIC_NP +# else +# define _LIBCPP_HAS_COND_TIMEDWAIT_MONOTONIC_NP +# endif +#endif + #if defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD) # error _LIBCPP_HAS_THREAD_API_PTHREAD may only be defined when \ _LIBCPP_HAS_NO_THREADS is not defined. Index: include/__mutex_base =================================================================== --- include/__mutex_base +++ include/__mutex_base @@ -288,7 +288,11 @@ class _LIBCPP_TYPE_VIS condition_variable { #ifndef _LIBCPP_CXX03_LANG +#if defined(_LIBCPP_HAS_COND_INITIALIZER_MONOTONIC_NP) + __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER_MONOTONIC_NP; +#else __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; +#endif #else __libcpp_condvar_t __cv_; #endif @@ -297,8 +301,12 @@ _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_CXX03_LANG constexpr condition_variable() _NOEXCEPT = default; +#else +#if defined(_LIBCPP_HAS_COND_INITIALIZER_MONOTONIC_NP) + condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER_MONOTONIC_NP;} #else condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;} +#endif #endif ~condition_variable(); @@ -347,6 +355,10 @@ private: void __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; +#if defined(_LIBCPP_HAS_COND_TIMEDWAIT_MONOTONIC_NP) || defined(_LIBCPP_HAS_COND_INITIALIZER_MONOTONIC_NP) + void __do_timed_wait(unique_lock& __lk, + chrono::time_point) _NOEXCEPT; +#endif }; #endif // !_LIBCPP_HAS_NO_THREADS @@ -407,15 +419,25 @@ using namespace chrono; if (__d <= __d.zero()) return cv_status::timeout; + steady_clock::time_point __c_now = steady_clock::now(); +#if defined(_LIBCPP_HAS_COND_TIMEDWAIT_MONOTONIC_NP) || defined(_LIBCPP_HAS_COND_INITIALIZER_MONOTONIC_NP) + typedef time_point > __c_tpf; + typedef time_point __c_tpi; + __c_tpf _Max = __c_tpi::max(); + if (_Max - __d > __c_now) + __do_timed_wait(__lk, __c_now + __ceil(__d)); + else + __do_timed_wait(__lk, __c_tpi::max()); +#else typedef time_point > __sys_tpf; typedef time_point __sys_tpi; __sys_tpf _Max = __sys_tpi::max(); - steady_clock::time_point __c_now = steady_clock::now(); system_clock::time_point __s_now = system_clock::now(); if (_Max - __d > __s_now) __do_timed_wait(__lk, __s_now + __ceil(__d)); else __do_timed_wait(__lk, __sys_tpi::max()); +#endif return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; } Index: include/__threading_support =================================================================== --- include/__threading_support +++ include/__threading_support @@ -60,6 +60,9 @@ // Condition Variable typedef pthread_cond_t __libcpp_condvar_t; +#if defined(_LIBCPP_HAS_COND_INITIALIZER_MONOTONIC_NP) +#define _LIBCPP_CONDVAR_INITIALIZER_MONOTONIC_NP PTHREAD_COND_INITIALIZER_MONOTONIC_NP +#endif #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER // Execute once Index: src/condition_variable.cpp =================================================================== --- src/condition_variable.cpp +++ src/condition_variable.cpp @@ -46,15 +46,11 @@ __throw_system_error(ec, "condition_variable wait failed"); } -void -condition_variable::__do_timed_wait(unique_lock& lk, - chrono::time_point tp) _NOEXCEPT +namespace { +timespec +chrono_timepoint_to_timespec(chrono::nanoseconds d) { using namespace chrono; - if (!lk.owns_lock()) - __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; @@ -71,10 +67,41 @@ ts.tv_sec = ts_sec_max; ts.tv_nsec = giga::num - 1; } + return ts; +} +} + +void +condition_variable::__do_timed_wait(unique_lock& lk, + chrono::time_point tp) _NOEXCEPT +{ + if (!lk.owns_lock()) + __throw_system_error(EPERM, + "condition_variable::timed wait: mutex not locked"); + timespec ts = chrono_timepoint_to_timespec(tp.time_since_epoch()); + int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); + if (ec != 0 && ec != ETIMEDOUT) + __throw_system_error(ec, "condition_variable timed_wait failed"); +} + +#if defined(_LIBCPP_HAS_COND_TIMEDWAIT_MONOTONIC_NP) || defined(_LIBCPP_HAS_COND_INITIALIZER_MONOTONIC_NP) +void +condition_variable::__do_timed_wait(unique_lock& lk, + chrono::time_point tp) _NOEXCEPT +{ + if (!lk.owns_lock()) + __throw_system_error(EPERM, + "condition_variable::timed wait: mutex not locked"); + timespec ts = chrono_timepoint_to_timespec(tp.time_since_epoch()); +#if defined(_LIBCPP_HAS_COND_TIMEDWAIT_MONOTONIC_NP) + int ec = pthread_cond_timedwait_monotonic_np(&__cv_, lk.mutex()->native_handle(), &ts); +#else int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); +#endif if (ec != 0 && ec != ETIMEDOUT) __throw_system_error(ec, "condition_variable timed_wait failed"); } +#endif void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk)