xref: /openbsd-src/gnu/llvm/libcxx/include/__mutex_base (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
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