17a984708SDavid Chisnall// -*- C++ -*-
27a984708SDavid Chisnall//===----------------------------------------------------------------------===//
37a984708SDavid Chisnall//
47a984708SDavid Chisnall//                     The LLVM Compiler Infrastructure
57a984708SDavid Chisnall//
67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open
77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details.
87a984708SDavid Chisnall//
97a984708SDavid Chisnall//===----------------------------------------------------------------------===//
107a984708SDavid Chisnall
117a984708SDavid Chisnall#ifndef _LIBCPP___MUTEX_BASE
127a984708SDavid Chisnall#define _LIBCPP___MUTEX_BASE
137a984708SDavid Chisnall
147a984708SDavid Chisnall#include <__config>
157a984708SDavid Chisnall#include <chrono>
167a984708SDavid Chisnall#include <system_error>
177c82a1ecSDimitry Andric#include <__threading_support>
18f9448bf3SDimitry Andric
197a984708SDavid Chisnall
207a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
217a984708SDavid Chisnall#pragma GCC system_header
227a984708SDavid Chisnall#endif
237a984708SDavid Chisnall
24f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
25f9448bf3SDimitry Andric#include <__undef_macros>
26f9448bf3SDimitry Andric
27f9448bf3SDimitry Andric
287a984708SDavid Chisnall_LIBCPP_BEGIN_NAMESPACE_STD
297a984708SDavid Chisnall
30d72607e9SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS
31d72607e9SDimitry Andric
327c82a1ecSDimitry Andric#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
337c82a1ecSDimitry Andric#  ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
347c82a1ecSDimitry Andric#    define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
357c82a1ecSDimitry Andric#  else
367c82a1ecSDimitry Andric#    define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
377c82a1ecSDimitry Andric#  endif
387c82a1ecSDimitry Andric#endif  // _LIBCPP_THREAD_SAFETY_ANNOTATION
397c82a1ecSDimitry Andric
407c82a1ecSDimitry Andricclass _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
417a984708SDavid Chisnall{
42540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
437c82a1ecSDimitry Andric    __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
447c82a1ecSDimitry Andric#else
457c82a1ecSDimitry Andric    __libcpp_mutex_t __m_;
467c82a1ecSDimitry Andric#endif
477a984708SDavid Chisnall
487a984708SDavid Chisnallpublic:
497a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
50540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
51db17bf38SDimitry Andric    constexpr mutex() = default;
52936e9439SDimitry Andric#else
537c82a1ecSDimitry Andric    mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;}
54936e9439SDimitry Andric#endif
557a984708SDavid Chisnall    ~mutex();
567a984708SDavid Chisnall
577a984708SDavid Chisnallprivate:
587a984708SDavid Chisnall    mutex(const mutex&);// = delete;
597a984708SDavid Chisnall    mutex& operator=(const mutex&);// = delete;
607a984708SDavid Chisnall
617a984708SDavid Chisnallpublic:
627c82a1ecSDimitry Andric    void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
637c82a1ecSDimitry Andric    bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
647c82a1ecSDimitry Andric    void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
657a984708SDavid Chisnall
667c82a1ecSDimitry Andric    typedef __libcpp_mutex_t* native_handle_type;
677a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
687a984708SDavid Chisnall};
697a984708SDavid Chisnall
70db17bf38SDimitry Andricstatic_assert(is_nothrow_default_constructible<mutex>::value,
71db17bf38SDimitry Andric              "the default constructor for std::mutex must be nothrow");
72db17bf38SDimitry Andric
731bf9f7c1SDimitry Andricstruct _LIBCPP_TYPE_VIS defer_lock_t {};
741bf9f7c1SDimitry Andricstruct _LIBCPP_TYPE_VIS try_to_lock_t {};
751bf9f7c1SDimitry Andricstruct _LIBCPP_TYPE_VIS adopt_lock_t {};
767a984708SDavid Chisnall
774ba319b5SDimitry Andric#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
787a984708SDavid Chisnall
79*b5893f02SDimitry Andricextern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t  defer_lock;
80*b5893f02SDimitry Andricextern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
81*b5893f02SDimitry Andricextern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t  adopt_lock;
827a984708SDavid Chisnall
83936e9439SDimitry Andric#else
84936e9439SDimitry Andric
8530785c0eSDimitry Andric/* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t  defer_lock  = defer_lock_t();
8630785c0eSDimitry Andric/* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
8730785c0eSDimitry Andric/* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
88936e9439SDimitry Andric
89936e9439SDimitry Andric#endif
907a984708SDavid Chisnall
917a984708SDavid Chisnalltemplate <class _Mutex>
92aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
937c82a1ecSDimitry Andriclock_guard
947a984708SDavid Chisnall{
957a984708SDavid Chisnallpublic:
967a984708SDavid Chisnall    typedef _Mutex mutex_type;
977a984708SDavid Chisnall
987a984708SDavid Chisnallprivate:
997a984708SDavid Chisnall    mutex_type& __m_;
1007a984708SDavid Chisnallpublic:
1017a984708SDavid Chisnall
1027a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1037c82a1ecSDimitry Andric    explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
1047a984708SDavid Chisnall        : __m_(__m) {__m_.lock();}
1057a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1067c82a1ecSDimitry Andric    lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
1077a984708SDavid Chisnall        : __m_(__m) {}
1087a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1097c82a1ecSDimitry Andric    ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
1107a984708SDavid Chisnall
1117a984708SDavid Chisnallprivate:
1127c82a1ecSDimitry Andric    lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
1137c82a1ecSDimitry Andric    lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
1147a984708SDavid Chisnall};
1157a984708SDavid Chisnall
1167a984708SDavid Chisnalltemplate <class _Mutex>
117aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS unique_lock
1187a984708SDavid Chisnall{
1197a984708SDavid Chisnallpublic:
1207a984708SDavid Chisnall    typedef _Mutex mutex_type;
1217a984708SDavid Chisnall
1227a984708SDavid Chisnallprivate:
1237a984708SDavid Chisnall    mutex_type* __m_;
1247a984708SDavid Chisnall    bool __owns_;
1257a984708SDavid Chisnall
1267a984708SDavid Chisnallpublic:
1277a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
128936e9439SDimitry Andric    unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
1297a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1307a984708SDavid Chisnall    explicit unique_lock(mutex_type& __m)
1317c82a1ecSDimitry Andric        : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
1327a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
133936e9439SDimitry Andric    unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
1347c82a1ecSDimitry Andric        : __m_(_VSTD::addressof(__m)), __owns_(false) {}
1357a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1367a984708SDavid Chisnall    unique_lock(mutex_type& __m, try_to_lock_t)
1377c82a1ecSDimitry Andric        : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
1387a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1397a984708SDavid Chisnall    unique_lock(mutex_type& __m, adopt_lock_t)
1407c82a1ecSDimitry Andric        : __m_(_VSTD::addressof(__m)), __owns_(true) {}
1417a984708SDavid Chisnall    template <class _Clock, class _Duration>
1427a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1437a984708SDavid Chisnall        unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
1447c82a1ecSDimitry Andric            : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
1457a984708SDavid Chisnall    template <class _Rep, class _Period>
1467a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1477a984708SDavid Chisnall        unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
1487c82a1ecSDimitry Andric            : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
1497a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1507a984708SDavid Chisnall    ~unique_lock()
1517a984708SDavid Chisnall    {
1527a984708SDavid Chisnall        if (__owns_)
1537a984708SDavid Chisnall            __m_->unlock();
1547a984708SDavid Chisnall    }
1557a984708SDavid Chisnall
1567a984708SDavid Chisnallprivate:
1577a984708SDavid Chisnall    unique_lock(unique_lock const&); // = delete;
1587a984708SDavid Chisnall    unique_lock& operator=(unique_lock const&); // = delete;
1597a984708SDavid Chisnall
1607a984708SDavid Chisnallpublic:
161540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
1627a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
163936e9439SDimitry Andric    unique_lock(unique_lock&& __u) _NOEXCEPT
1647a984708SDavid Chisnall        : __m_(__u.__m_), __owns_(__u.__owns_)
1657a984708SDavid Chisnall        {__u.__m_ = nullptr; __u.__owns_ = false;}
1667a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
167936e9439SDimitry Andric    unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
1687a984708SDavid Chisnall        {
1697a984708SDavid Chisnall            if (__owns_)
1707a984708SDavid Chisnall                __m_->unlock();
1717a984708SDavid Chisnall            __m_ = __u.__m_;
1727a984708SDavid Chisnall            __owns_ = __u.__owns_;
1737a984708SDavid Chisnall            __u.__m_ = nullptr;
1747a984708SDavid Chisnall            __u.__owns_ = false;
1757a984708SDavid Chisnall            return *this;
1767a984708SDavid Chisnall        }
1777a984708SDavid Chisnall
178540d2a8bSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
1797a984708SDavid Chisnall
1807a984708SDavid Chisnall    void lock();
1817a984708SDavid Chisnall    bool try_lock();
1827a984708SDavid Chisnall
1837a984708SDavid Chisnall    template <class _Rep, class _Period>
1847a984708SDavid Chisnall        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
1857a984708SDavid Chisnall    template <class _Clock, class _Duration>
1867a984708SDavid Chisnall        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
1877a984708SDavid Chisnall
1887a984708SDavid Chisnall    void unlock();
1897a984708SDavid Chisnall
1907a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
191936e9439SDimitry Andric    void swap(unique_lock& __u) _NOEXCEPT
1927a984708SDavid Chisnall    {
1937a984708SDavid Chisnall        _VSTD::swap(__m_, __u.__m_);
1947a984708SDavid Chisnall        _VSTD::swap(__owns_, __u.__owns_);
1957a984708SDavid Chisnall    }
1967a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
197936e9439SDimitry Andric    mutex_type* release() _NOEXCEPT
1987a984708SDavid Chisnall    {
1997a984708SDavid Chisnall        mutex_type* __m = __m_;
2007a984708SDavid Chisnall        __m_ = nullptr;
2017a984708SDavid Chisnall        __owns_ = false;
2027a984708SDavid Chisnall        return __m;
2037a984708SDavid Chisnall    }
2047a984708SDavid Chisnall
2057a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
206936e9439SDimitry Andric    bool owns_lock() const _NOEXCEPT {return __owns_;}
2077a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
20894e3ee44SDavid Chisnall    _LIBCPP_EXPLICIT
209936e9439SDimitry Andric        operator bool () const _NOEXCEPT {return __owns_;}
2107a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
211936e9439SDimitry Andric    mutex_type* mutex() const _NOEXCEPT {return __m_;}
2127a984708SDavid Chisnall};
2137a984708SDavid Chisnall
2147a984708SDavid Chisnalltemplate <class _Mutex>
2157a984708SDavid Chisnallvoid
2167a984708SDavid Chisnallunique_lock<_Mutex>::lock()
2177a984708SDavid Chisnall{
2187a984708SDavid Chisnall    if (__m_ == nullptr)
2197a984708SDavid Chisnall        __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
2207a984708SDavid Chisnall    if (__owns_)
2217a984708SDavid Chisnall        __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
2227a984708SDavid Chisnall    __m_->lock();
2237a984708SDavid Chisnall    __owns_ = true;
2247a984708SDavid Chisnall}
2257a984708SDavid Chisnall
2267a984708SDavid Chisnalltemplate <class _Mutex>
2277a984708SDavid Chisnallbool
2287a984708SDavid Chisnallunique_lock<_Mutex>::try_lock()
2297a984708SDavid Chisnall{
2307a984708SDavid Chisnall    if (__m_ == nullptr)
2317a984708SDavid Chisnall        __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
2327a984708SDavid Chisnall    if (__owns_)
2337a984708SDavid Chisnall        __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
2347a984708SDavid Chisnall    __owns_ = __m_->try_lock();
2357a984708SDavid Chisnall    return __owns_;
2367a984708SDavid Chisnall}
2377a984708SDavid Chisnall
2387a984708SDavid Chisnalltemplate <class _Mutex>
2397a984708SDavid Chisnalltemplate <class _Rep, class _Period>
2407a984708SDavid Chisnallbool
2417a984708SDavid Chisnallunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
2427a984708SDavid Chisnall{
2437a984708SDavid Chisnall    if (__m_ == nullptr)
2447a984708SDavid Chisnall        __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
2457a984708SDavid Chisnall    if (__owns_)
2467a984708SDavid Chisnall        __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
2477a984708SDavid Chisnall    __owns_ = __m_->try_lock_for(__d);
2487a984708SDavid Chisnall    return __owns_;
2497a984708SDavid Chisnall}
2507a984708SDavid Chisnall
2517a984708SDavid Chisnalltemplate <class _Mutex>
2527a984708SDavid Chisnalltemplate <class _Clock, class _Duration>
2537a984708SDavid Chisnallbool
2547a984708SDavid Chisnallunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
2557a984708SDavid Chisnall{
2567a984708SDavid Chisnall    if (__m_ == nullptr)
2577a984708SDavid Chisnall        __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
2587a984708SDavid Chisnall    if (__owns_)
2597a984708SDavid Chisnall        __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
2607a984708SDavid Chisnall    __owns_ = __m_->try_lock_until(__t);
2617a984708SDavid Chisnall    return __owns_;
2627a984708SDavid Chisnall}
2637a984708SDavid Chisnall
2647a984708SDavid Chisnalltemplate <class _Mutex>
2657a984708SDavid Chisnallvoid
2667a984708SDavid Chisnallunique_lock<_Mutex>::unlock()
2677a984708SDavid Chisnall{
2687a984708SDavid Chisnall    if (!__owns_)
2697a984708SDavid Chisnall        __throw_system_error(EPERM, "unique_lock::unlock: not locked");
2707a984708SDavid Chisnall    __m_->unlock();
2717a984708SDavid Chisnall    __owns_ = false;
2727a984708SDavid Chisnall}
2737a984708SDavid Chisnall
2747a984708SDavid Chisnalltemplate <class _Mutex>
2757a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
2767a984708SDavid Chisnallvoid
277936e9439SDimitry Andricswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
278936e9439SDimitry Andric    {__x.swap(__y);}
2797a984708SDavid Chisnall
280d72607e9SDimitry Andric//enum class cv_status
281d72607e9SDimitry Andric_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
2827a984708SDavid Chisnall{
2837a984708SDavid Chisnall    no_timeout,
2847a984708SDavid Chisnall    timeout
2857a984708SDavid Chisnall};
286d72607e9SDimitry Andric_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
2877a984708SDavid Chisnall
2881bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS condition_variable
2897a984708SDavid Chisnall{
290540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
2917c82a1ecSDimitry Andric    __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
2927c82a1ecSDimitry Andric#else
2937c82a1ecSDimitry Andric    __libcpp_condvar_t __cv_;
2947c82a1ecSDimitry Andric#endif
2957c82a1ecSDimitry Andric
2967a984708SDavid Chisnallpublic:
2977a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
298540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
299aed8d94eSDimitry Andric    constexpr condition_variable() _NOEXCEPT = default;
300936e9439SDimitry Andric#else
3017c82a1ecSDimitry Andric    condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;}
302936e9439SDimitry Andric#endif
3037a984708SDavid Chisnall    ~condition_variable();
3047a984708SDavid Chisnall
3057a984708SDavid Chisnallprivate:
3067a984708SDavid Chisnall    condition_variable(const condition_variable&); // = delete;
3077a984708SDavid Chisnall    condition_variable& operator=(const condition_variable&); // = delete;
3087a984708SDavid Chisnall
3097a984708SDavid Chisnallpublic:
310936e9439SDimitry Andric    void notify_one() _NOEXCEPT;
311936e9439SDimitry Andric    void notify_all() _NOEXCEPT;
3127a984708SDavid Chisnall
313d72607e9SDimitry Andric    void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
3147a984708SDavid Chisnall    template <class _Predicate>
315540d2a8bSDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
3167a984708SDavid Chisnall        void wait(unique_lock<mutex>& __lk, _Predicate __pred);
3177a984708SDavid Chisnall
3187a984708SDavid Chisnall    template <class _Clock, class _Duration>
319540d2a8bSDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
3207a984708SDavid Chisnall        cv_status
3217a984708SDavid Chisnall        wait_until(unique_lock<mutex>& __lk,
3227a984708SDavid Chisnall                   const chrono::time_point<_Clock, _Duration>& __t);
3237a984708SDavid Chisnall
3247a984708SDavid Chisnall    template <class _Clock, class _Duration, class _Predicate>
325540d2a8bSDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
3267a984708SDavid Chisnall        bool
3277a984708SDavid Chisnall        wait_until(unique_lock<mutex>& __lk,
3287a984708SDavid Chisnall                   const chrono::time_point<_Clock, _Duration>& __t,
3297a984708SDavid Chisnall                   _Predicate __pred);
3307a984708SDavid Chisnall
3317a984708SDavid Chisnall    template <class _Rep, class _Period>
332540d2a8bSDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
3337a984708SDavid Chisnall        cv_status
3347a984708SDavid Chisnall        wait_for(unique_lock<mutex>& __lk,
3357a984708SDavid Chisnall                 const chrono::duration<_Rep, _Period>& __d);
3367a984708SDavid Chisnall
3377a984708SDavid Chisnall    template <class _Rep, class _Period, class _Predicate>
3387a984708SDavid Chisnall        bool
3399729cf09SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
3407a984708SDavid Chisnall        wait_for(unique_lock<mutex>& __lk,
3417a984708SDavid Chisnall                 const chrono::duration<_Rep, _Period>& __d,
3427a984708SDavid Chisnall                 _Predicate __pred);
3437a984708SDavid Chisnall
3447c82a1ecSDimitry Andric    typedef __libcpp_condvar_t* native_handle_type;
3457a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
3467a984708SDavid Chisnall
3477a984708SDavid Chisnallprivate:
3487a984708SDavid Chisnall    void __do_timed_wait(unique_lock<mutex>& __lk,
349d72607e9SDimitry Andric       chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
3507a984708SDavid Chisnall};
351d72607e9SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
3527a984708SDavid Chisnall
3537a984708SDavid Chisnalltemplate <class _To, class _Rep, class _Period>
3547a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
3557a984708SDavid Chisnalltypename enable_if
3567a984708SDavid Chisnall<
3577a984708SDavid Chisnall    chrono::__is_duration<_To>::value,
3587a984708SDavid Chisnall    _To
3597a984708SDavid Chisnall>::type
3607a984708SDavid Chisnall__ceil(chrono::duration<_Rep, _Period> __d)
3617a984708SDavid Chisnall{
3627a984708SDavid Chisnall    using namespace chrono;
3637a984708SDavid Chisnall    _To __r = duration_cast<_To>(__d);
3647a984708SDavid Chisnall    if (__r < __d)
3657a984708SDavid Chisnall        ++__r;
3667a984708SDavid Chisnall    return __r;
3677a984708SDavid Chisnall}
3687a984708SDavid Chisnall
369d72607e9SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS
3707a984708SDavid Chisnalltemplate <class _Predicate>
3717a984708SDavid Chisnallvoid
3727a984708SDavid Chisnallcondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
3737a984708SDavid Chisnall{
3747a984708SDavid Chisnall    while (!__pred())
3757a984708SDavid Chisnall        wait(__lk);
3767a984708SDavid Chisnall}
3777a984708SDavid Chisnall
3787a984708SDavid Chisnalltemplate <class _Clock, class _Duration>
3797a984708SDavid Chisnallcv_status
3807a984708SDavid Chisnallcondition_variable::wait_until(unique_lock<mutex>& __lk,
3817a984708SDavid Chisnall                               const chrono::time_point<_Clock, _Duration>& __t)
3827a984708SDavid Chisnall{
3837a984708SDavid Chisnall    using namespace chrono;
384936e9439SDimitry Andric    wait_for(__lk, __t - _Clock::now());
3857a984708SDavid Chisnall    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
3867a984708SDavid Chisnall}
3877a984708SDavid Chisnall
3887a984708SDavid Chisnalltemplate <class _Clock, class _Duration, class _Predicate>
3897a984708SDavid Chisnallbool
3907a984708SDavid Chisnallcondition_variable::wait_until(unique_lock<mutex>& __lk,
3917a984708SDavid Chisnall                   const chrono::time_point<_Clock, _Duration>& __t,
3927a984708SDavid Chisnall                   _Predicate __pred)
3937a984708SDavid Chisnall{
3947a984708SDavid Chisnall    while (!__pred())
3957a984708SDavid Chisnall    {
3967a984708SDavid Chisnall        if (wait_until(__lk, __t) == cv_status::timeout)
3977a984708SDavid Chisnall            return __pred();
3987a984708SDavid Chisnall    }
3997a984708SDavid Chisnall    return true;
4007a984708SDavid Chisnall}
4017a984708SDavid Chisnall
4027a984708SDavid Chisnalltemplate <class _Rep, class _Period>
4037a984708SDavid Chisnallcv_status
4047a984708SDavid Chisnallcondition_variable::wait_for(unique_lock<mutex>& __lk,
4057a984708SDavid Chisnall                             const chrono::duration<_Rep, _Period>& __d)
4067a984708SDavid Chisnall{
4077a984708SDavid Chisnall    using namespace chrono;
408936e9439SDimitry Andric    if (__d <= __d.zero())
409936e9439SDimitry Andric        return cv_status::timeout;
410936e9439SDimitry Andric    typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
411936e9439SDimitry Andric    typedef time_point<system_clock, nanoseconds> __sys_tpi;
412936e9439SDimitry Andric    __sys_tpf _Max = __sys_tpi::max();
4137a984708SDavid Chisnall    steady_clock::time_point __c_now = steady_clock::now();
4147a848d17SDimitry Andric    system_clock::time_point __s_now = system_clock::now();
415936e9439SDimitry Andric    if (_Max - __d > __s_now)
4167a984708SDavid Chisnall        __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
417936e9439SDimitry Andric    else
418936e9439SDimitry Andric        __do_timed_wait(__lk, __sys_tpi::max());
4197a984708SDavid Chisnall    return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
4207a984708SDavid Chisnall                                                 cv_status::timeout;
4217a984708SDavid Chisnall}
4227a984708SDavid Chisnall
4237a984708SDavid Chisnalltemplate <class _Rep, class _Period, class _Predicate>
4249729cf09SDimitry Andricinline
4257a984708SDavid Chisnallbool
4267a984708SDavid Chisnallcondition_variable::wait_for(unique_lock<mutex>& __lk,
4277a984708SDavid Chisnall                             const chrono::duration<_Rep, _Period>& __d,
4287a984708SDavid Chisnall                             _Predicate __pred)
4297a984708SDavid Chisnall{
4307a984708SDavid Chisnall    return wait_until(__lk, chrono::steady_clock::now() + __d,
4317a984708SDavid Chisnall                      _VSTD::move(__pred));
4327a984708SDavid Chisnall}
4337a984708SDavid Chisnall
434d72607e9SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
435d72607e9SDimitry Andric
4367a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD
4377a984708SDavid Chisnall
438f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
439f9448bf3SDimitry Andric
4407a984708SDavid Chisnall#endif  // _LIBCPP___MUTEX_BASE
441