1*4d6fc14bSjoerg// -*- C++ -*- 2*4d6fc14bSjoerg//===----------------------------------------------------------------------===// 3*4d6fc14bSjoerg// 4*4d6fc14bSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*4d6fc14bSjoerg// See https://llvm.org/LICENSE.txt for license information. 6*4d6fc14bSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*4d6fc14bSjoerg// 8*4d6fc14bSjoerg//===----------------------------------------------------------------------===// 9*4d6fc14bSjoerg 10*4d6fc14bSjoerg#ifndef _LIBCPP___MUTEX_BASE 11*4d6fc14bSjoerg#define _LIBCPP___MUTEX_BASE 12*4d6fc14bSjoerg 13*4d6fc14bSjoerg#include <__config> 14*4d6fc14bSjoerg#include <chrono> 15*4d6fc14bSjoerg#include <system_error> 16*4d6fc14bSjoerg#include <__threading_support> 17*4d6fc14bSjoerg 18*4d6fc14bSjoerg#include <time.h> 19*4d6fc14bSjoerg 20*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21*4d6fc14bSjoerg#pragma GCC system_header 22*4d6fc14bSjoerg#endif 23*4d6fc14bSjoerg 24*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS 25*4d6fc14bSjoerg#include <__undef_macros> 26*4d6fc14bSjoerg 27*4d6fc14bSjoerg 28*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD 29*4d6fc14bSjoerg 30*4d6fc14bSjoerg#ifndef _LIBCPP_HAS_NO_THREADS 31*4d6fc14bSjoerg 32*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex 33*4d6fc14bSjoerg{ 34*4d6fc14bSjoerg __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; 35*4d6fc14bSjoerg 36*4d6fc14bSjoergpublic: 37*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 38*4d6fc14bSjoerg _LIBCPP_CONSTEXPR mutex() = default; 39*4d6fc14bSjoerg 40*4d6fc14bSjoerg mutex(const mutex&) = delete; 41*4d6fc14bSjoerg mutex& operator=(const mutex&) = delete; 42*4d6fc14bSjoerg 43*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) 44*4d6fc14bSjoerg ~mutex() = default; 45*4d6fc14bSjoerg#else 46*4d6fc14bSjoerg ~mutex() _NOEXCEPT; 47*4d6fc14bSjoerg#endif 48*4d6fc14bSjoerg 49*4d6fc14bSjoerg void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); 50*4d6fc14bSjoerg bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); 51*4d6fc14bSjoerg void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); 52*4d6fc14bSjoerg 53*4d6fc14bSjoerg typedef __libcpp_mutex_t* native_handle_type; 54*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 55*4d6fc14bSjoerg}; 56*4d6fc14bSjoerg 57*4d6fc14bSjoergstatic_assert(is_nothrow_default_constructible<mutex>::value, 58*4d6fc14bSjoerg "the default constructor for std::mutex must be nothrow"); 59*4d6fc14bSjoerg 60*4d6fc14bSjoergstruct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; }; 61*4d6fc14bSjoergstruct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; }; 62*4d6fc14bSjoergstruct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; }; 63*4d6fc14bSjoerg 64*4d6fc14bSjoerg#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) 65*4d6fc14bSjoerg 66*4d6fc14bSjoergextern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock; 67*4d6fc14bSjoergextern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock; 68*4d6fc14bSjoergextern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock; 69*4d6fc14bSjoerg 70*4d6fc14bSjoerg#else 71*4d6fc14bSjoerg 72*4d6fc14bSjoerg/* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t defer_lock = defer_lock_t(); 73*4d6fc14bSjoerg/* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t(); 74*4d6fc14bSjoerg/* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t adopt_lock = adopt_lock_t(); 75*4d6fc14bSjoerg 76*4d6fc14bSjoerg#endif 77*4d6fc14bSjoerg 78*4d6fc14bSjoergtemplate <class _Mutex> 79*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) 80*4d6fc14bSjoerglock_guard 81*4d6fc14bSjoerg{ 82*4d6fc14bSjoergpublic: 83*4d6fc14bSjoerg typedef _Mutex mutex_type; 84*4d6fc14bSjoerg 85*4d6fc14bSjoergprivate: 86*4d6fc14bSjoerg mutex_type& __m_; 87*4d6fc14bSjoergpublic: 88*4d6fc14bSjoerg 89*4d6fc14bSjoerg _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 90*4d6fc14bSjoerg explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 91*4d6fc14bSjoerg : __m_(__m) {__m_.lock();} 92*4d6fc14bSjoerg 93*4d6fc14bSjoerg _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 94*4d6fc14bSjoerg lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 95*4d6fc14bSjoerg : __m_(__m) {} 96*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 97*4d6fc14bSjoerg ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 98*4d6fc14bSjoerg 99*4d6fc14bSjoergprivate: 100*4d6fc14bSjoerg lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE; 101*4d6fc14bSjoerg lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE; 102*4d6fc14bSjoerg}; 103*4d6fc14bSjoerg 104*4d6fc14bSjoergtemplate <class _Mutex> 105*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS unique_lock 106*4d6fc14bSjoerg{ 107*4d6fc14bSjoergpublic: 108*4d6fc14bSjoerg typedef _Mutex mutex_type; 109*4d6fc14bSjoerg 110*4d6fc14bSjoergprivate: 111*4d6fc14bSjoerg mutex_type* __m_; 112*4d6fc14bSjoerg bool __owns_; 113*4d6fc14bSjoerg 114*4d6fc14bSjoergpublic: 115*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 116*4d6fc14bSjoerg unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 117*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 118*4d6fc14bSjoerg explicit unique_lock(mutex_type& __m) 119*4d6fc14bSjoerg : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} 120*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 121*4d6fc14bSjoerg unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 122*4d6fc14bSjoerg : __m_(_VSTD::addressof(__m)), __owns_(false) {} 123*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 124*4d6fc14bSjoerg unique_lock(mutex_type& __m, try_to_lock_t) 125*4d6fc14bSjoerg : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} 126*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 127*4d6fc14bSjoerg unique_lock(mutex_type& __m, adopt_lock_t) 128*4d6fc14bSjoerg : __m_(_VSTD::addressof(__m)), __owns_(true) {} 129*4d6fc14bSjoerg template <class _Clock, class _Duration> 130*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 131*4d6fc14bSjoerg unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 132*4d6fc14bSjoerg : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} 133*4d6fc14bSjoerg template <class _Rep, class _Period> 134*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 135*4d6fc14bSjoerg unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 136*4d6fc14bSjoerg : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} 137*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 138*4d6fc14bSjoerg ~unique_lock() 139*4d6fc14bSjoerg { 140*4d6fc14bSjoerg if (__owns_) 141*4d6fc14bSjoerg __m_->unlock(); 142*4d6fc14bSjoerg } 143*4d6fc14bSjoerg 144*4d6fc14bSjoergprivate: 145*4d6fc14bSjoerg unique_lock(unique_lock const&); // = delete; 146*4d6fc14bSjoerg unique_lock& operator=(unique_lock const&); // = delete; 147*4d6fc14bSjoerg 148*4d6fc14bSjoergpublic: 149*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 150*4d6fc14bSjoerg unique_lock(unique_lock&& __u) _NOEXCEPT 151*4d6fc14bSjoerg : __m_(__u.__m_), __owns_(__u.__owns_) 152*4d6fc14bSjoerg {__u.__m_ = nullptr; __u.__owns_ = false;} 153*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 154*4d6fc14bSjoerg unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 155*4d6fc14bSjoerg { 156*4d6fc14bSjoerg if (__owns_) 157*4d6fc14bSjoerg __m_->unlock(); 158*4d6fc14bSjoerg __m_ = __u.__m_; 159*4d6fc14bSjoerg __owns_ = __u.__owns_; 160*4d6fc14bSjoerg __u.__m_ = nullptr; 161*4d6fc14bSjoerg __u.__owns_ = false; 162*4d6fc14bSjoerg return *this; 163*4d6fc14bSjoerg } 164*4d6fc14bSjoerg 165*4d6fc14bSjoerg void lock(); 166*4d6fc14bSjoerg bool try_lock(); 167*4d6fc14bSjoerg 168*4d6fc14bSjoerg template <class _Rep, class _Period> 169*4d6fc14bSjoerg bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 170*4d6fc14bSjoerg template <class _Clock, class _Duration> 171*4d6fc14bSjoerg bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 172*4d6fc14bSjoerg 173*4d6fc14bSjoerg void unlock(); 174*4d6fc14bSjoerg 175*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 176*4d6fc14bSjoerg void swap(unique_lock& __u) _NOEXCEPT 177*4d6fc14bSjoerg { 178*4d6fc14bSjoerg _VSTD::swap(__m_, __u.__m_); 179*4d6fc14bSjoerg _VSTD::swap(__owns_, __u.__owns_); 180*4d6fc14bSjoerg } 181*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 182*4d6fc14bSjoerg mutex_type* release() _NOEXCEPT 183*4d6fc14bSjoerg { 184*4d6fc14bSjoerg mutex_type* __m = __m_; 185*4d6fc14bSjoerg __m_ = nullptr; 186*4d6fc14bSjoerg __owns_ = false; 187*4d6fc14bSjoerg return __m; 188*4d6fc14bSjoerg } 189*4d6fc14bSjoerg 190*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 191*4d6fc14bSjoerg bool owns_lock() const _NOEXCEPT {return __owns_;} 192*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 193*4d6fc14bSjoerg _LIBCPP_EXPLICIT 194*4d6fc14bSjoerg operator bool () const _NOEXCEPT {return __owns_;} 195*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 196*4d6fc14bSjoerg mutex_type* mutex() const _NOEXCEPT {return __m_;} 197*4d6fc14bSjoerg}; 198*4d6fc14bSjoerg 199*4d6fc14bSjoergtemplate <class _Mutex> 200*4d6fc14bSjoergvoid 201*4d6fc14bSjoergunique_lock<_Mutex>::lock() 202*4d6fc14bSjoerg{ 203*4d6fc14bSjoerg if (__m_ == nullptr) 204*4d6fc14bSjoerg __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 205*4d6fc14bSjoerg if (__owns_) 206*4d6fc14bSjoerg __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 207*4d6fc14bSjoerg __m_->lock(); 208*4d6fc14bSjoerg __owns_ = true; 209*4d6fc14bSjoerg} 210*4d6fc14bSjoerg 211*4d6fc14bSjoergtemplate <class _Mutex> 212*4d6fc14bSjoergbool 213*4d6fc14bSjoergunique_lock<_Mutex>::try_lock() 214*4d6fc14bSjoerg{ 215*4d6fc14bSjoerg if (__m_ == nullptr) 216*4d6fc14bSjoerg __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 217*4d6fc14bSjoerg if (__owns_) 218*4d6fc14bSjoerg __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 219*4d6fc14bSjoerg __owns_ = __m_->try_lock(); 220*4d6fc14bSjoerg return __owns_; 221*4d6fc14bSjoerg} 222*4d6fc14bSjoerg 223*4d6fc14bSjoergtemplate <class _Mutex> 224*4d6fc14bSjoergtemplate <class _Rep, class _Period> 225*4d6fc14bSjoergbool 226*4d6fc14bSjoergunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 227*4d6fc14bSjoerg{ 228*4d6fc14bSjoerg if (__m_ == nullptr) 229*4d6fc14bSjoerg __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 230*4d6fc14bSjoerg if (__owns_) 231*4d6fc14bSjoerg __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 232*4d6fc14bSjoerg __owns_ = __m_->try_lock_for(__d); 233*4d6fc14bSjoerg return __owns_; 234*4d6fc14bSjoerg} 235*4d6fc14bSjoerg 236*4d6fc14bSjoergtemplate <class _Mutex> 237*4d6fc14bSjoergtemplate <class _Clock, class _Duration> 238*4d6fc14bSjoergbool 239*4d6fc14bSjoergunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 240*4d6fc14bSjoerg{ 241*4d6fc14bSjoerg if (__m_ == nullptr) 242*4d6fc14bSjoerg __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 243*4d6fc14bSjoerg if (__owns_) 244*4d6fc14bSjoerg __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 245*4d6fc14bSjoerg __owns_ = __m_->try_lock_until(__t); 246*4d6fc14bSjoerg return __owns_; 247*4d6fc14bSjoerg} 248*4d6fc14bSjoerg 249*4d6fc14bSjoergtemplate <class _Mutex> 250*4d6fc14bSjoergvoid 251*4d6fc14bSjoergunique_lock<_Mutex>::unlock() 252*4d6fc14bSjoerg{ 253*4d6fc14bSjoerg if (!__owns_) 254*4d6fc14bSjoerg __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 255*4d6fc14bSjoerg __m_->unlock(); 256*4d6fc14bSjoerg __owns_ = false; 257*4d6fc14bSjoerg} 258*4d6fc14bSjoerg 259*4d6fc14bSjoergtemplate <class _Mutex> 260*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 261*4d6fc14bSjoergvoid 262*4d6fc14bSjoergswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 263*4d6fc14bSjoerg {__x.swap(__y);} 264*4d6fc14bSjoerg 265*4d6fc14bSjoerg//enum class cv_status 266*4d6fc14bSjoerg_LIBCPP_DECLARE_STRONG_ENUM(cv_status) 267*4d6fc14bSjoerg{ 268*4d6fc14bSjoerg no_timeout, 269*4d6fc14bSjoerg timeout 270*4d6fc14bSjoerg}; 271*4d6fc14bSjoerg_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) 272*4d6fc14bSjoerg 273*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS condition_variable 274*4d6fc14bSjoerg{ 275*4d6fc14bSjoerg __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; 276*4d6fc14bSjoergpublic: 277*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 278*4d6fc14bSjoerg _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; 279*4d6fc14bSjoerg 280*4d6fc14bSjoerg#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION 281*4d6fc14bSjoerg ~condition_variable() = default; 282*4d6fc14bSjoerg#else 283*4d6fc14bSjoerg ~condition_variable(); 284*4d6fc14bSjoerg#endif 285*4d6fc14bSjoerg 286*4d6fc14bSjoerg condition_variable(const condition_variable&) = delete; 287*4d6fc14bSjoerg condition_variable& operator=(const condition_variable&) = delete; 288*4d6fc14bSjoerg 289*4d6fc14bSjoerg void notify_one() _NOEXCEPT; 290*4d6fc14bSjoerg void notify_all() _NOEXCEPT; 291*4d6fc14bSjoerg 292*4d6fc14bSjoerg void wait(unique_lock<mutex>& __lk) _NOEXCEPT; 293*4d6fc14bSjoerg template <class _Predicate> 294*4d6fc14bSjoerg _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 295*4d6fc14bSjoerg void wait(unique_lock<mutex>& __lk, _Predicate __pred); 296*4d6fc14bSjoerg 297*4d6fc14bSjoerg template <class _Clock, class _Duration> 298*4d6fc14bSjoerg _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 299*4d6fc14bSjoerg cv_status 300*4d6fc14bSjoerg wait_until(unique_lock<mutex>& __lk, 301*4d6fc14bSjoerg const chrono::time_point<_Clock, _Duration>& __t); 302*4d6fc14bSjoerg 303*4d6fc14bSjoerg template <class _Clock, class _Duration, class _Predicate> 304*4d6fc14bSjoerg _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 305*4d6fc14bSjoerg bool 306*4d6fc14bSjoerg wait_until(unique_lock<mutex>& __lk, 307*4d6fc14bSjoerg const chrono::time_point<_Clock, _Duration>& __t, 308*4d6fc14bSjoerg _Predicate __pred); 309*4d6fc14bSjoerg 310*4d6fc14bSjoerg template <class _Rep, class _Period> 311*4d6fc14bSjoerg _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 312*4d6fc14bSjoerg cv_status 313*4d6fc14bSjoerg wait_for(unique_lock<mutex>& __lk, 314*4d6fc14bSjoerg const chrono::duration<_Rep, _Period>& __d); 315*4d6fc14bSjoerg 316*4d6fc14bSjoerg template <class _Rep, class _Period, class _Predicate> 317*4d6fc14bSjoerg bool 318*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 319*4d6fc14bSjoerg wait_for(unique_lock<mutex>& __lk, 320*4d6fc14bSjoerg const chrono::duration<_Rep, _Period>& __d, 321*4d6fc14bSjoerg _Predicate __pred); 322*4d6fc14bSjoerg 323*4d6fc14bSjoerg typedef __libcpp_condvar_t* native_handle_type; 324*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 325*4d6fc14bSjoerg 326*4d6fc14bSjoergprivate: 327*4d6fc14bSjoerg void __do_timed_wait(unique_lock<mutex>& __lk, 328*4d6fc14bSjoerg chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; 329*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 330*4d6fc14bSjoerg void __do_timed_wait(unique_lock<mutex>& __lk, 331*4d6fc14bSjoerg chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT; 332*4d6fc14bSjoerg#endif 333*4d6fc14bSjoerg template <class _Clock> 334*4d6fc14bSjoerg void __do_timed_wait(unique_lock<mutex>& __lk, 335*4d6fc14bSjoerg chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; 336*4d6fc14bSjoerg}; 337*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_NO_THREADS 338*4d6fc14bSjoerg 339*4d6fc14bSjoergtemplate <class _Rep, class _Period> 340*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 341*4d6fc14bSjoergtypename enable_if 342*4d6fc14bSjoerg< 343*4d6fc14bSjoerg is_floating_point<_Rep>::value, 344*4d6fc14bSjoerg chrono::nanoseconds 345*4d6fc14bSjoerg>::type 346*4d6fc14bSjoerg__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 347*4d6fc14bSjoerg{ 348*4d6fc14bSjoerg using namespace chrono; 349*4d6fc14bSjoerg using __ratio = ratio_divide<_Period, nano>; 350*4d6fc14bSjoerg using __ns_rep = nanoseconds::rep; 351*4d6fc14bSjoerg _Rep __result_float = __d.count() * __ratio::num / __ratio::den; 352*4d6fc14bSjoerg 353*4d6fc14bSjoerg _Rep __result_max = numeric_limits<__ns_rep>::max(); 354*4d6fc14bSjoerg if (__result_float >= __result_max) { 355*4d6fc14bSjoerg return nanoseconds::max(); 356*4d6fc14bSjoerg } 357*4d6fc14bSjoerg 358*4d6fc14bSjoerg _Rep __result_min = numeric_limits<__ns_rep>::min(); 359*4d6fc14bSjoerg if (__result_float <= __result_min) { 360*4d6fc14bSjoerg return nanoseconds::min(); 361*4d6fc14bSjoerg } 362*4d6fc14bSjoerg 363*4d6fc14bSjoerg return nanoseconds(static_cast<__ns_rep>(__result_float)); 364*4d6fc14bSjoerg} 365*4d6fc14bSjoerg 366*4d6fc14bSjoergtemplate <class _Rep, class _Period> 367*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 368*4d6fc14bSjoergtypename enable_if 369*4d6fc14bSjoerg< 370*4d6fc14bSjoerg !is_floating_point<_Rep>::value, 371*4d6fc14bSjoerg chrono::nanoseconds 372*4d6fc14bSjoerg>::type 373*4d6fc14bSjoerg__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 374*4d6fc14bSjoerg{ 375*4d6fc14bSjoerg using namespace chrono; 376*4d6fc14bSjoerg if (__d.count() == 0) { 377*4d6fc14bSjoerg return nanoseconds(0); 378*4d6fc14bSjoerg } 379*4d6fc14bSjoerg 380*4d6fc14bSjoerg using __ratio = ratio_divide<_Period, nano>; 381*4d6fc14bSjoerg using __ns_rep = nanoseconds::rep; 382*4d6fc14bSjoerg __ns_rep __result_max = numeric_limits<__ns_rep>::max(); 383*4d6fc14bSjoerg if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { 384*4d6fc14bSjoerg return nanoseconds::max(); 385*4d6fc14bSjoerg } 386*4d6fc14bSjoerg 387*4d6fc14bSjoerg __ns_rep __result_min = numeric_limits<__ns_rep>::min(); 388*4d6fc14bSjoerg if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { 389*4d6fc14bSjoerg return nanoseconds::min(); 390*4d6fc14bSjoerg } 391*4d6fc14bSjoerg 392*4d6fc14bSjoerg __ns_rep __result = __d.count() * __ratio::num / __ratio::den; 393*4d6fc14bSjoerg if (__result == 0) { 394*4d6fc14bSjoerg return nanoseconds(1); 395*4d6fc14bSjoerg } 396*4d6fc14bSjoerg 397*4d6fc14bSjoerg return nanoseconds(__result); 398*4d6fc14bSjoerg} 399*4d6fc14bSjoerg 400*4d6fc14bSjoerg#ifndef _LIBCPP_HAS_NO_THREADS 401*4d6fc14bSjoergtemplate <class _Predicate> 402*4d6fc14bSjoergvoid 403*4d6fc14bSjoergcondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 404*4d6fc14bSjoerg{ 405*4d6fc14bSjoerg while (!__pred()) 406*4d6fc14bSjoerg wait(__lk); 407*4d6fc14bSjoerg} 408*4d6fc14bSjoerg 409*4d6fc14bSjoergtemplate <class _Clock, class _Duration> 410*4d6fc14bSjoergcv_status 411*4d6fc14bSjoergcondition_variable::wait_until(unique_lock<mutex>& __lk, 412*4d6fc14bSjoerg const chrono::time_point<_Clock, _Duration>& __t) 413*4d6fc14bSjoerg{ 414*4d6fc14bSjoerg using namespace chrono; 415*4d6fc14bSjoerg using __clock_tp_ns = time_point<_Clock, nanoseconds>; 416*4d6fc14bSjoerg 417*4d6fc14bSjoerg typename _Clock::time_point __now = _Clock::now(); 418*4d6fc14bSjoerg if (__t <= __now) 419*4d6fc14bSjoerg return cv_status::timeout; 420*4d6fc14bSjoerg 421*4d6fc14bSjoerg __clock_tp_ns __t_ns = __clock_tp_ns(_VSTD::__safe_nanosecond_cast(__t.time_since_epoch())); 422*4d6fc14bSjoerg 423*4d6fc14bSjoerg __do_timed_wait(__lk, __t_ns); 424*4d6fc14bSjoerg return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 425*4d6fc14bSjoerg} 426*4d6fc14bSjoerg 427*4d6fc14bSjoergtemplate <class _Clock, class _Duration, class _Predicate> 428*4d6fc14bSjoergbool 429*4d6fc14bSjoergcondition_variable::wait_until(unique_lock<mutex>& __lk, 430*4d6fc14bSjoerg const chrono::time_point<_Clock, _Duration>& __t, 431*4d6fc14bSjoerg _Predicate __pred) 432*4d6fc14bSjoerg{ 433*4d6fc14bSjoerg while (!__pred()) 434*4d6fc14bSjoerg { 435*4d6fc14bSjoerg if (wait_until(__lk, __t) == cv_status::timeout) 436*4d6fc14bSjoerg return __pred(); 437*4d6fc14bSjoerg } 438*4d6fc14bSjoerg return true; 439*4d6fc14bSjoerg} 440*4d6fc14bSjoerg 441*4d6fc14bSjoergtemplate <class _Rep, class _Period> 442*4d6fc14bSjoergcv_status 443*4d6fc14bSjoergcondition_variable::wait_for(unique_lock<mutex>& __lk, 444*4d6fc14bSjoerg const chrono::duration<_Rep, _Period>& __d) 445*4d6fc14bSjoerg{ 446*4d6fc14bSjoerg using namespace chrono; 447*4d6fc14bSjoerg if (__d <= __d.zero()) 448*4d6fc14bSjoerg return cv_status::timeout; 449*4d6fc14bSjoerg using __ns_rep = nanoseconds::rep; 450*4d6fc14bSjoerg steady_clock::time_point __c_now = steady_clock::now(); 451*4d6fc14bSjoerg 452*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 453*4d6fc14bSjoerg using __clock_tp_ns = time_point<steady_clock, nanoseconds>; 454*4d6fc14bSjoerg __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); 455*4d6fc14bSjoerg#else 456*4d6fc14bSjoerg using __clock_tp_ns = time_point<system_clock, nanoseconds>; 457*4d6fc14bSjoerg __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); 458*4d6fc14bSjoerg#endif 459*4d6fc14bSjoerg 460*4d6fc14bSjoerg __ns_rep __d_ns_count = _VSTD::__safe_nanosecond_cast(__d).count(); 461*4d6fc14bSjoerg 462*4d6fc14bSjoerg if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { 463*4d6fc14bSjoerg __do_timed_wait(__lk, __clock_tp_ns::max()); 464*4d6fc14bSjoerg } else { 465*4d6fc14bSjoerg __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); 466*4d6fc14bSjoerg } 467*4d6fc14bSjoerg 468*4d6fc14bSjoerg return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 469*4d6fc14bSjoerg cv_status::timeout; 470*4d6fc14bSjoerg} 471*4d6fc14bSjoerg 472*4d6fc14bSjoergtemplate <class _Rep, class _Period, class _Predicate> 473*4d6fc14bSjoerginline 474*4d6fc14bSjoergbool 475*4d6fc14bSjoergcondition_variable::wait_for(unique_lock<mutex>& __lk, 476*4d6fc14bSjoerg const chrono::duration<_Rep, _Period>& __d, 477*4d6fc14bSjoerg _Predicate __pred) 478*4d6fc14bSjoerg{ 479*4d6fc14bSjoerg return wait_until(__lk, chrono::steady_clock::now() + __d, 480*4d6fc14bSjoerg _VSTD::move(__pred)); 481*4d6fc14bSjoerg} 482*4d6fc14bSjoerg 483*4d6fc14bSjoerg#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 484*4d6fc14bSjoerginline 485*4d6fc14bSjoergvoid 486*4d6fc14bSjoergcondition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 487*4d6fc14bSjoerg chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT 488*4d6fc14bSjoerg{ 489*4d6fc14bSjoerg using namespace chrono; 490*4d6fc14bSjoerg if (!__lk.owns_lock()) 491*4d6fc14bSjoerg __throw_system_error(EPERM, 492*4d6fc14bSjoerg "condition_variable::timed wait: mutex not locked"); 493*4d6fc14bSjoerg nanoseconds __d = __tp.time_since_epoch(); 494*4d6fc14bSjoerg timespec __ts; 495*4d6fc14bSjoerg seconds __s = duration_cast<seconds>(__d); 496*4d6fc14bSjoerg using __ts_sec = decltype(__ts.tv_sec); 497*4d6fc14bSjoerg const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 498*4d6fc14bSjoerg if (__s.count() < __ts_sec_max) 499*4d6fc14bSjoerg { 500*4d6fc14bSjoerg __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 501*4d6fc14bSjoerg __ts.tv_nsec = (__d - __s).count(); 502*4d6fc14bSjoerg } 503*4d6fc14bSjoerg else 504*4d6fc14bSjoerg { 505*4d6fc14bSjoerg __ts.tv_sec = __ts_sec_max; 506*4d6fc14bSjoerg __ts.tv_nsec = giga::num - 1; 507*4d6fc14bSjoerg } 508*4d6fc14bSjoerg int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts); 509*4d6fc14bSjoerg if (__ec != 0 && __ec != ETIMEDOUT) 510*4d6fc14bSjoerg __throw_system_error(__ec, "condition_variable timed_wait failed"); 511*4d6fc14bSjoerg} 512*4d6fc14bSjoerg#endif // _LIBCPP_HAS_COND_CLOCKWAIT 513*4d6fc14bSjoerg 514*4d6fc14bSjoergtemplate <class _Clock> 515*4d6fc14bSjoerginline 516*4d6fc14bSjoergvoid 517*4d6fc14bSjoergcondition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 518*4d6fc14bSjoerg chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT 519*4d6fc14bSjoerg{ 520*4d6fc14bSjoerg wait_for(__lk, __tp - _Clock::now()); 521*4d6fc14bSjoerg} 522*4d6fc14bSjoerg 523*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_NO_THREADS 524*4d6fc14bSjoerg 525*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD 526*4d6fc14bSjoerg 527*4d6fc14bSjoerg_LIBCPP_POP_MACROS 528*4d6fc14bSjoerg 529*4d6fc14bSjoerg#endif // _LIBCPP___MUTEX_BASE 530