13e519524SHoward Hinnant// -*- C++ -*- 23e519524SHoward Hinnant//===----------------------------------------------------------------------===// 33e519524SHoward Hinnant// 457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 73e519524SHoward Hinnant// 83e519524SHoward Hinnant//===----------------------------------------------------------------------===// 93e519524SHoward Hinnant 103e519524SHoward Hinnant#ifndef _LIBCPP___MUTEX_BASE 113e519524SHoward Hinnant#define _LIBCPP___MUTEX_BASE 123e519524SHoward Hinnant 13489637e6SNikolas Klauser#include <__chrono/duration.h> 14489637e6SNikolas Klauser#include <__chrono/steady_clock.h> 15489637e6SNikolas Klauser#include <__chrono/system_clock.h> 16489637e6SNikolas Klauser#include <__chrono/time_point.h> 173e519524SHoward Hinnant#include <__config> 18bfbd73f8SArthur O'Dwyer#include <__threading_support> 195726e559SLouis Dionne#include <ratio> 203e519524SHoward Hinnant#include <system_error> 2185e26f56SDan Albert#include <time.h> 223e519524SHoward Hinnant 23073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 243e519524SHoward Hinnant# pragma GCC system_header 25073458b1SHoward Hinnant#endif 263e519524SHoward Hinnant 27a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS 28a016efb1SEric Fiselier#include <__undef_macros> 29a016efb1SEric Fiselier 30a016efb1SEric Fiselier 313e519524SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD 323e519524SHoward Hinnant 33b3fcc67fSJonathan Roelofs#ifndef _LIBCPP_HAS_NO_THREADS 34b3fcc67fSJonathan Roelofs 357865b2e9SEric Fiselierclass _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex 363e519524SHoward Hinnant{ 37816739caSMarshall Clow __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; 383e519524SHoward Hinnant 393e519524SHoward Hinnantpublic: 40f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 418baf8383SEric Fiselier _LIBCPP_CONSTEXPR mutex() = default; 428baf8383SEric Fiselier 438baf8383SEric Fiselier mutex(const mutex&) = delete; 448baf8383SEric Fiselier mutex& operator=(const mutex&) = delete; 458baf8383SEric Fiselier 468baf8383SEric Fiselier#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) 478baf8383SEric Fiselier ~mutex() = default; 48bfa7990bSHoward Hinnant#else 4965d4d5e9SRichard Smith ~mutex() _NOEXCEPT; 508baf8383SEric Fiselier#endif 513e519524SHoward Hinnant 527865b2e9SEric Fiselier void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); 537865b2e9SEric Fiselier bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); 547865b2e9SEric Fiselier void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); 553e519524SHoward Hinnant 56c7e4239fSAsiri Rathnayake typedef __libcpp_mutex_t* native_handle_type; 57f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 583e519524SHoward Hinnant}; 593e519524SHoward Hinnant 608551d0e3SEric Fiselierstatic_assert(is_nothrow_default_constructible<mutex>::value, 618551d0e3SEric Fiselier "the default constructor for std::mutex must be nothrow"); 628551d0e3SEric Fiselier 63e16f2cb6SLouis Dionnestruct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; }; 64e16f2cb6SLouis Dionnestruct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; }; 65e16f2cb6SLouis Dionnestruct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; }; 663e519524SHoward Hinnant 67c8e84ff2SLouis Dionne#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) 683e519524SHoward Hinnant 699b3222f6SLouis Dionneextern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock; 709b3222f6SLouis Dionneextern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock; 719b3222f6SLouis Dionneextern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock; 723e519524SHoward Hinnant 7302e610efSHoward Hinnant#else 7402e610efSHoward Hinnant 75cb793e1aSLouis Dionne/* inline */ constexpr defer_lock_t defer_lock = defer_lock_t(); 76cb793e1aSLouis Dionne/* inline */ constexpr try_to_lock_t try_to_lock = try_to_lock_t(); 77cb793e1aSLouis Dionne/* inline */ constexpr adopt_lock_t adopt_lock = adopt_lock_t(); 7802e610efSHoward Hinnant 7902e610efSHoward Hinnant#endif 803e519524SHoward Hinnant 813e519524SHoward Hinnanttemplate <class _Mutex> 82e2f2d1edSEric Fiselierclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) 8348f35e07SEric Fiselierlock_guard 843e519524SHoward Hinnant{ 853e519524SHoward Hinnantpublic: 863e519524SHoward Hinnant typedef _Mutex mutex_type; 873e519524SHoward Hinnant 883e519524SHoward Hinnantprivate: 893e519524SHoward Hinnant mutex_type& __m_; 903e519524SHoward Hinnantpublic: 913e519524SHoward Hinnant 9286dd28a5SLouis Dionne _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 937865b2e9SEric Fiselier explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 943e519524SHoward Hinnant : __m_(__m) {__m_.lock();} 9586dd28a5SLouis Dionne 9686dd28a5SLouis Dionne _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 977865b2e9SEric Fiselier lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 983e519524SHoward Hinnant : __m_(__m) {} 99f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 1007865b2e9SEric Fiselier ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 1013e519524SHoward Hinnant 1023e519524SHoward Hinnantprivate: 103d7d70601SArthur O'Dwyer lock_guard(lock_guard const&) = delete; 104d7d70601SArthur O'Dwyer lock_guard& operator=(lock_guard const&) = delete; 1053e519524SHoward Hinnant}; 1063e519524SHoward Hinnant 1073e519524SHoward Hinnanttemplate <class _Mutex> 108e2f2d1edSEric Fiselierclass _LIBCPP_TEMPLATE_VIS unique_lock 1093e519524SHoward Hinnant{ 1103e519524SHoward Hinnantpublic: 1113e519524SHoward Hinnant typedef _Mutex mutex_type; 1123e519524SHoward Hinnant 1133e519524SHoward Hinnantprivate: 1143e519524SHoward Hinnant mutex_type* __m_; 1153e519524SHoward Hinnant bool __owns_; 1163e519524SHoward Hinnant 1173e519524SHoward Hinnantpublic: 118f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 11902e610efSHoward Hinnant unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 120f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 1213e519524SHoward Hinnant explicit unique_lock(mutex_type& __m) 1223126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} 123f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 12402e610efSHoward Hinnant unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 1253126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), __owns_(false) {} 126f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 1273e519524SHoward Hinnant unique_lock(mutex_type& __m, try_to_lock_t) 1283126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} 129f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 1303e519524SHoward Hinnant unique_lock(mutex_type& __m, adopt_lock_t) 1313126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), __owns_(true) {} 1323e519524SHoward Hinnant template <class _Clock, class _Duration> 133f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 1343e519524SHoward Hinnant unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 1353126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} 1363e519524SHoward Hinnant template <class _Rep, class _Period> 137f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 1383e519524SHoward Hinnant unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 1393126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} 140f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 1413e519524SHoward Hinnant ~unique_lock() 1423e519524SHoward Hinnant { 1433e519524SHoward Hinnant if (__owns_) 1443e519524SHoward Hinnant __m_->unlock(); 1453e519524SHoward Hinnant } 1463e519524SHoward Hinnant 147feb80aa9SNikolas Klauser unique_lock(unique_lock const&) = delete; 148feb80aa9SNikolas Klauser unique_lock& operator=(unique_lock const&) = delete; 1493e519524SHoward Hinnant 150f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 15102e610efSHoward Hinnant unique_lock(unique_lock&& __u) _NOEXCEPT 1523e519524SHoward Hinnant : __m_(__u.__m_), __owns_(__u.__owns_) 1533e519524SHoward Hinnant {__u.__m_ = nullptr; __u.__owns_ = false;} 154f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 15502e610efSHoward Hinnant unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 1563e519524SHoward Hinnant { 1573e519524SHoward Hinnant if (__owns_) 1583e519524SHoward Hinnant __m_->unlock(); 1593e519524SHoward Hinnant __m_ = __u.__m_; 1603e519524SHoward Hinnant __owns_ = __u.__owns_; 1613e519524SHoward Hinnant __u.__m_ = nullptr; 1623e519524SHoward Hinnant __u.__owns_ = false; 1633e519524SHoward Hinnant return *this; 1643e519524SHoward Hinnant } 1656fd5c650SHoward Hinnant 1663e519524SHoward Hinnant void lock(); 1673e519524SHoward Hinnant bool try_lock(); 1683e519524SHoward Hinnant 1693e519524SHoward Hinnant template <class _Rep, class _Period> 1703e519524SHoward Hinnant bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 1713e519524SHoward Hinnant template <class _Clock, class _Duration> 1723e519524SHoward Hinnant bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 1733e519524SHoward Hinnant 1743e519524SHoward Hinnant void unlock(); 1753e519524SHoward Hinnant 176f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 17702e610efSHoward Hinnant void swap(unique_lock& __u) _NOEXCEPT 1783e519524SHoward Hinnant { 179ce48a113SHoward Hinnant _VSTD::swap(__m_, __u.__m_); 180ce48a113SHoward Hinnant _VSTD::swap(__owns_, __u.__owns_); 1813e519524SHoward Hinnant } 182f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 18302e610efSHoward Hinnant mutex_type* release() _NOEXCEPT 1843e519524SHoward Hinnant { 1853e519524SHoward Hinnant mutex_type* __m = __m_; 1863e519524SHoward Hinnant __m_ = nullptr; 1873e519524SHoward Hinnant __owns_ = false; 1883e519524SHoward Hinnant return __m; 1893e519524SHoward Hinnant } 1903e519524SHoward Hinnant 191f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 19202e610efSHoward Hinnant bool owns_lock() const _NOEXCEPT {return __owns_;} 193f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 194317e92a3SArthur O'Dwyer explicit operator bool() const _NOEXCEPT {return __owns_;} 195f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 19602e610efSHoward Hinnant mutex_type* mutex() const _NOEXCEPT {return __m_;} 1973e519524SHoward Hinnant}; 1983e519524SHoward Hinnant 1993e519524SHoward Hinnanttemplate <class _Mutex> 2003e519524SHoward Hinnantvoid 2013e519524SHoward Hinnantunique_lock<_Mutex>::lock() 2023e519524SHoward Hinnant{ 2033e519524SHoward Hinnant if (__m_ == nullptr) 2043e519524SHoward Hinnant __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 2053e519524SHoward Hinnant if (__owns_) 2063e519524SHoward Hinnant __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 2073e519524SHoward Hinnant __m_->lock(); 2083e519524SHoward Hinnant __owns_ = true; 2093e519524SHoward Hinnant} 2103e519524SHoward Hinnant 2113e519524SHoward Hinnanttemplate <class _Mutex> 2123e519524SHoward Hinnantbool 2133e519524SHoward Hinnantunique_lock<_Mutex>::try_lock() 2143e519524SHoward Hinnant{ 2153e519524SHoward Hinnant if (__m_ == nullptr) 2163e519524SHoward Hinnant __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 2173e519524SHoward Hinnant if (__owns_) 2183e519524SHoward Hinnant __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 2193e519524SHoward Hinnant __owns_ = __m_->try_lock(); 2203e519524SHoward Hinnant return __owns_; 2213e519524SHoward Hinnant} 2223e519524SHoward Hinnant 2233e519524SHoward Hinnanttemplate <class _Mutex> 2243e519524SHoward Hinnanttemplate <class _Rep, class _Period> 2253e519524SHoward Hinnantbool 2263e519524SHoward Hinnantunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 2273e519524SHoward Hinnant{ 2283e519524SHoward Hinnant if (__m_ == nullptr) 2293e519524SHoward Hinnant __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 2303e519524SHoward Hinnant if (__owns_) 2313e519524SHoward Hinnant __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 2323e519524SHoward Hinnant __owns_ = __m_->try_lock_for(__d); 2333e519524SHoward Hinnant return __owns_; 2343e519524SHoward Hinnant} 2353e519524SHoward Hinnant 2363e519524SHoward Hinnanttemplate <class _Mutex> 2373e519524SHoward Hinnanttemplate <class _Clock, class _Duration> 2383e519524SHoward Hinnantbool 2393e519524SHoward Hinnantunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 2403e519524SHoward Hinnant{ 2413e519524SHoward Hinnant if (__m_ == nullptr) 2423e519524SHoward Hinnant __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 2433e519524SHoward Hinnant if (__owns_) 2443e519524SHoward Hinnant __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 2453e519524SHoward Hinnant __owns_ = __m_->try_lock_until(__t); 2463e519524SHoward Hinnant return __owns_; 2473e519524SHoward Hinnant} 2483e519524SHoward Hinnant 2493e519524SHoward Hinnanttemplate <class _Mutex> 2503e519524SHoward Hinnantvoid 2513e519524SHoward Hinnantunique_lock<_Mutex>::unlock() 2523e519524SHoward Hinnant{ 2533e519524SHoward Hinnant if (!__owns_) 2543e519524SHoward Hinnant __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 2553e519524SHoward Hinnant __m_->unlock(); 2563e519524SHoward Hinnant __owns_ = false; 2573e519524SHoward Hinnant} 2583e519524SHoward Hinnant 2593e519524SHoward Hinnanttemplate <class _Mutex> 260f5ab703fSHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 2613e519524SHoward Hinnantvoid 26202e610efSHoward Hinnantswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 26302e610efSHoward Hinnant {__x.swap(__y);} 2643e519524SHoward Hinnant 265ce81aed4SMarshall Clow//enum class cv_status 266ce81aed4SMarshall Clow_LIBCPP_DECLARE_STRONG_ENUM(cv_status) 2673e519524SHoward Hinnant{ 2683e519524SHoward Hinnant no_timeout, 2693e519524SHoward Hinnant timeout 2703e519524SHoward Hinnant}; 271ce81aed4SMarshall Clow_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) 2723e519524SHoward Hinnant 2736e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS condition_variable 2743e519524SHoward Hinnant{ 275816739caSMarshall Clow __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; 2763e519524SHoward Hinnantpublic: 277f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY 2788cedf04aSEric Fiselier _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; 2798cedf04aSEric Fiselier 2808cedf04aSEric Fiselier#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION 2818cedf04aSEric Fiselier ~condition_variable() = default; 282bfa7990bSHoward Hinnant#else 2833e519524SHoward Hinnant ~condition_variable(); 2848cedf04aSEric Fiselier#endif 2853e519524SHoward Hinnant 2868cedf04aSEric Fiselier condition_variable(const condition_variable&) = delete; 2878cedf04aSEric Fiselier condition_variable& operator=(const condition_variable&) = delete; 2883e519524SHoward Hinnant 28945c663dbSHoward Hinnant void notify_one() _NOEXCEPT; 29045c663dbSHoward Hinnant void notify_all() _NOEXCEPT; 2913e519524SHoward Hinnant 2921641a7c1SMarshall Clow void wait(unique_lock<mutex>& __lk) _NOEXCEPT; 2933e519524SHoward Hinnant template <class _Predicate> 294bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2953e519524SHoward Hinnant void wait(unique_lock<mutex>& __lk, _Predicate __pred); 2963e519524SHoward Hinnant 2973e519524SHoward Hinnant template <class _Clock, class _Duration> 298bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2993e519524SHoward Hinnant cv_status 3003e519524SHoward Hinnant wait_until(unique_lock<mutex>& __lk, 3013e519524SHoward Hinnant const chrono::time_point<_Clock, _Duration>& __t); 3023e519524SHoward Hinnant 3033e519524SHoward Hinnant template <class _Clock, class _Duration, class _Predicate> 304bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 3053e519524SHoward Hinnant bool 3063e519524SHoward Hinnant wait_until(unique_lock<mutex>& __lk, 3073e519524SHoward Hinnant const chrono::time_point<_Clock, _Duration>& __t, 3083e519524SHoward Hinnant _Predicate __pred); 3093e519524SHoward Hinnant 3103e519524SHoward Hinnant template <class _Rep, class _Period> 311bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 3123e519524SHoward Hinnant cv_status 3133e519524SHoward Hinnant wait_for(unique_lock<mutex>& __lk, 3143e519524SHoward Hinnant const chrono::duration<_Rep, _Period>& __d); 3153e519524SHoward Hinnant 3163e519524SHoward Hinnant template <class _Rep, class _Period, class _Predicate> 3173e519524SHoward Hinnant bool 318906c872dSEvgeniy Stepanov _LIBCPP_INLINE_VISIBILITY 3193e519524SHoward Hinnant wait_for(unique_lock<mutex>& __lk, 3203e519524SHoward Hinnant const chrono::duration<_Rep, _Period>& __d, 3213e519524SHoward Hinnant _Predicate __pred); 3223e519524SHoward Hinnant 323c7e4239fSAsiri Rathnayake typedef __libcpp_condvar_t* native_handle_type; 324f5ab703fSHoward Hinnant _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 3253e519524SHoward Hinnant 3263e519524SHoward Hinnantprivate: 3273e519524SHoward Hinnant void __do_timed_wait(unique_lock<mutex>& __lk, 3281641a7c1SMarshall Clow chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; 32985e26f56SDan Albert#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 33085e26f56SDan Albert void __do_timed_wait(unique_lock<mutex>& __lk, 33185e26f56SDan Albert chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT; 33285e26f56SDan Albert#endif 33385e26f56SDan Albert template <class _Clock> 33485e26f56SDan Albert void __do_timed_wait(unique_lock<mutex>& __lk, 33585e26f56SDan Albert chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; 3363e519524SHoward Hinnant}; 337b3fcc67fSJonathan Roelofs#endif // !_LIBCPP_HAS_NO_THREADS 3383e519524SHoward Hinnant 33985e26f56SDan Alberttemplate <class _Rep, class _Period> 340f5ab703fSHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 341*4887d047SNikolas Klauser__enable_if_t<is_floating_point<_Rep>::value, chrono::nanoseconds> 34285e26f56SDan Albert__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 3433e519524SHoward Hinnant{ 3443e519524SHoward Hinnant using namespace chrono; 34585e26f56SDan Albert using __ratio = ratio_divide<_Period, nano>; 34685e26f56SDan Albert using __ns_rep = nanoseconds::rep; 34785e26f56SDan Albert _Rep __result_float = __d.count() * __ratio::num / __ratio::den; 34885e26f56SDan Albert 34985e26f56SDan Albert _Rep __result_max = numeric_limits<__ns_rep>::max(); 35085e26f56SDan Albert if (__result_float >= __result_max) { 35185e26f56SDan Albert return nanoseconds::max(); 35285e26f56SDan Albert } 35385e26f56SDan Albert 35485e26f56SDan Albert _Rep __result_min = numeric_limits<__ns_rep>::min(); 35585e26f56SDan Albert if (__result_float <= __result_min) { 35685e26f56SDan Albert return nanoseconds::min(); 35785e26f56SDan Albert } 35885e26f56SDan Albert 35985e26f56SDan Albert return nanoseconds(static_cast<__ns_rep>(__result_float)); 36085e26f56SDan Albert} 36185e26f56SDan Albert 36285e26f56SDan Alberttemplate <class _Rep, class _Period> 36385e26f56SDan Albertinline _LIBCPP_INLINE_VISIBILITY 364*4887d047SNikolas Klauser__enable_if_t<!is_floating_point<_Rep>::value, chrono::nanoseconds> 36585e26f56SDan Albert__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 36685e26f56SDan Albert{ 36785e26f56SDan Albert using namespace chrono; 36885e26f56SDan Albert if (__d.count() == 0) { 36985e26f56SDan Albert return nanoseconds(0); 37085e26f56SDan Albert } 37185e26f56SDan Albert 37285e26f56SDan Albert using __ratio = ratio_divide<_Period, nano>; 37385e26f56SDan Albert using __ns_rep = nanoseconds::rep; 374d586f92cSArthur O'Dwyer __ns_rep __result_max = numeric_limits<__ns_rep>::max(); 37585e26f56SDan Albert if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { 37685e26f56SDan Albert return nanoseconds::max(); 37785e26f56SDan Albert } 37885e26f56SDan Albert 379d586f92cSArthur O'Dwyer __ns_rep __result_min = numeric_limits<__ns_rep>::min(); 38085e26f56SDan Albert if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { 38185e26f56SDan Albert return nanoseconds::min(); 38285e26f56SDan Albert } 38385e26f56SDan Albert 38485e26f56SDan Albert __ns_rep __result = __d.count() * __ratio::num / __ratio::den; 38585e26f56SDan Albert if (__result == 0) { 38685e26f56SDan Albert return nanoseconds(1); 38785e26f56SDan Albert } 38885e26f56SDan Albert 38985e26f56SDan Albert return nanoseconds(__result); 3903e519524SHoward Hinnant} 3913e519524SHoward Hinnant 392b3fcc67fSJonathan Roelofs#ifndef _LIBCPP_HAS_NO_THREADS 3933e519524SHoward Hinnanttemplate <class _Predicate> 3943e519524SHoward Hinnantvoid 3953e519524SHoward Hinnantcondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 3963e519524SHoward Hinnant{ 3973e519524SHoward Hinnant while (!__pred()) 3983e519524SHoward Hinnant wait(__lk); 3993e519524SHoward Hinnant} 4003e519524SHoward Hinnant 4013e519524SHoward Hinnanttemplate <class _Clock, class _Duration> 4023e519524SHoward Hinnantcv_status 4033e519524SHoward Hinnantcondition_variable::wait_until(unique_lock<mutex>& __lk, 4043e519524SHoward Hinnant const chrono::time_point<_Clock, _Duration>& __t) 4053e519524SHoward Hinnant{ 4063e519524SHoward Hinnant using namespace chrono; 40785e26f56SDan Albert using __clock_tp_ns = time_point<_Clock, nanoseconds>; 40885e26f56SDan Albert 40985e26f56SDan Albert typename _Clock::time_point __now = _Clock::now(); 41085e26f56SDan Albert if (__t <= __now) 41185e26f56SDan Albert return cv_status::timeout; 41285e26f56SDan Albert 413781c476cSArthur O'Dwyer __clock_tp_ns __t_ns = __clock_tp_ns(_VSTD::__safe_nanosecond_cast(__t.time_since_epoch())); 41485e26f56SDan Albert 41585e26f56SDan Albert __do_timed_wait(__lk, __t_ns); 4163e519524SHoward Hinnant return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 4173e519524SHoward Hinnant} 4183e519524SHoward Hinnant 4193e519524SHoward Hinnanttemplate <class _Clock, class _Duration, class _Predicate> 4203e519524SHoward Hinnantbool 4213e519524SHoward Hinnantcondition_variable::wait_until(unique_lock<mutex>& __lk, 4223e519524SHoward Hinnant const chrono::time_point<_Clock, _Duration>& __t, 4233e519524SHoward Hinnant _Predicate __pred) 4243e519524SHoward Hinnant{ 4253e519524SHoward Hinnant while (!__pred()) 4263e519524SHoward Hinnant { 4273e519524SHoward Hinnant if (wait_until(__lk, __t) == cv_status::timeout) 4283e519524SHoward Hinnant return __pred(); 4293e519524SHoward Hinnant } 4303e519524SHoward Hinnant return true; 4313e519524SHoward Hinnant} 4323e519524SHoward Hinnant 4333e519524SHoward Hinnanttemplate <class _Rep, class _Period> 4343e519524SHoward Hinnantcv_status 4353e519524SHoward Hinnantcondition_variable::wait_for(unique_lock<mutex>& __lk, 4363e519524SHoward Hinnant const chrono::duration<_Rep, _Period>& __d) 4373e519524SHoward Hinnant{ 4383e519524SHoward Hinnant using namespace chrono; 439aad745a0SHoward Hinnant if (__d <= __d.zero()) 440aad745a0SHoward Hinnant return cv_status::timeout; 44185e26f56SDan Albert using __ns_rep = nanoseconds::rep; 4423dc6455fSHoward Hinnant steady_clock::time_point __c_now = steady_clock::now(); 44385e26f56SDan Albert 44485e26f56SDan Albert#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 44585e26f56SDan Albert using __clock_tp_ns = time_point<steady_clock, nanoseconds>; 446781c476cSArthur O'Dwyer __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); 44785e26f56SDan Albert#else 44885e26f56SDan Albert using __clock_tp_ns = time_point<system_clock, nanoseconds>; 449781c476cSArthur O'Dwyer __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); 45085e26f56SDan Albert#endif 45185e26f56SDan Albert 452781c476cSArthur O'Dwyer __ns_rep __d_ns_count = _VSTD::__safe_nanosecond_cast(__d).count(); 45385e26f56SDan Albert 45485e26f56SDan Albert if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { 45585e26f56SDan Albert __do_timed_wait(__lk, __clock_tp_ns::max()); 45685e26f56SDan Albert } else { 45785e26f56SDan Albert __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); 45885e26f56SDan Albert } 45985e26f56SDan Albert 4603dc6455fSHoward Hinnant return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 4613e519524SHoward Hinnant cv_status::timeout; 4623e519524SHoward Hinnant} 4633e519524SHoward Hinnant 4643e519524SHoward Hinnanttemplate <class _Rep, class _Period, class _Predicate> 465906c872dSEvgeniy Stepanovinline 4663e519524SHoward Hinnantbool 4673e519524SHoward Hinnantcondition_variable::wait_for(unique_lock<mutex>& __lk, 4683e519524SHoward Hinnant const chrono::duration<_Rep, _Period>& __d, 4693e519524SHoward Hinnant _Predicate __pred) 4703e519524SHoward Hinnant{ 4713dc6455fSHoward Hinnant return wait_until(__lk, chrono::steady_clock::now() + __d, 472ce48a113SHoward Hinnant _VSTD::move(__pred)); 4733e519524SHoward Hinnant} 4743e519524SHoward Hinnant 47585e26f56SDan Albert#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 47685e26f56SDan Albertinline 47785e26f56SDan Albertvoid 47885e26f56SDan Albertcondition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 47985e26f56SDan Albert chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT 48085e26f56SDan Albert{ 48185e26f56SDan Albert using namespace chrono; 48285e26f56SDan Albert if (!__lk.owns_lock()) 48385e26f56SDan Albert __throw_system_error(EPERM, 48485e26f56SDan Albert "condition_variable::timed wait: mutex not locked"); 48585e26f56SDan Albert nanoseconds __d = __tp.time_since_epoch(); 48685e26f56SDan Albert timespec __ts; 48785e26f56SDan Albert seconds __s = duration_cast<seconds>(__d); 48885e26f56SDan Albert using __ts_sec = decltype(__ts.tv_sec); 48985e26f56SDan Albert const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 49085e26f56SDan Albert if (__s.count() < __ts_sec_max) 49185e26f56SDan Albert { 49285e26f56SDan Albert __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 49385e26f56SDan Albert __ts.tv_nsec = (__d - __s).count(); 49485e26f56SDan Albert } 49585e26f56SDan Albert else 49685e26f56SDan Albert { 49785e26f56SDan Albert __ts.tv_sec = __ts_sec_max; 49885e26f56SDan Albert __ts.tv_nsec = giga::num - 1; 49985e26f56SDan Albert } 50085e26f56SDan Albert int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts); 50185e26f56SDan Albert if (__ec != 0 && __ec != ETIMEDOUT) 50285e26f56SDan Albert __throw_system_error(__ec, "condition_variable timed_wait failed"); 50385e26f56SDan Albert} 50485e26f56SDan Albert#endif // _LIBCPP_HAS_COND_CLOCKWAIT 50585e26f56SDan Albert 50685e26f56SDan Alberttemplate <class _Clock> 50785e26f56SDan Albertinline 50885e26f56SDan Albertvoid 50985e26f56SDan Albertcondition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 51085e26f56SDan Albert chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT 51185e26f56SDan Albert{ 51285e26f56SDan Albert wait_for(__lk, __tp - _Clock::now()); 51385e26f56SDan Albert} 51485e26f56SDan Albert 515b3fcc67fSJonathan Roelofs#endif // !_LIBCPP_HAS_NO_THREADS 516b3fcc67fSJonathan Roelofs 5173e519524SHoward Hinnant_LIBCPP_END_NAMESPACE_STD 5183e519524SHoward Hinnant 519a016efb1SEric Fiselier_LIBCPP_POP_MACROS 520a016efb1SEric Fiselier 5213e519524SHoward Hinnant#endif // _LIBCPP___MUTEX_BASE 522