14684ddb6SLionel Sambuc// -*- C++ -*-
24684ddb6SLionel Sambuc//===---------------------- condition_variable ----------------------------===//
34684ddb6SLionel Sambuc//
44684ddb6SLionel Sambuc//                     The LLVM Compiler Infrastructure
54684ddb6SLionel Sambuc//
64684ddb6SLionel Sambuc// This file is dual licensed under the MIT and the University of Illinois Open
74684ddb6SLionel Sambuc// Source Licenses. See LICENSE.TXT for details.
84684ddb6SLionel Sambuc//
94684ddb6SLionel Sambuc//===----------------------------------------------------------------------===//
104684ddb6SLionel Sambuc
114684ddb6SLionel Sambuc#ifndef _LIBCPP_CONDITION_VARIABLE
124684ddb6SLionel Sambuc#define _LIBCPP_CONDITION_VARIABLE
134684ddb6SLionel Sambuc
144684ddb6SLionel Sambuc/*
154684ddb6SLionel Sambuc    condition_variable synopsis
164684ddb6SLionel Sambuc
174684ddb6SLionel Sambucnamespace std
184684ddb6SLionel Sambuc{
194684ddb6SLionel Sambuc
204684ddb6SLionel Sambucenum class cv_status { no_timeout, timeout };
214684ddb6SLionel Sambuc
224684ddb6SLionel Sambucclass condition_variable
234684ddb6SLionel Sambuc{
244684ddb6SLionel Sambucpublic:
254684ddb6SLionel Sambuc    condition_variable();
264684ddb6SLionel Sambuc    ~condition_variable();
274684ddb6SLionel Sambuc
284684ddb6SLionel Sambuc    condition_variable(const condition_variable&) = delete;
294684ddb6SLionel Sambuc    condition_variable& operator=(const condition_variable&) = delete;
304684ddb6SLionel Sambuc
314684ddb6SLionel Sambuc    void notify_one() noexcept;
324684ddb6SLionel Sambuc    void notify_all() noexcept;
334684ddb6SLionel Sambuc
344684ddb6SLionel Sambuc    void wait(unique_lock<mutex>& lock);
354684ddb6SLionel Sambuc    template <class Predicate>
364684ddb6SLionel Sambuc        void wait(unique_lock<mutex>& lock, Predicate pred);
374684ddb6SLionel Sambuc
384684ddb6SLionel Sambuc    template <class Clock, class Duration>
394684ddb6SLionel Sambuc        cv_status
404684ddb6SLionel Sambuc        wait_until(unique_lock<mutex>& lock,
414684ddb6SLionel Sambuc                   const chrono::time_point<Clock, Duration>& abs_time);
424684ddb6SLionel Sambuc
434684ddb6SLionel Sambuc    template <class Clock, class Duration, class Predicate>
444684ddb6SLionel Sambuc        bool
454684ddb6SLionel Sambuc        wait_until(unique_lock<mutex>& lock,
464684ddb6SLionel Sambuc                   const chrono::time_point<Clock, Duration>& abs_time,
474684ddb6SLionel Sambuc                   Predicate pred);
484684ddb6SLionel Sambuc
494684ddb6SLionel Sambuc    template <class Rep, class Period>
504684ddb6SLionel Sambuc        cv_status
514684ddb6SLionel Sambuc        wait_for(unique_lock<mutex>& lock,
524684ddb6SLionel Sambuc                 const chrono::duration<Rep, Period>& rel_time);
534684ddb6SLionel Sambuc
544684ddb6SLionel Sambuc    template <class Rep, class Period, class Predicate>
554684ddb6SLionel Sambuc        bool
564684ddb6SLionel Sambuc        wait_for(unique_lock<mutex>& lock,
574684ddb6SLionel Sambuc                 const chrono::duration<Rep, Period>& rel_time,
584684ddb6SLionel Sambuc                 Predicate pred);
594684ddb6SLionel Sambuc
604684ddb6SLionel Sambuc    typedef pthread_cond_t* native_handle_type;
614684ddb6SLionel Sambuc    native_handle_type native_handle();
624684ddb6SLionel Sambuc};
634684ddb6SLionel Sambuc
644684ddb6SLionel Sambucvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
654684ddb6SLionel Sambuc
664684ddb6SLionel Sambucclass condition_variable_any
674684ddb6SLionel Sambuc{
684684ddb6SLionel Sambucpublic:
694684ddb6SLionel Sambuc    condition_variable_any();
704684ddb6SLionel Sambuc    ~condition_variable_any();
714684ddb6SLionel Sambuc
724684ddb6SLionel Sambuc    condition_variable_any(const condition_variable_any&) = delete;
734684ddb6SLionel Sambuc    condition_variable_any& operator=(const condition_variable_any&) = delete;
744684ddb6SLionel Sambuc
754684ddb6SLionel Sambuc    void notify_one() noexcept;
764684ddb6SLionel Sambuc    void notify_all() noexcept;
774684ddb6SLionel Sambuc
784684ddb6SLionel Sambuc    template <class Lock>
794684ddb6SLionel Sambuc        void wait(Lock& lock);
804684ddb6SLionel Sambuc    template <class Lock, class Predicate>
814684ddb6SLionel Sambuc        void wait(Lock& lock, Predicate pred);
824684ddb6SLionel Sambuc
834684ddb6SLionel Sambuc    template <class Lock, class Clock, class Duration>
844684ddb6SLionel Sambuc        cv_status
854684ddb6SLionel Sambuc        wait_until(Lock& lock,
864684ddb6SLionel Sambuc                   const chrono::time_point<Clock, Duration>& abs_time);
874684ddb6SLionel Sambuc
884684ddb6SLionel Sambuc    template <class Lock, class Clock, class Duration, class Predicate>
894684ddb6SLionel Sambuc        bool
904684ddb6SLionel Sambuc        wait_until(Lock& lock,
914684ddb6SLionel Sambuc                   const chrono::time_point<Clock, Duration>& abs_time,
924684ddb6SLionel Sambuc                   Predicate pred);
934684ddb6SLionel Sambuc
944684ddb6SLionel Sambuc    template <class Lock, class Rep, class Period>
954684ddb6SLionel Sambuc        cv_status
964684ddb6SLionel Sambuc        wait_for(Lock& lock,
974684ddb6SLionel Sambuc                 const chrono::duration<Rep, Period>& rel_time);
984684ddb6SLionel Sambuc
994684ddb6SLionel Sambuc    template <class Lock, class Rep, class Period, class Predicate>
1004684ddb6SLionel Sambuc        bool
1014684ddb6SLionel Sambuc        wait_for(Lock& lock,
1024684ddb6SLionel Sambuc                 const chrono::duration<Rep, Period>& rel_time,
1034684ddb6SLionel Sambuc                 Predicate pred);
1044684ddb6SLionel Sambuc};
1054684ddb6SLionel Sambuc
1064684ddb6SLionel Sambuc}  // std
1074684ddb6SLionel Sambuc
1084684ddb6SLionel Sambuc*/
1094684ddb6SLionel Sambuc
1104684ddb6SLionel Sambuc#include <__config>
1114684ddb6SLionel Sambuc#include <__mutex_base>
1124684ddb6SLionel Sambuc#include <memory>
1134684ddb6SLionel Sambuc
1144684ddb6SLionel Sambuc#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1154684ddb6SLionel Sambuc#pragma GCC system_header
1164684ddb6SLionel Sambuc#endif
1174684ddb6SLionel Sambuc
118*0a6a1f1dSLionel Sambuc#ifndef _LIBCPP_HAS_NO_THREADS
119*0a6a1f1dSLionel Sambuc
1204684ddb6SLionel Sambuc_LIBCPP_BEGIN_NAMESPACE_STD
1214684ddb6SLionel Sambuc
1224684ddb6SLionel Sambucclass _LIBCPP_TYPE_VIS condition_variable_any
1234684ddb6SLionel Sambuc{
1244684ddb6SLionel Sambuc    condition_variable __cv_;
1254684ddb6SLionel Sambuc    shared_ptr<mutex>  __mut_;
1264684ddb6SLionel Sambucpublic:
1274684ddb6SLionel Sambuc    condition_variable_any();
1284684ddb6SLionel Sambuc
1294684ddb6SLionel Sambuc    void notify_one() _NOEXCEPT;
1304684ddb6SLionel Sambuc    void notify_all() _NOEXCEPT;
1314684ddb6SLionel Sambuc
1324684ddb6SLionel Sambuc    template <class _Lock>
1334684ddb6SLionel Sambuc        void wait(_Lock& __lock);
1344684ddb6SLionel Sambuc    template <class _Lock, class _Predicate>
1354684ddb6SLionel Sambuc        void wait(_Lock& __lock, _Predicate __pred);
1364684ddb6SLionel Sambuc
1374684ddb6SLionel Sambuc    template <class _Lock, class _Clock, class _Duration>
1384684ddb6SLionel Sambuc        cv_status
1394684ddb6SLionel Sambuc        wait_until(_Lock& __lock,
1404684ddb6SLionel Sambuc                   const chrono::time_point<_Clock, _Duration>& __t);
1414684ddb6SLionel Sambuc
1424684ddb6SLionel Sambuc    template <class _Lock, class _Clock, class _Duration, class _Predicate>
1434684ddb6SLionel Sambuc        bool
1444684ddb6SLionel Sambuc        wait_until(_Lock& __lock,
1454684ddb6SLionel Sambuc                   const chrono::time_point<_Clock, _Duration>& __t,
1464684ddb6SLionel Sambuc                   _Predicate __pred);
1474684ddb6SLionel Sambuc
1484684ddb6SLionel Sambuc    template <class _Lock, class _Rep, class _Period>
1494684ddb6SLionel Sambuc        cv_status
1504684ddb6SLionel Sambuc        wait_for(_Lock& __lock,
1514684ddb6SLionel Sambuc                 const chrono::duration<_Rep, _Period>& __d);
1524684ddb6SLionel Sambuc
1534684ddb6SLionel Sambuc    template <class _Lock, class _Rep, class _Period, class _Predicate>
1544684ddb6SLionel Sambuc        bool
1554684ddb6SLionel Sambuc        wait_for(_Lock& __lock,
1564684ddb6SLionel Sambuc                 const chrono::duration<_Rep, _Period>& __d,
1574684ddb6SLionel Sambuc                 _Predicate __pred);
1584684ddb6SLionel Sambuc};
1594684ddb6SLionel Sambuc
1604684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
1614684ddb6SLionel Sambuccondition_variable_any::condition_variable_any()
1624684ddb6SLionel Sambuc    : __mut_(make_shared<mutex>()) {}
1634684ddb6SLionel Sambuc
1644684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
1654684ddb6SLionel Sambucvoid
1664684ddb6SLionel Sambuccondition_variable_any::notify_one() _NOEXCEPT
1674684ddb6SLionel Sambuc{
1684684ddb6SLionel Sambuc    {lock_guard<mutex> __lx(*__mut_);}
1694684ddb6SLionel Sambuc    __cv_.notify_one();
1704684ddb6SLionel Sambuc}
1714684ddb6SLionel Sambuc
1724684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
1734684ddb6SLionel Sambucvoid
1744684ddb6SLionel Sambuccondition_variable_any::notify_all() _NOEXCEPT
1754684ddb6SLionel Sambuc{
1764684ddb6SLionel Sambuc    {lock_guard<mutex> __lx(*__mut_);}
1774684ddb6SLionel Sambuc    __cv_.notify_all();
1784684ddb6SLionel Sambuc}
1794684ddb6SLionel Sambuc
1804684ddb6SLionel Sambucstruct __lock_external
1814684ddb6SLionel Sambuc{
1824684ddb6SLionel Sambuc    template <class _Lock>
1834684ddb6SLionel Sambuc    void operator()(_Lock* __m) {__m->lock();}
1844684ddb6SLionel Sambuc};
1854684ddb6SLionel Sambuc
1864684ddb6SLionel Sambuctemplate <class _Lock>
1874684ddb6SLionel Sambucvoid
1884684ddb6SLionel Sambuccondition_variable_any::wait(_Lock& __lock)
1894684ddb6SLionel Sambuc{
1904684ddb6SLionel Sambuc    shared_ptr<mutex> __mut = __mut_;
1914684ddb6SLionel Sambuc    unique_lock<mutex> __lk(*__mut);
1924684ddb6SLionel Sambuc    __lock.unlock();
1934684ddb6SLionel Sambuc    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
1944684ddb6SLionel Sambuc    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
1954684ddb6SLionel Sambuc    __cv_.wait(__lk);
1964684ddb6SLionel Sambuc}  // __mut_.unlock(), __lock.lock()
1974684ddb6SLionel Sambuc
1984684ddb6SLionel Sambuctemplate <class _Lock, class _Predicate>
1994684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
2004684ddb6SLionel Sambucvoid
2014684ddb6SLionel Sambuccondition_variable_any::wait(_Lock& __lock, _Predicate __pred)
2024684ddb6SLionel Sambuc{
2034684ddb6SLionel Sambuc    while (!__pred())
2044684ddb6SLionel Sambuc        wait(__lock);
2054684ddb6SLionel Sambuc}
2064684ddb6SLionel Sambuc
2074684ddb6SLionel Sambuctemplate <class _Lock, class _Clock, class _Duration>
2084684ddb6SLionel Sambuccv_status
2094684ddb6SLionel Sambuccondition_variable_any::wait_until(_Lock& __lock,
2104684ddb6SLionel Sambuc                                   const chrono::time_point<_Clock, _Duration>& __t)
2114684ddb6SLionel Sambuc{
2124684ddb6SLionel Sambuc    shared_ptr<mutex> __mut = __mut_;
2134684ddb6SLionel Sambuc    unique_lock<mutex> __lk(*__mut);
2144684ddb6SLionel Sambuc    __lock.unlock();
2154684ddb6SLionel Sambuc    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
2164684ddb6SLionel Sambuc    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2174684ddb6SLionel Sambuc    return __cv_.wait_until(__lk, __t);
2184684ddb6SLionel Sambuc}  // __mut_.unlock(), __lock.lock()
2194684ddb6SLionel Sambuc
2204684ddb6SLionel Sambuctemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
2214684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
2224684ddb6SLionel Sambucbool
2234684ddb6SLionel Sambuccondition_variable_any::wait_until(_Lock& __lock,
2244684ddb6SLionel Sambuc                                   const chrono::time_point<_Clock, _Duration>& __t,
2254684ddb6SLionel Sambuc                                   _Predicate __pred)
2264684ddb6SLionel Sambuc{
2274684ddb6SLionel Sambuc    while (!__pred())
2284684ddb6SLionel Sambuc        if (wait_until(__lock, __t) == cv_status::timeout)
2294684ddb6SLionel Sambuc            return __pred();
2304684ddb6SLionel Sambuc    return true;
2314684ddb6SLionel Sambuc}
2324684ddb6SLionel Sambuc
2334684ddb6SLionel Sambuctemplate <class _Lock, class _Rep, class _Period>
2344684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
2354684ddb6SLionel Sambuccv_status
2364684ddb6SLionel Sambuccondition_variable_any::wait_for(_Lock& __lock,
2374684ddb6SLionel Sambuc                                 const chrono::duration<_Rep, _Period>& __d)
2384684ddb6SLionel Sambuc{
2394684ddb6SLionel Sambuc    return wait_until(__lock, chrono::steady_clock::now() + __d);
2404684ddb6SLionel Sambuc}
2414684ddb6SLionel Sambuc
2424684ddb6SLionel Sambuctemplate <class _Lock, class _Rep, class _Period, class _Predicate>
2434684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
2444684ddb6SLionel Sambucbool
2454684ddb6SLionel Sambuccondition_variable_any::wait_for(_Lock& __lock,
2464684ddb6SLionel Sambuc                                 const chrono::duration<_Rep, _Period>& __d,
2474684ddb6SLionel Sambuc                                 _Predicate __pred)
2484684ddb6SLionel Sambuc{
2494684ddb6SLionel Sambuc    return wait_until(__lock, chrono::steady_clock::now() + __d,
2504684ddb6SLionel Sambuc                      _VSTD::move(__pred));
2514684ddb6SLionel Sambuc}
2524684ddb6SLionel Sambuc
2534684ddb6SLionel Sambuc_LIBCPP_FUNC_VIS
2544684ddb6SLionel Sambucvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
2554684ddb6SLionel Sambuc
2564684ddb6SLionel Sambuc_LIBCPP_END_NAMESPACE_STD
2574684ddb6SLionel Sambuc
258*0a6a1f1dSLionel Sambuc#endif // !_LIBCPP_HAS_NO_THREADS
259*0a6a1f1dSLionel Sambuc
2604684ddb6SLionel Sambuc#endif  // _LIBCPP_CONDITION_VARIABLE
261