146035553Spatrick// -*- C++ -*- 246035553Spatrick//===----------------------------------------------------------------------===// 346035553Spatrick// 446035553Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 546035553Spatrick// See https://llvm.org/LICENSE.txt for license information. 646035553Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 746035553Spatrick// 846035553Spatrick//===----------------------------------------------------------------------===// 946035553Spatrick 1046035553Spatrick#ifndef _LIBCPP___MUTEX_BASE 1146035553Spatrick#define _LIBCPP___MUTEX_BASE 1246035553Spatrick 13*4bdff4beSrobert#include <__chrono/duration.h> 14*4bdff4beSrobert#include <__chrono/steady_clock.h> 15*4bdff4beSrobert#include <__chrono/system_clock.h> 16*4bdff4beSrobert#include <__chrono/time_point.h> 1746035553Spatrick#include <__config> 1876d0caaeSpatrick#include <__threading_support> 19*4bdff4beSrobert#include <ratio> 2046035553Spatrick#include <system_error> 2146035553Spatrick#include <time.h> 2246035553Spatrick 2346035553Spatrick#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2446035553Spatrick# pragma GCC system_header 2546035553Spatrick#endif 2646035553Spatrick 2746035553Spatrick_LIBCPP_PUSH_MACROS 2846035553Spatrick#include <__undef_macros> 2946035553Spatrick 3046035553Spatrick 3146035553Spatrick_LIBCPP_BEGIN_NAMESPACE_STD 3246035553Spatrick 3346035553Spatrick#ifndef _LIBCPP_HAS_NO_THREADS 3446035553Spatrick 3546035553Spatrickclass _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex 3646035553Spatrick{ 3746035553Spatrick __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; 3846035553Spatrick 3946035553Spatrickpublic: 4046035553Spatrick _LIBCPP_INLINE_VISIBILITY 4146035553Spatrick _LIBCPP_CONSTEXPR mutex() = default; 4246035553Spatrick 4346035553Spatrick mutex(const mutex&) = delete; 4446035553Spatrick mutex& operator=(const mutex&) = delete; 4546035553Spatrick 4646035553Spatrick#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) 4746035553Spatrick ~mutex() = default; 4846035553Spatrick#else 4946035553Spatrick ~mutex() _NOEXCEPT; 5046035553Spatrick#endif 5146035553Spatrick 5246035553Spatrick void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); 5346035553Spatrick bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); 5446035553Spatrick void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); 5546035553Spatrick 5646035553Spatrick typedef __libcpp_mutex_t* native_handle_type; 5746035553Spatrick _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 5846035553Spatrick}; 5946035553Spatrick 6046035553Spatrickstatic_assert(is_nothrow_default_constructible<mutex>::value, 6146035553Spatrick "the default constructor for std::mutex must be nothrow"); 6246035553Spatrick 6346035553Spatrickstruct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; }; 6446035553Spatrickstruct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; }; 6546035553Spatrickstruct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; }; 6646035553Spatrick 6746035553Spatrick#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) 6846035553Spatrick 6946035553Spatrickextern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock; 7046035553Spatrickextern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock; 7146035553Spatrickextern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock; 7246035553Spatrick 7346035553Spatrick#else 7446035553Spatrick 75*4bdff4beSrobert/* inline */ constexpr defer_lock_t defer_lock = defer_lock_t(); 76*4bdff4beSrobert/* inline */ constexpr try_to_lock_t try_to_lock = try_to_lock_t(); 77*4bdff4beSrobert/* inline */ constexpr adopt_lock_t adopt_lock = adopt_lock_t(); 7846035553Spatrick 7946035553Spatrick#endif 8046035553Spatrick 8146035553Spatricktemplate <class _Mutex> 8246035553Spatrickclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) 8346035553Spatricklock_guard 8446035553Spatrick{ 8546035553Spatrickpublic: 8646035553Spatrick typedef _Mutex mutex_type; 8746035553Spatrick 8846035553Spatrickprivate: 8946035553Spatrick mutex_type& __m_; 9046035553Spatrickpublic: 9146035553Spatrick 9246035553Spatrick _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 9346035553Spatrick explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 9446035553Spatrick : __m_(__m) {__m_.lock();} 9546035553Spatrick 9646035553Spatrick _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 9746035553Spatrick lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 9846035553Spatrick : __m_(__m) {} 9946035553Spatrick _LIBCPP_INLINE_VISIBILITY 10046035553Spatrick ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 10146035553Spatrick 10246035553Spatrickprivate: 103*4bdff4beSrobert lock_guard(lock_guard const&) = delete; 104*4bdff4beSrobert lock_guard& operator=(lock_guard const&) = delete; 10546035553Spatrick}; 106*4bdff4beSrobert_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); 10746035553Spatrick 10846035553Spatricktemplate <class _Mutex> 10946035553Spatrickclass _LIBCPP_TEMPLATE_VIS unique_lock 11046035553Spatrick{ 11146035553Spatrickpublic: 11246035553Spatrick typedef _Mutex mutex_type; 11346035553Spatrick 11446035553Spatrickprivate: 11546035553Spatrick mutex_type* __m_; 11646035553Spatrick bool __owns_; 11746035553Spatrick 11846035553Spatrickpublic: 11946035553Spatrick _LIBCPP_INLINE_VISIBILITY 12046035553Spatrick unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 12146035553Spatrick _LIBCPP_INLINE_VISIBILITY 12246035553Spatrick explicit unique_lock(mutex_type& __m) 12346035553Spatrick : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} 12446035553Spatrick _LIBCPP_INLINE_VISIBILITY 12546035553Spatrick unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 12646035553Spatrick : __m_(_VSTD::addressof(__m)), __owns_(false) {} 12746035553Spatrick _LIBCPP_INLINE_VISIBILITY 12846035553Spatrick unique_lock(mutex_type& __m, try_to_lock_t) 12946035553Spatrick : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} 13046035553Spatrick _LIBCPP_INLINE_VISIBILITY 13146035553Spatrick unique_lock(mutex_type& __m, adopt_lock_t) 13246035553Spatrick : __m_(_VSTD::addressof(__m)), __owns_(true) {} 13346035553Spatrick template <class _Clock, class _Duration> 13446035553Spatrick _LIBCPP_INLINE_VISIBILITY 13546035553Spatrick unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 13646035553Spatrick : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} 13746035553Spatrick template <class _Rep, class _Period> 13846035553Spatrick _LIBCPP_INLINE_VISIBILITY 13946035553Spatrick unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 14046035553Spatrick : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} 14146035553Spatrick _LIBCPP_INLINE_VISIBILITY 14246035553Spatrick ~unique_lock() 14346035553Spatrick { 14446035553Spatrick if (__owns_) 14546035553Spatrick __m_->unlock(); 14646035553Spatrick } 14746035553Spatrick 148*4bdff4beSrobert unique_lock(unique_lock const&) = delete; 149*4bdff4beSrobert unique_lock& operator=(unique_lock const&) = delete; 15046035553Spatrick 15146035553Spatrick _LIBCPP_INLINE_VISIBILITY 15246035553Spatrick unique_lock(unique_lock&& __u) _NOEXCEPT 15346035553Spatrick : __m_(__u.__m_), __owns_(__u.__owns_) 15446035553Spatrick {__u.__m_ = nullptr; __u.__owns_ = false;} 15546035553Spatrick _LIBCPP_INLINE_VISIBILITY 15646035553Spatrick unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 15746035553Spatrick { 15846035553Spatrick if (__owns_) 15946035553Spatrick __m_->unlock(); 16046035553Spatrick __m_ = __u.__m_; 16146035553Spatrick __owns_ = __u.__owns_; 16246035553Spatrick __u.__m_ = nullptr; 16346035553Spatrick __u.__owns_ = false; 16446035553Spatrick return *this; 16546035553Spatrick } 16646035553Spatrick 16746035553Spatrick void lock(); 16846035553Spatrick bool try_lock(); 16946035553Spatrick 17046035553Spatrick template <class _Rep, class _Period> 17146035553Spatrick bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 17246035553Spatrick template <class _Clock, class _Duration> 17346035553Spatrick bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 17446035553Spatrick 17546035553Spatrick void unlock(); 17646035553Spatrick 17746035553Spatrick _LIBCPP_INLINE_VISIBILITY 17846035553Spatrick void swap(unique_lock& __u) _NOEXCEPT 17946035553Spatrick { 18046035553Spatrick _VSTD::swap(__m_, __u.__m_); 18146035553Spatrick _VSTD::swap(__owns_, __u.__owns_); 18246035553Spatrick } 18346035553Spatrick _LIBCPP_INLINE_VISIBILITY 18446035553Spatrick mutex_type* release() _NOEXCEPT 18546035553Spatrick { 18646035553Spatrick mutex_type* __m = __m_; 18746035553Spatrick __m_ = nullptr; 18846035553Spatrick __owns_ = false; 18946035553Spatrick return __m; 19046035553Spatrick } 19146035553Spatrick 19246035553Spatrick _LIBCPP_INLINE_VISIBILITY 19346035553Spatrick bool owns_lock() const _NOEXCEPT {return __owns_;} 19446035553Spatrick _LIBCPP_INLINE_VISIBILITY 19576d0caaeSpatrick explicit operator bool() const _NOEXCEPT {return __owns_;} 19646035553Spatrick _LIBCPP_INLINE_VISIBILITY 19746035553Spatrick mutex_type* mutex() const _NOEXCEPT {return __m_;} 19846035553Spatrick}; 199*4bdff4beSrobert_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock); 20046035553Spatrick 20146035553Spatricktemplate <class _Mutex> 20246035553Spatrickvoid 20346035553Spatrickunique_lock<_Mutex>::lock() 20446035553Spatrick{ 20546035553Spatrick if (__m_ == nullptr) 20646035553Spatrick __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 20746035553Spatrick if (__owns_) 20846035553Spatrick __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 20946035553Spatrick __m_->lock(); 21046035553Spatrick __owns_ = true; 21146035553Spatrick} 21246035553Spatrick 21346035553Spatricktemplate <class _Mutex> 21446035553Spatrickbool 21546035553Spatrickunique_lock<_Mutex>::try_lock() 21646035553Spatrick{ 21746035553Spatrick if (__m_ == nullptr) 21846035553Spatrick __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 21946035553Spatrick if (__owns_) 22046035553Spatrick __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 22146035553Spatrick __owns_ = __m_->try_lock(); 22246035553Spatrick return __owns_; 22346035553Spatrick} 22446035553Spatrick 22546035553Spatricktemplate <class _Mutex> 22646035553Spatricktemplate <class _Rep, class _Period> 22746035553Spatrickbool 22846035553Spatrickunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 22946035553Spatrick{ 23046035553Spatrick if (__m_ == nullptr) 23146035553Spatrick __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 23246035553Spatrick if (__owns_) 23346035553Spatrick __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 23446035553Spatrick __owns_ = __m_->try_lock_for(__d); 23546035553Spatrick return __owns_; 23646035553Spatrick} 23746035553Spatrick 23846035553Spatricktemplate <class _Mutex> 23946035553Spatricktemplate <class _Clock, class _Duration> 24046035553Spatrickbool 24146035553Spatrickunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 24246035553Spatrick{ 24346035553Spatrick if (__m_ == nullptr) 24446035553Spatrick __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 24546035553Spatrick if (__owns_) 24646035553Spatrick __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 24746035553Spatrick __owns_ = __m_->try_lock_until(__t); 24846035553Spatrick return __owns_; 24946035553Spatrick} 25046035553Spatrick 25146035553Spatricktemplate <class _Mutex> 25246035553Spatrickvoid 25346035553Spatrickunique_lock<_Mutex>::unlock() 25446035553Spatrick{ 25546035553Spatrick if (!__owns_) 25646035553Spatrick __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 25746035553Spatrick __m_->unlock(); 25846035553Spatrick __owns_ = false; 25946035553Spatrick} 26046035553Spatrick 26146035553Spatricktemplate <class _Mutex> 26246035553Spatrickinline _LIBCPP_INLINE_VISIBILITY 26346035553Spatrickvoid 26446035553Spatrickswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 26546035553Spatrick {__x.swap(__y);} 26646035553Spatrick 26746035553Spatrick//enum class cv_status 26846035553Spatrick_LIBCPP_DECLARE_STRONG_ENUM(cv_status) 26946035553Spatrick{ 27046035553Spatrick no_timeout, 27146035553Spatrick timeout 27246035553Spatrick}; 27346035553Spatrick_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) 27446035553Spatrick 27546035553Spatrickclass _LIBCPP_TYPE_VIS condition_variable 27646035553Spatrick{ 27746035553Spatrick __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; 27846035553Spatrickpublic: 27946035553Spatrick _LIBCPP_INLINE_VISIBILITY 28046035553Spatrick _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; 28146035553Spatrick 28246035553Spatrick#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION 28346035553Spatrick ~condition_variable() = default; 28446035553Spatrick#else 28546035553Spatrick ~condition_variable(); 28646035553Spatrick#endif 28746035553Spatrick 28846035553Spatrick condition_variable(const condition_variable&) = delete; 28946035553Spatrick condition_variable& operator=(const condition_variable&) = delete; 29046035553Spatrick 29146035553Spatrick void notify_one() _NOEXCEPT; 29246035553Spatrick void notify_all() _NOEXCEPT; 29346035553Spatrick 29446035553Spatrick void wait(unique_lock<mutex>& __lk) _NOEXCEPT; 29546035553Spatrick template <class _Predicate> 29646035553Spatrick _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 29746035553Spatrick void wait(unique_lock<mutex>& __lk, _Predicate __pred); 29846035553Spatrick 29946035553Spatrick template <class _Clock, class _Duration> 30046035553Spatrick _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 30146035553Spatrick cv_status 30246035553Spatrick wait_until(unique_lock<mutex>& __lk, 30346035553Spatrick const chrono::time_point<_Clock, _Duration>& __t); 30446035553Spatrick 30546035553Spatrick template <class _Clock, class _Duration, class _Predicate> 30646035553Spatrick _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 30746035553Spatrick bool 30846035553Spatrick wait_until(unique_lock<mutex>& __lk, 30946035553Spatrick const chrono::time_point<_Clock, _Duration>& __t, 31046035553Spatrick _Predicate __pred); 31146035553Spatrick 31246035553Spatrick template <class _Rep, class _Period> 31346035553Spatrick _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 31446035553Spatrick cv_status 31546035553Spatrick wait_for(unique_lock<mutex>& __lk, 31646035553Spatrick const chrono::duration<_Rep, _Period>& __d); 31746035553Spatrick 31846035553Spatrick template <class _Rep, class _Period, class _Predicate> 31946035553Spatrick bool 32046035553Spatrick _LIBCPP_INLINE_VISIBILITY 32146035553Spatrick wait_for(unique_lock<mutex>& __lk, 32246035553Spatrick const chrono::duration<_Rep, _Period>& __d, 32346035553Spatrick _Predicate __pred); 32446035553Spatrick 32546035553Spatrick typedef __libcpp_condvar_t* native_handle_type; 32646035553Spatrick _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 32746035553Spatrick 32846035553Spatrickprivate: 32946035553Spatrick void __do_timed_wait(unique_lock<mutex>& __lk, 33046035553Spatrick chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; 33146035553Spatrick#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 33246035553Spatrick void __do_timed_wait(unique_lock<mutex>& __lk, 33346035553Spatrick chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT; 33446035553Spatrick#endif 33546035553Spatrick template <class _Clock> 33646035553Spatrick void __do_timed_wait(unique_lock<mutex>& __lk, 33746035553Spatrick chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; 33846035553Spatrick}; 33946035553Spatrick#endif // !_LIBCPP_HAS_NO_THREADS 34046035553Spatrick 34146035553Spatricktemplate <class _Rep, class _Period> 34246035553Spatrickinline _LIBCPP_INLINE_VISIBILITY 343*4bdff4beSrobert__enable_if_t<is_floating_point<_Rep>::value, chrono::nanoseconds> 34446035553Spatrick__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 34546035553Spatrick{ 34646035553Spatrick using namespace chrono; 34746035553Spatrick using __ratio = ratio_divide<_Period, nano>; 34846035553Spatrick using __ns_rep = nanoseconds::rep; 34946035553Spatrick _Rep __result_float = __d.count() * __ratio::num / __ratio::den; 35046035553Spatrick 35146035553Spatrick _Rep __result_max = numeric_limits<__ns_rep>::max(); 35246035553Spatrick if (__result_float >= __result_max) { 35346035553Spatrick return nanoseconds::max(); 35446035553Spatrick } 35546035553Spatrick 35646035553Spatrick _Rep __result_min = numeric_limits<__ns_rep>::min(); 35746035553Spatrick if (__result_float <= __result_min) { 35846035553Spatrick return nanoseconds::min(); 35946035553Spatrick } 36046035553Spatrick 36146035553Spatrick return nanoseconds(static_cast<__ns_rep>(__result_float)); 36246035553Spatrick} 36346035553Spatrick 36446035553Spatricktemplate <class _Rep, class _Period> 36546035553Spatrickinline _LIBCPP_INLINE_VISIBILITY 366*4bdff4beSrobert__enable_if_t<!is_floating_point<_Rep>::value, chrono::nanoseconds> 36746035553Spatrick__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 36846035553Spatrick{ 36946035553Spatrick using namespace chrono; 37046035553Spatrick if (__d.count() == 0) { 37146035553Spatrick return nanoseconds(0); 37246035553Spatrick } 37346035553Spatrick 37446035553Spatrick using __ratio = ratio_divide<_Period, nano>; 37546035553Spatrick using __ns_rep = nanoseconds::rep; 37676d0caaeSpatrick __ns_rep __result_max = numeric_limits<__ns_rep>::max(); 37746035553Spatrick if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { 37846035553Spatrick return nanoseconds::max(); 37946035553Spatrick } 38046035553Spatrick 38176d0caaeSpatrick __ns_rep __result_min = numeric_limits<__ns_rep>::min(); 38246035553Spatrick if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { 38346035553Spatrick return nanoseconds::min(); 38446035553Spatrick } 38546035553Spatrick 38646035553Spatrick __ns_rep __result = __d.count() * __ratio::num / __ratio::den; 38746035553Spatrick if (__result == 0) { 38846035553Spatrick return nanoseconds(1); 38946035553Spatrick } 39046035553Spatrick 39146035553Spatrick return nanoseconds(__result); 39246035553Spatrick} 39346035553Spatrick 39446035553Spatrick#ifndef _LIBCPP_HAS_NO_THREADS 39546035553Spatricktemplate <class _Predicate> 39646035553Spatrickvoid 39746035553Spatrickcondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 39846035553Spatrick{ 39946035553Spatrick while (!__pred()) 40046035553Spatrick wait(__lk); 40146035553Spatrick} 40246035553Spatrick 40346035553Spatricktemplate <class _Clock, class _Duration> 40446035553Spatrickcv_status 40546035553Spatrickcondition_variable::wait_until(unique_lock<mutex>& __lk, 40646035553Spatrick const chrono::time_point<_Clock, _Duration>& __t) 40746035553Spatrick{ 40846035553Spatrick using namespace chrono; 40946035553Spatrick using __clock_tp_ns = time_point<_Clock, nanoseconds>; 41046035553Spatrick 41146035553Spatrick typename _Clock::time_point __now = _Clock::now(); 41246035553Spatrick if (__t <= __now) 41346035553Spatrick return cv_status::timeout; 41446035553Spatrick 41576d0caaeSpatrick __clock_tp_ns __t_ns = __clock_tp_ns(_VSTD::__safe_nanosecond_cast(__t.time_since_epoch())); 41646035553Spatrick 41746035553Spatrick __do_timed_wait(__lk, __t_ns); 41846035553Spatrick return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 41946035553Spatrick} 42046035553Spatrick 42146035553Spatricktemplate <class _Clock, class _Duration, class _Predicate> 42246035553Spatrickbool 42346035553Spatrickcondition_variable::wait_until(unique_lock<mutex>& __lk, 42446035553Spatrick const chrono::time_point<_Clock, _Duration>& __t, 42546035553Spatrick _Predicate __pred) 42646035553Spatrick{ 42746035553Spatrick while (!__pred()) 42846035553Spatrick { 42946035553Spatrick if (wait_until(__lk, __t) == cv_status::timeout) 43046035553Spatrick return __pred(); 43146035553Spatrick } 43246035553Spatrick return true; 43346035553Spatrick} 43446035553Spatrick 43546035553Spatricktemplate <class _Rep, class _Period> 43646035553Spatrickcv_status 43746035553Spatrickcondition_variable::wait_for(unique_lock<mutex>& __lk, 43846035553Spatrick const chrono::duration<_Rep, _Period>& __d) 43946035553Spatrick{ 44046035553Spatrick using namespace chrono; 44146035553Spatrick if (__d <= __d.zero()) 44246035553Spatrick return cv_status::timeout; 44346035553Spatrick using __ns_rep = nanoseconds::rep; 44446035553Spatrick steady_clock::time_point __c_now = steady_clock::now(); 44546035553Spatrick 44646035553Spatrick#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 44746035553Spatrick using __clock_tp_ns = time_point<steady_clock, nanoseconds>; 44876d0caaeSpatrick __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); 44946035553Spatrick#else 45046035553Spatrick using __clock_tp_ns = time_point<system_clock, nanoseconds>; 45176d0caaeSpatrick __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); 45246035553Spatrick#endif 45346035553Spatrick 45476d0caaeSpatrick __ns_rep __d_ns_count = _VSTD::__safe_nanosecond_cast(__d).count(); 45546035553Spatrick 45646035553Spatrick if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { 45746035553Spatrick __do_timed_wait(__lk, __clock_tp_ns::max()); 45846035553Spatrick } else { 45946035553Spatrick __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); 46046035553Spatrick } 46146035553Spatrick 46246035553Spatrick return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 46346035553Spatrick cv_status::timeout; 46446035553Spatrick} 46546035553Spatrick 46646035553Spatricktemplate <class _Rep, class _Period, class _Predicate> 46746035553Spatrickinline 46846035553Spatrickbool 46946035553Spatrickcondition_variable::wait_for(unique_lock<mutex>& __lk, 47046035553Spatrick const chrono::duration<_Rep, _Period>& __d, 47146035553Spatrick _Predicate __pred) 47246035553Spatrick{ 47346035553Spatrick return wait_until(__lk, chrono::steady_clock::now() + __d, 47446035553Spatrick _VSTD::move(__pred)); 47546035553Spatrick} 47646035553Spatrick 47746035553Spatrick#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 47846035553Spatrickinline 47946035553Spatrickvoid 48046035553Spatrickcondition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 48146035553Spatrick chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT 48246035553Spatrick{ 48346035553Spatrick using namespace chrono; 48446035553Spatrick if (!__lk.owns_lock()) 48546035553Spatrick __throw_system_error(EPERM, 48646035553Spatrick "condition_variable::timed wait: mutex not locked"); 48746035553Spatrick nanoseconds __d = __tp.time_since_epoch(); 48846035553Spatrick timespec __ts; 48946035553Spatrick seconds __s = duration_cast<seconds>(__d); 49046035553Spatrick using __ts_sec = decltype(__ts.tv_sec); 49146035553Spatrick const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 49246035553Spatrick if (__s.count() < __ts_sec_max) 49346035553Spatrick { 49446035553Spatrick __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 49546035553Spatrick __ts.tv_nsec = (__d - __s).count(); 49646035553Spatrick } 49746035553Spatrick else 49846035553Spatrick { 49946035553Spatrick __ts.tv_sec = __ts_sec_max; 50046035553Spatrick __ts.tv_nsec = giga::num - 1; 50146035553Spatrick } 50246035553Spatrick int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts); 50346035553Spatrick if (__ec != 0 && __ec != ETIMEDOUT) 50446035553Spatrick __throw_system_error(__ec, "condition_variable timed_wait failed"); 50546035553Spatrick} 50646035553Spatrick#endif // _LIBCPP_HAS_COND_CLOCKWAIT 50746035553Spatrick 50846035553Spatricktemplate <class _Clock> 50946035553Spatrickinline 51046035553Spatrickvoid 51146035553Spatrickcondition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 51246035553Spatrick chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT 51346035553Spatrick{ 51446035553Spatrick wait_for(__lk, __tp - _Clock::now()); 51546035553Spatrick} 51646035553Spatrick 51746035553Spatrick#endif // !_LIBCPP_HAS_NO_THREADS 51846035553Spatrick 51946035553Spatrick_LIBCPP_END_NAMESPACE_STD 52046035553Spatrick 52146035553Spatrick_LIBCPP_POP_MACROS 52246035553Spatrick 52346035553Spatrick#endif // _LIBCPP___MUTEX_BASE 524