xref: /netbsd-src/external/apache2/llvm/dist/libcxx/include/__mutex_base (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
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