13e519524SHoward Hinnant// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
33e519524SHoward Hinnant//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
73e519524SHoward Hinnant//
83e519524SHoward Hinnant//===----------------------------------------------------------------------===//
93e519524SHoward Hinnant
103e519524SHoward Hinnant#ifndef _LIBCPP_CONDITION_VARIABLE
113e519524SHoward Hinnant#define _LIBCPP_CONDITION_VARIABLE
123e519524SHoward Hinnant
133e519524SHoward Hinnant/*
143e519524SHoward Hinnant    condition_variable synopsis
153e519524SHoward Hinnant
163e519524SHoward Hinnantnamespace std
173e519524SHoward Hinnant{
183e519524SHoward Hinnant
193e519524SHoward Hinnantenum class cv_status { no_timeout, timeout };
203e519524SHoward Hinnant
213e519524SHoward Hinnantclass condition_variable
223e519524SHoward Hinnant{
233e519524SHoward Hinnantpublic:
243e519524SHoward Hinnant    condition_variable();
253e519524SHoward Hinnant    ~condition_variable();
263e519524SHoward Hinnant
273e519524SHoward Hinnant    condition_variable(const condition_variable&) = delete;
283e519524SHoward Hinnant    condition_variable& operator=(const condition_variable&) = delete;
293e519524SHoward Hinnant
3045c663dbSHoward Hinnant    void notify_one() noexcept;
3145c663dbSHoward Hinnant    void notify_all() noexcept;
323e519524SHoward Hinnant
333e519524SHoward Hinnant    void wait(unique_lock<mutex>& lock);
343e519524SHoward Hinnant    template <class Predicate>
353e519524SHoward Hinnant        void wait(unique_lock<mutex>& lock, Predicate pred);
363e519524SHoward Hinnant
373e519524SHoward Hinnant    template <class Clock, class Duration>
383e519524SHoward Hinnant        cv_status
393e519524SHoward Hinnant        wait_until(unique_lock<mutex>& lock,
403e519524SHoward Hinnant                   const chrono::time_point<Clock, Duration>& abs_time);
413e519524SHoward Hinnant
423e519524SHoward Hinnant    template <class Clock, class Duration, class Predicate>
433e519524SHoward Hinnant        bool
443e519524SHoward Hinnant        wait_until(unique_lock<mutex>& lock,
453e519524SHoward Hinnant                   const chrono::time_point<Clock, Duration>& abs_time,
463e519524SHoward Hinnant                   Predicate pred);
473e519524SHoward Hinnant
483e519524SHoward Hinnant    template <class Rep, class Period>
493e519524SHoward Hinnant        cv_status
503e519524SHoward Hinnant        wait_for(unique_lock<mutex>& lock,
513e519524SHoward Hinnant                 const chrono::duration<Rep, Period>& rel_time);
523e519524SHoward Hinnant
533e519524SHoward Hinnant    template <class Rep, class Period, class Predicate>
543e519524SHoward Hinnant        bool
553e519524SHoward Hinnant        wait_for(unique_lock<mutex>& lock,
563e519524SHoward Hinnant                 const chrono::duration<Rep, Period>& rel_time,
573e519524SHoward Hinnant                 Predicate pred);
583e519524SHoward Hinnant
593e519524SHoward Hinnant    typedef pthread_cond_t* native_handle_type;
603e519524SHoward Hinnant    native_handle_type native_handle();
613e519524SHoward Hinnant};
623e519524SHoward Hinnant
63167fd108SHoward Hinnantvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
64167fd108SHoward Hinnant
653e519524SHoward Hinnantclass condition_variable_any
663e519524SHoward Hinnant{
673e519524SHoward Hinnantpublic:
683e519524SHoward Hinnant    condition_variable_any();
693e519524SHoward Hinnant    ~condition_variable_any();
703e519524SHoward Hinnant
713e519524SHoward Hinnant    condition_variable_any(const condition_variable_any&) = delete;
723e519524SHoward Hinnant    condition_variable_any& operator=(const condition_variable_any&) = delete;
733e519524SHoward Hinnant
7445c663dbSHoward Hinnant    void notify_one() noexcept;
7545c663dbSHoward Hinnant    void notify_all() noexcept;
763e519524SHoward Hinnant
773e519524SHoward Hinnant    template <class Lock>
783e519524SHoward Hinnant        void wait(Lock& lock);
793e519524SHoward Hinnant    template <class Lock, class Predicate>
803e519524SHoward Hinnant        void wait(Lock& lock, Predicate pred);
813e519524SHoward Hinnant
823e519524SHoward Hinnant    template <class Lock, class Clock, class Duration>
833e519524SHoward Hinnant        cv_status
843e519524SHoward Hinnant        wait_until(Lock& lock,
853e519524SHoward Hinnant                   const chrono::time_point<Clock, Duration>& abs_time);
863e519524SHoward Hinnant
873e519524SHoward Hinnant    template <class Lock, class Clock, class Duration, class Predicate>
883e519524SHoward Hinnant        bool
893e519524SHoward Hinnant        wait_until(Lock& lock,
903e519524SHoward Hinnant                   const chrono::time_point<Clock, Duration>& abs_time,
913e519524SHoward Hinnant                   Predicate pred);
923e519524SHoward Hinnant
933e519524SHoward Hinnant    template <class Lock, class Rep, class Period>
943e519524SHoward Hinnant        cv_status
953e519524SHoward Hinnant        wait_for(Lock& lock,
963e519524SHoward Hinnant                 const chrono::duration<Rep, Period>& rel_time);
973e519524SHoward Hinnant
983e519524SHoward Hinnant    template <class Lock, class Rep, class Period, class Predicate>
993e519524SHoward Hinnant        bool
1003e519524SHoward Hinnant        wait_for(Lock& lock,
1013e519524SHoward Hinnant                 const chrono::duration<Rep, Period>& rel_time,
1023e519524SHoward Hinnant                 Predicate pred);
1033e519524SHoward Hinnant};
1043e519524SHoward Hinnant
1053e519524SHoward Hinnant}  // std
1063e519524SHoward Hinnant
1073e519524SHoward Hinnant*/
1083e519524SHoward Hinnant
109385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
1103e519524SHoward Hinnant#include <__config>
1113e519524SHoward Hinnant#include <__mutex_base>
1123e519524SHoward Hinnant#include <memory>
113bd6e6846SMark de Wever#include <version>
1143e519524SHoward Hinnant
115073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1163e519524SHoward Hinnant#  pragma GCC system_header
117073458b1SHoward Hinnant#endif
1183e519524SHoward Hinnant
119b3fcc67fSJonathan Roelofs#ifndef _LIBCPP_HAS_NO_THREADS
120b3fcc67fSJonathan Roelofs
1213e519524SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
1223e519524SHoward Hinnant
1236e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS condition_variable_any
1243e519524SHoward Hinnant{
1253e519524SHoward Hinnant    condition_variable __cv_;
1263e519524SHoward Hinnant    shared_ptr<mutex>  __mut_;
1273e519524SHoward Hinnantpublic:
128906c872dSEvgeniy Stepanov    _LIBCPP_INLINE_VISIBILITY
1293e519524SHoward Hinnant    condition_variable_any();
1303e519524SHoward Hinnant
131906c872dSEvgeniy Stepanov    _LIBCPP_INLINE_VISIBILITY
13245c663dbSHoward Hinnant    void notify_one() _NOEXCEPT;
133906c872dSEvgeniy Stepanov    _LIBCPP_INLINE_VISIBILITY
13445c663dbSHoward Hinnant    void notify_all() _NOEXCEPT;
1353e519524SHoward Hinnant
1363e519524SHoward Hinnant    template <class _Lock>
137bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1383e519524SHoward Hinnant        void wait(_Lock& __lock);
1393e519524SHoward Hinnant    template <class _Lock, class _Predicate>
140906c872dSEvgeniy Stepanov        _LIBCPP_INLINE_VISIBILITY
1413e519524SHoward Hinnant        void wait(_Lock& __lock, _Predicate __pred);
1423e519524SHoward Hinnant
1433e519524SHoward Hinnant    template <class _Lock, class _Clock, class _Duration>
144bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1453e519524SHoward Hinnant        cv_status
1463e519524SHoward Hinnant        wait_until(_Lock& __lock,
1473e519524SHoward Hinnant                   const chrono::time_point<_Clock, _Duration>& __t);
1483e519524SHoward Hinnant
1493e519524SHoward Hinnant    template <class _Lock, class _Clock, class _Duration, class _Predicate>
1503e519524SHoward Hinnant        bool
151906c872dSEvgeniy Stepanov        _LIBCPP_INLINE_VISIBILITY
1523e519524SHoward Hinnant        wait_until(_Lock& __lock,
1533e519524SHoward Hinnant                   const chrono::time_point<_Clock, _Duration>& __t,
1543e519524SHoward Hinnant                   _Predicate __pred);
1553e519524SHoward Hinnant
1563e519524SHoward Hinnant    template <class _Lock, class _Rep, class _Period>
1573e519524SHoward Hinnant        cv_status
158906c872dSEvgeniy Stepanov        _LIBCPP_INLINE_VISIBILITY
1593e519524SHoward Hinnant        wait_for(_Lock& __lock,
1603e519524SHoward Hinnant                 const chrono::duration<_Rep, _Period>& __d);
1613e519524SHoward Hinnant
1623e519524SHoward Hinnant    template <class _Lock, class _Rep, class _Period, class _Predicate>
1633e519524SHoward Hinnant        bool
164906c872dSEvgeniy Stepanov        _LIBCPP_INLINE_VISIBILITY
1653e519524SHoward Hinnant        wait_for(_Lock& __lock,
1663e519524SHoward Hinnant                 const chrono::duration<_Rep, _Period>& __d,
1673e519524SHoward Hinnant                 _Predicate __pred);
1683e519524SHoward Hinnant};
1693e519524SHoward Hinnant
170906c872dSEvgeniy Stepanovinline
1713e519524SHoward Hinnantcondition_variable_any::condition_variable_any()
1723e519524SHoward Hinnant    : __mut_(make_shared<mutex>()) {}
1733e519524SHoward Hinnant
174906c872dSEvgeniy Stepanovinline
1753e519524SHoward Hinnantvoid
17645c663dbSHoward Hinnantcondition_variable_any::notify_one() _NOEXCEPT
1773e519524SHoward Hinnant{
17854d333a6SHoward Hinnant    {lock_guard<mutex> __lx(*__mut_);}
1793e519524SHoward Hinnant    __cv_.notify_one();
1803e519524SHoward Hinnant}
1813e519524SHoward Hinnant
182906c872dSEvgeniy Stepanovinline
1833e519524SHoward Hinnantvoid
18445c663dbSHoward Hinnantcondition_variable_any::notify_all() _NOEXCEPT
1853e519524SHoward Hinnant{
18654d333a6SHoward Hinnant    {lock_guard<mutex> __lx(*__mut_);}
1873e519524SHoward Hinnant    __cv_.notify_all();
1883e519524SHoward Hinnant}
1893e519524SHoward Hinnant
1903e519524SHoward Hinnantstruct __lock_external
1913e519524SHoward Hinnant{
1923e519524SHoward Hinnant    template <class _Lock>
1933e519524SHoward Hinnant    void operator()(_Lock* __m) {__m->lock();}
1943e519524SHoward Hinnant};
1953e519524SHoward Hinnant
1963e519524SHoward Hinnanttemplate <class _Lock>
1973e519524SHoward Hinnantvoid
1983e519524SHoward Hinnantcondition_variable_any::wait(_Lock& __lock)
1993e519524SHoward Hinnant{
2003e519524SHoward Hinnant    shared_ptr<mutex> __mut = __mut_;
2013e519524SHoward Hinnant    unique_lock<mutex> __lk(*__mut);
2023e519524SHoward Hinnant    __lock.unlock();
20354d333a6SHoward Hinnant    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
20454d333a6SHoward Hinnant    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2053e519524SHoward Hinnant    __cv_.wait(__lk);
2063e519524SHoward Hinnant}  // __mut_.unlock(), __lock.lock()
2073e519524SHoward Hinnant
2083e519524SHoward Hinnanttemplate <class _Lock, class _Predicate>
209906c872dSEvgeniy Stepanovinline
2103e519524SHoward Hinnantvoid
2113e519524SHoward Hinnantcondition_variable_any::wait(_Lock& __lock, _Predicate __pred)
2123e519524SHoward Hinnant{
2133e519524SHoward Hinnant    while (!__pred())
2143e519524SHoward Hinnant        wait(__lock);
2153e519524SHoward Hinnant}
2163e519524SHoward Hinnant
2173e519524SHoward Hinnanttemplate <class _Lock, class _Clock, class _Duration>
2183e519524SHoward Hinnantcv_status
2193e519524SHoward Hinnantcondition_variable_any::wait_until(_Lock& __lock,
2203e519524SHoward Hinnant                                   const chrono::time_point<_Clock, _Duration>& __t)
2213e519524SHoward Hinnant{
2223e519524SHoward Hinnant    shared_ptr<mutex> __mut = __mut_;
2233e519524SHoward Hinnant    unique_lock<mutex> __lk(*__mut);
2243e519524SHoward Hinnant    __lock.unlock();
22554d333a6SHoward Hinnant    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
22654d333a6SHoward Hinnant    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2273e519524SHoward Hinnant    return __cv_.wait_until(__lk, __t);
2283e519524SHoward Hinnant}  // __mut_.unlock(), __lock.lock()
2293e519524SHoward Hinnant
2303e519524SHoward Hinnanttemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
231906c872dSEvgeniy Stepanovinline
2323e519524SHoward Hinnantbool
2333e519524SHoward Hinnantcondition_variable_any::wait_until(_Lock& __lock,
2343e519524SHoward Hinnant                                   const chrono::time_point<_Clock, _Duration>& __t,
2353e519524SHoward Hinnant                                   _Predicate __pred)
2363e519524SHoward Hinnant{
2373e519524SHoward Hinnant    while (!__pred())
2383e519524SHoward Hinnant        if (wait_until(__lock, __t) == cv_status::timeout)
2393e519524SHoward Hinnant            return __pred();
2403e519524SHoward Hinnant    return true;
2413e519524SHoward Hinnant}
2423e519524SHoward Hinnant
2433e519524SHoward Hinnanttemplate <class _Lock, class _Rep, class _Period>
244906c872dSEvgeniy Stepanovinline
2453e519524SHoward Hinnantcv_status
2463e519524SHoward Hinnantcondition_variable_any::wait_for(_Lock& __lock,
2473e519524SHoward Hinnant                                 const chrono::duration<_Rep, _Period>& __d)
2483e519524SHoward Hinnant{
2493dc6455fSHoward Hinnant    return wait_until(__lock, chrono::steady_clock::now() + __d);
2503e519524SHoward Hinnant}
2513e519524SHoward Hinnant
2523e519524SHoward Hinnanttemplate <class _Lock, class _Rep, class _Period, class _Predicate>
253906c872dSEvgeniy Stepanovinline
2543e519524SHoward Hinnantbool
2553e519524SHoward Hinnantcondition_variable_any::wait_for(_Lock& __lock,
2563e519524SHoward Hinnant                                 const chrono::duration<_Rep, _Period>& __d,
2573e519524SHoward Hinnant                                 _Predicate __pred)
2583e519524SHoward Hinnant{
2593dc6455fSHoward Hinnant    return wait_until(__lock, chrono::steady_clock::now() + __d,
260ce48a113SHoward Hinnant                      _VSTD::move(__pred));
2613e519524SHoward Hinnant}
2623e519524SHoward Hinnant
2636e41256fSHoward Hinnant_LIBCPP_FUNC_VIS
264*b48c5010SNikolas Klauservoid notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);
265b77c0c03SHoward Hinnant
2663e519524SHoward Hinnant_LIBCPP_END_NAMESPACE_STD
2673e519524SHoward Hinnant
268b3fcc67fSJonathan Roelofs#endif // !_LIBCPP_HAS_NO_THREADS
269b3fcc67fSJonathan Roelofs
2703e519524SHoward Hinnant#endif // _LIBCPP_CONDITION_VARIABLE
271