17a984708SDavid Chisnall// -*- C++ -*-
27a984708SDavid Chisnall//===---------------------- condition_variable ----------------------------===//
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_CONDITION_VARIABLE
127a984708SDavid Chisnall#define _LIBCPP_CONDITION_VARIABLE
137a984708SDavid Chisnall
147a984708SDavid Chisnall/*
157a984708SDavid Chisnall    condition_variable synopsis
167a984708SDavid Chisnall
177a984708SDavid Chisnallnamespace std
187a984708SDavid Chisnall{
197a984708SDavid Chisnall
207a984708SDavid Chisnallenum class cv_status { no_timeout, timeout };
217a984708SDavid Chisnall
227a984708SDavid Chisnallclass condition_variable
237a984708SDavid Chisnall{
247a984708SDavid Chisnallpublic:
257a984708SDavid Chisnall    condition_variable();
267a984708SDavid Chisnall    ~condition_variable();
277a984708SDavid Chisnall
287a984708SDavid Chisnall    condition_variable(const condition_variable&) = delete;
297a984708SDavid Chisnall    condition_variable& operator=(const condition_variable&) = delete;
307a984708SDavid Chisnall
31936e9439SDimitry Andric    void notify_one() noexcept;
32936e9439SDimitry Andric    void notify_all() noexcept;
337a984708SDavid Chisnall
347a984708SDavid Chisnall    void wait(unique_lock<mutex>& lock);
357a984708SDavid Chisnall    template <class Predicate>
367a984708SDavid Chisnall        void wait(unique_lock<mutex>& lock, Predicate pred);
377a984708SDavid Chisnall
387a984708SDavid Chisnall    template <class Clock, class Duration>
397a984708SDavid Chisnall        cv_status
407a984708SDavid Chisnall        wait_until(unique_lock<mutex>& lock,
417a984708SDavid Chisnall                   const chrono::time_point<Clock, Duration>& abs_time);
427a984708SDavid Chisnall
437a984708SDavid Chisnall    template <class Clock, class Duration, class Predicate>
447a984708SDavid Chisnall        bool
457a984708SDavid Chisnall        wait_until(unique_lock<mutex>& lock,
467a984708SDavid Chisnall                   const chrono::time_point<Clock, Duration>& abs_time,
477a984708SDavid Chisnall                   Predicate pred);
487a984708SDavid Chisnall
497a984708SDavid Chisnall    template <class Rep, class Period>
507a984708SDavid Chisnall        cv_status
517a984708SDavid Chisnall        wait_for(unique_lock<mutex>& lock,
527a984708SDavid Chisnall                 const chrono::duration<Rep, Period>& rel_time);
537a984708SDavid Chisnall
547a984708SDavid Chisnall    template <class Rep, class Period, class Predicate>
557a984708SDavid Chisnall        bool
567a984708SDavid Chisnall        wait_for(unique_lock<mutex>& lock,
577a984708SDavid Chisnall                 const chrono::duration<Rep, Period>& rel_time,
587a984708SDavid Chisnall                 Predicate pred);
597a984708SDavid Chisnall
607a984708SDavid Chisnall    typedef pthread_cond_t* native_handle_type;
617a984708SDavid Chisnall    native_handle_type native_handle();
627a984708SDavid Chisnall};
637a984708SDavid Chisnall
647a984708SDavid Chisnallvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
657a984708SDavid Chisnall
667a984708SDavid Chisnallclass condition_variable_any
677a984708SDavid Chisnall{
687a984708SDavid Chisnallpublic:
697a984708SDavid Chisnall    condition_variable_any();
707a984708SDavid Chisnall    ~condition_variable_any();
717a984708SDavid Chisnall
727a984708SDavid Chisnall    condition_variable_any(const condition_variable_any&) = delete;
737a984708SDavid Chisnall    condition_variable_any& operator=(const condition_variable_any&) = delete;
747a984708SDavid Chisnall
75936e9439SDimitry Andric    void notify_one() noexcept;
76936e9439SDimitry Andric    void notify_all() noexcept;
777a984708SDavid Chisnall
787a984708SDavid Chisnall    template <class Lock>
797a984708SDavid Chisnall        void wait(Lock& lock);
807a984708SDavid Chisnall    template <class Lock, class Predicate>
817a984708SDavid Chisnall        void wait(Lock& lock, Predicate pred);
827a984708SDavid Chisnall
837a984708SDavid Chisnall    template <class Lock, class Clock, class Duration>
847a984708SDavid Chisnall        cv_status
857a984708SDavid Chisnall        wait_until(Lock& lock,
867a984708SDavid Chisnall                   const chrono::time_point<Clock, Duration>& abs_time);
877a984708SDavid Chisnall
887a984708SDavid Chisnall    template <class Lock, class Clock, class Duration, class Predicate>
897a984708SDavid Chisnall        bool
907a984708SDavid Chisnall        wait_until(Lock& lock,
917a984708SDavid Chisnall                   const chrono::time_point<Clock, Duration>& abs_time,
927a984708SDavid Chisnall                   Predicate pred);
937a984708SDavid Chisnall
947a984708SDavid Chisnall    template <class Lock, class Rep, class Period>
957a984708SDavid Chisnall        cv_status
967a984708SDavid Chisnall        wait_for(Lock& lock,
977a984708SDavid Chisnall                 const chrono::duration<Rep, Period>& rel_time);
987a984708SDavid Chisnall
997a984708SDavid Chisnall    template <class Lock, class Rep, class Period, class Predicate>
1007a984708SDavid Chisnall        bool
1017a984708SDavid Chisnall        wait_for(Lock& lock,
1027a984708SDavid Chisnall                 const chrono::duration<Rep, Period>& rel_time,
1037a984708SDavid Chisnall                 Predicate pred);
1047a984708SDavid Chisnall};
1057a984708SDavid Chisnall
1067a984708SDavid Chisnall}  // std
1077a984708SDavid Chisnall
1087a984708SDavid Chisnall*/
1097a984708SDavid Chisnall
1107a984708SDavid Chisnall#include <__config>
1117a984708SDavid Chisnall#include <__mutex_base>
1127a984708SDavid Chisnall#include <memory>
1137a984708SDavid Chisnall
1147a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1157a984708SDavid Chisnall#pragma GCC system_header
1167a984708SDavid Chisnall#endif
1177a984708SDavid Chisnall
118d72607e9SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS
119d72607e9SDimitry Andric
1207a984708SDavid Chisnall_LIBCPP_BEGIN_NAMESPACE_STD
1217a984708SDavid Chisnall
1221bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS condition_variable_any
1237a984708SDavid Chisnall{
1247a984708SDavid Chisnall    condition_variable __cv_;
1257a984708SDavid Chisnall    shared_ptr<mutex>  __mut_;
1267a984708SDavid Chisnallpublic:
1279729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1287a984708SDavid Chisnall    condition_variable_any();
1297a984708SDavid Chisnall
1309729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
131936e9439SDimitry Andric    void notify_one() _NOEXCEPT;
1329729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
133936e9439SDimitry Andric    void notify_all() _NOEXCEPT;
1347a984708SDavid Chisnall
1357a984708SDavid Chisnall    template <class _Lock>
136*540d2a8bSDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1377a984708SDavid Chisnall        void wait(_Lock& __lock);
1387a984708SDavid Chisnall    template <class _Lock, class _Predicate>
1399729cf09SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1407a984708SDavid Chisnall        void wait(_Lock& __lock, _Predicate __pred);
1417a984708SDavid Chisnall
1427a984708SDavid Chisnall    template <class _Lock, class _Clock, class _Duration>
143*540d2a8bSDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1447a984708SDavid Chisnall        cv_status
1457a984708SDavid Chisnall        wait_until(_Lock& __lock,
1467a984708SDavid Chisnall                   const chrono::time_point<_Clock, _Duration>& __t);
1477a984708SDavid Chisnall
1487a984708SDavid Chisnall    template <class _Lock, class _Clock, class _Duration, class _Predicate>
1497a984708SDavid Chisnall        bool
1509729cf09SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1517a984708SDavid Chisnall        wait_until(_Lock& __lock,
1527a984708SDavid Chisnall                   const chrono::time_point<_Clock, _Duration>& __t,
1537a984708SDavid Chisnall                   _Predicate __pred);
1547a984708SDavid Chisnall
1557a984708SDavid Chisnall    template <class _Lock, class _Rep, class _Period>
1567a984708SDavid Chisnall        cv_status
1579729cf09SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1587a984708SDavid Chisnall        wait_for(_Lock& __lock,
1597a984708SDavid Chisnall                 const chrono::duration<_Rep, _Period>& __d);
1607a984708SDavid Chisnall
1617a984708SDavid Chisnall    template <class _Lock, class _Rep, class _Period, class _Predicate>
1627a984708SDavid Chisnall        bool
1639729cf09SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1647a984708SDavid Chisnall        wait_for(_Lock& __lock,
1657a984708SDavid Chisnall                 const chrono::duration<_Rep, _Period>& __d,
1667a984708SDavid Chisnall                 _Predicate __pred);
1677a984708SDavid Chisnall};
1687a984708SDavid Chisnall
1699729cf09SDimitry Andricinline
1707a984708SDavid Chisnallcondition_variable_any::condition_variable_any()
1717a984708SDavid Chisnall    : __mut_(make_shared<mutex>()) {}
1727a984708SDavid Chisnall
1739729cf09SDimitry Andricinline
1747a984708SDavid Chisnallvoid
175936e9439SDimitry Andriccondition_variable_any::notify_one() _NOEXCEPT
1767a984708SDavid Chisnall{
1771e0896acSDavid Chisnall    {lock_guard<mutex> __lx(*__mut_);}
1787a984708SDavid Chisnall    __cv_.notify_one();
1797a984708SDavid Chisnall}
1807a984708SDavid Chisnall
1819729cf09SDimitry Andricinline
1827a984708SDavid Chisnallvoid
183936e9439SDimitry Andriccondition_variable_any::notify_all() _NOEXCEPT
1847a984708SDavid Chisnall{
1851e0896acSDavid Chisnall    {lock_guard<mutex> __lx(*__mut_);}
1867a984708SDavid Chisnall    __cv_.notify_all();
1877a984708SDavid Chisnall}
1887a984708SDavid Chisnall
1897a984708SDavid Chisnallstruct __lock_external
1907a984708SDavid Chisnall{
1917a984708SDavid Chisnall    template <class _Lock>
1927a984708SDavid Chisnall    void operator()(_Lock* __m) {__m->lock();}
1937a984708SDavid Chisnall};
1947a984708SDavid Chisnall
1957a984708SDavid Chisnalltemplate <class _Lock>
1967a984708SDavid Chisnallvoid
1977a984708SDavid Chisnallcondition_variable_any::wait(_Lock& __lock)
1987a984708SDavid Chisnall{
1997a984708SDavid Chisnall    shared_ptr<mutex> __mut = __mut_;
2007a984708SDavid Chisnall    unique_lock<mutex> __lk(*__mut);
2017a984708SDavid Chisnall    __lock.unlock();
2021e0896acSDavid Chisnall    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
2031e0896acSDavid Chisnall    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2047a984708SDavid Chisnall    __cv_.wait(__lk);
2057a984708SDavid Chisnall}  // __mut_.unlock(), __lock.lock()
2067a984708SDavid Chisnall
2077a984708SDavid Chisnalltemplate <class _Lock, class _Predicate>
2089729cf09SDimitry Andricinline
2097a984708SDavid Chisnallvoid
2107a984708SDavid Chisnallcondition_variable_any::wait(_Lock& __lock, _Predicate __pred)
2117a984708SDavid Chisnall{
2127a984708SDavid Chisnall    while (!__pred())
2137a984708SDavid Chisnall        wait(__lock);
2147a984708SDavid Chisnall}
2157a984708SDavid Chisnall
2167a984708SDavid Chisnalltemplate <class _Lock, class _Clock, class _Duration>
2177a984708SDavid Chisnallcv_status
2187a984708SDavid Chisnallcondition_variable_any::wait_until(_Lock& __lock,
2197a984708SDavid Chisnall                                   const chrono::time_point<_Clock, _Duration>& __t)
2207a984708SDavid Chisnall{
2217a984708SDavid Chisnall    shared_ptr<mutex> __mut = __mut_;
2227a984708SDavid Chisnall    unique_lock<mutex> __lk(*__mut);
2237a984708SDavid Chisnall    __lock.unlock();
2241e0896acSDavid Chisnall    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
2251e0896acSDavid Chisnall    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2267a984708SDavid Chisnall    return __cv_.wait_until(__lk, __t);
2277a984708SDavid Chisnall}  // __mut_.unlock(), __lock.lock()
2287a984708SDavid Chisnall
2297a984708SDavid Chisnalltemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
2309729cf09SDimitry Andricinline
2317a984708SDavid Chisnallbool
2327a984708SDavid Chisnallcondition_variable_any::wait_until(_Lock& __lock,
2337a984708SDavid Chisnall                                   const chrono::time_point<_Clock, _Duration>& __t,
2347a984708SDavid Chisnall                                   _Predicate __pred)
2357a984708SDavid Chisnall{
2367a984708SDavid Chisnall    while (!__pred())
2377a984708SDavid Chisnall        if (wait_until(__lock, __t) == cv_status::timeout)
2387a984708SDavid Chisnall            return __pred();
2397a984708SDavid Chisnall    return true;
2407a984708SDavid Chisnall}
2417a984708SDavid Chisnall
2427a984708SDavid Chisnalltemplate <class _Lock, class _Rep, class _Period>
2439729cf09SDimitry Andricinline
2447a984708SDavid Chisnallcv_status
2457a984708SDavid Chisnallcondition_variable_any::wait_for(_Lock& __lock,
2467a984708SDavid Chisnall                                 const chrono::duration<_Rep, _Period>& __d)
2477a984708SDavid Chisnall{
2487a984708SDavid Chisnall    return wait_until(__lock, chrono::steady_clock::now() + __d);
2497a984708SDavid Chisnall}
2507a984708SDavid Chisnall
2517a984708SDavid Chisnalltemplate <class _Lock, class _Rep, class _Period, class _Predicate>
2529729cf09SDimitry Andricinline
2537a984708SDavid Chisnallbool
2547a984708SDavid Chisnallcondition_variable_any::wait_for(_Lock& __lock,
2557a984708SDavid Chisnall                                 const chrono::duration<_Rep, _Period>& __d,
2567a984708SDavid Chisnall                                 _Predicate __pred)
2577a984708SDavid Chisnall{
2587a984708SDavid Chisnall    return wait_until(__lock, chrono::steady_clock::now() + __d,
2597a984708SDavid Chisnall                      _VSTD::move(__pred));
2607a984708SDavid Chisnall}
2617a984708SDavid Chisnall
2621bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS
2637a984708SDavid Chisnallvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
2647a984708SDavid Chisnall
2657a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD
2667a984708SDavid Chisnall
267d72607e9SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
268d72607e9SDimitry Andric
2697a984708SDavid Chisnall#endif  // _LIBCPP_CONDITION_VARIABLE
270