xref: /freebsd/contrib/llvm-project/libcxx/include/condition_variable (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
10b57cec5SDimitry Andric// -*- C++ -*-
2*349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_CONDITION_VARIABLE
110b57cec5SDimitry Andric#define _LIBCPP_CONDITION_VARIABLE
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    condition_variable synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andricnamespace std
170b57cec5SDimitry Andric{
180b57cec5SDimitry Andric
190b57cec5SDimitry Andricenum class cv_status { no_timeout, timeout };
200b57cec5SDimitry Andric
210b57cec5SDimitry Andricclass condition_variable
220b57cec5SDimitry Andric{
230b57cec5SDimitry Andricpublic:
240b57cec5SDimitry Andric    condition_variable();
250b57cec5SDimitry Andric    ~condition_variable();
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric    condition_variable(const condition_variable&) = delete;
280b57cec5SDimitry Andric    condition_variable& operator=(const condition_variable&) = delete;
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric    void notify_one() noexcept;
310b57cec5SDimitry Andric    void notify_all() noexcept;
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric    void wait(unique_lock<mutex>& lock);
340b57cec5SDimitry Andric    template <class Predicate>
350b57cec5SDimitry Andric        void wait(unique_lock<mutex>& lock, Predicate pred);
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric    template <class Clock, class Duration>
380b57cec5SDimitry Andric        cv_status
390b57cec5SDimitry Andric        wait_until(unique_lock<mutex>& lock,
400b57cec5SDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time);
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric    template <class Clock, class Duration, class Predicate>
430b57cec5SDimitry Andric        bool
440b57cec5SDimitry Andric        wait_until(unique_lock<mutex>& lock,
450b57cec5SDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time,
460b57cec5SDimitry Andric                   Predicate pred);
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric    template <class Rep, class Period>
490b57cec5SDimitry Andric        cv_status
500b57cec5SDimitry Andric        wait_for(unique_lock<mutex>& lock,
510b57cec5SDimitry Andric                 const chrono::duration<Rep, Period>& rel_time);
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric    template <class Rep, class Period, class Predicate>
540b57cec5SDimitry Andric        bool
550b57cec5SDimitry Andric        wait_for(unique_lock<mutex>& lock,
560b57cec5SDimitry Andric                 const chrono::duration<Rep, Period>& rel_time,
570b57cec5SDimitry Andric                 Predicate pred);
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric    typedef pthread_cond_t* native_handle_type;
600b57cec5SDimitry Andric    native_handle_type native_handle();
610b57cec5SDimitry Andric};
620b57cec5SDimitry Andric
630b57cec5SDimitry Andricvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
640b57cec5SDimitry Andric
650b57cec5SDimitry Andricclass condition_variable_any
660b57cec5SDimitry Andric{
670b57cec5SDimitry Andricpublic:
680b57cec5SDimitry Andric    condition_variable_any();
690b57cec5SDimitry Andric    ~condition_variable_any();
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric    condition_variable_any(const condition_variable_any&) = delete;
720b57cec5SDimitry Andric    condition_variable_any& operator=(const condition_variable_any&) = delete;
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric    void notify_one() noexcept;
750b57cec5SDimitry Andric    void notify_all() noexcept;
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric    template <class Lock>
780b57cec5SDimitry Andric        void wait(Lock& lock);
790b57cec5SDimitry Andric    template <class Lock, class Predicate>
800b57cec5SDimitry Andric        void wait(Lock& lock, Predicate pred);
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric    template <class Lock, class Clock, class Duration>
830b57cec5SDimitry Andric        cv_status
840b57cec5SDimitry Andric        wait_until(Lock& lock,
850b57cec5SDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time);
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric    template <class Lock, class Clock, class Duration, class Predicate>
880b57cec5SDimitry Andric        bool
890b57cec5SDimitry Andric        wait_until(Lock& lock,
900b57cec5SDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time,
910b57cec5SDimitry Andric                   Predicate pred);
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric    template <class Lock, class Rep, class Period>
940b57cec5SDimitry Andric        cv_status
950b57cec5SDimitry Andric        wait_for(Lock& lock,
960b57cec5SDimitry Andric                 const chrono::duration<Rep, Period>& rel_time);
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric    template <class Lock, class Rep, class Period, class Predicate>
990b57cec5SDimitry Andric        bool
1000b57cec5SDimitry Andric        wait_for(Lock& lock,
1010b57cec5SDimitry Andric                 const chrono::duration<Rep, Period>& rel_time,
1020b57cec5SDimitry Andric                 Predicate pred);
1030b57cec5SDimitry Andric};
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric}  // std
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric*/
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric#include <__config>
1100b57cec5SDimitry Andric#include <__mutex_base>
1110b57cec5SDimitry Andric#include <memory>
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1140b57cec5SDimitry Andric#pragma GCC system_header
1150b57cec5SDimitry Andric#endif
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS condition_variable_any
1220b57cec5SDimitry Andric{
1230b57cec5SDimitry Andric    condition_variable __cv_;
1240b57cec5SDimitry Andric    shared_ptr<mutex>  __mut_;
1250b57cec5SDimitry Andricpublic:
1260b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1270b57cec5SDimitry Andric    condition_variable_any();
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1300b57cec5SDimitry Andric    void notify_one() _NOEXCEPT;
1310b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1320b57cec5SDimitry Andric    void notify_all() _NOEXCEPT;
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric    template <class _Lock>
1350b57cec5SDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1360b57cec5SDimitry Andric        void wait(_Lock& __lock);
1370b57cec5SDimitry Andric    template <class _Lock, class _Predicate>
1380b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1390b57cec5SDimitry Andric        void wait(_Lock& __lock, _Predicate __pred);
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric    template <class _Lock, class _Clock, class _Duration>
1420b57cec5SDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1430b57cec5SDimitry Andric        cv_status
1440b57cec5SDimitry Andric        wait_until(_Lock& __lock,
1450b57cec5SDimitry Andric                   const chrono::time_point<_Clock, _Duration>& __t);
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric    template <class _Lock, class _Clock, class _Duration, class _Predicate>
1480b57cec5SDimitry Andric        bool
1490b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1500b57cec5SDimitry Andric        wait_until(_Lock& __lock,
1510b57cec5SDimitry Andric                   const chrono::time_point<_Clock, _Duration>& __t,
1520b57cec5SDimitry Andric                   _Predicate __pred);
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric    template <class _Lock, class _Rep, class _Period>
1550b57cec5SDimitry Andric        cv_status
1560b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1570b57cec5SDimitry Andric        wait_for(_Lock& __lock,
1580b57cec5SDimitry Andric                 const chrono::duration<_Rep, _Period>& __d);
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric    template <class _Lock, class _Rep, class _Period, class _Predicate>
1610b57cec5SDimitry Andric        bool
1620b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1630b57cec5SDimitry Andric        wait_for(_Lock& __lock,
1640b57cec5SDimitry Andric                 const chrono::duration<_Rep, _Period>& __d,
1650b57cec5SDimitry Andric                 _Predicate __pred);
1660b57cec5SDimitry Andric};
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andricinline
1690b57cec5SDimitry Andriccondition_variable_any::condition_variable_any()
1700b57cec5SDimitry Andric    : __mut_(make_shared<mutex>()) {}
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andricinline
1730b57cec5SDimitry Andricvoid
1740b57cec5SDimitry Andriccondition_variable_any::notify_one() _NOEXCEPT
1750b57cec5SDimitry Andric{
1760b57cec5SDimitry Andric    {lock_guard<mutex> __lx(*__mut_);}
1770b57cec5SDimitry Andric    __cv_.notify_one();
1780b57cec5SDimitry Andric}
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andricinline
1810b57cec5SDimitry Andricvoid
1820b57cec5SDimitry Andriccondition_variable_any::notify_all() _NOEXCEPT
1830b57cec5SDimitry Andric{
1840b57cec5SDimitry Andric    {lock_guard<mutex> __lx(*__mut_);}
1850b57cec5SDimitry Andric    __cv_.notify_all();
1860b57cec5SDimitry Andric}
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andricstruct __lock_external
1890b57cec5SDimitry Andric{
1900b57cec5SDimitry Andric    template <class _Lock>
1910b57cec5SDimitry Andric    void operator()(_Lock* __m) {__m->lock();}
1920b57cec5SDimitry Andric};
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andrictemplate <class _Lock>
1950b57cec5SDimitry Andricvoid
1960b57cec5SDimitry Andriccondition_variable_any::wait(_Lock& __lock)
1970b57cec5SDimitry Andric{
1980b57cec5SDimitry Andric    shared_ptr<mutex> __mut = __mut_;
1990b57cec5SDimitry Andric    unique_lock<mutex> __lk(*__mut);
2000b57cec5SDimitry Andric    __lock.unlock();
2010b57cec5SDimitry Andric    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
2020b57cec5SDimitry Andric    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2030b57cec5SDimitry Andric    __cv_.wait(__lk);
2040b57cec5SDimitry Andric}  // __mut_.unlock(), __lock.lock()
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andrictemplate <class _Lock, class _Predicate>
2070b57cec5SDimitry Andricinline
2080b57cec5SDimitry Andricvoid
2090b57cec5SDimitry Andriccondition_variable_any::wait(_Lock& __lock, _Predicate __pred)
2100b57cec5SDimitry Andric{
2110b57cec5SDimitry Andric    while (!__pred())
2120b57cec5SDimitry Andric        wait(__lock);
2130b57cec5SDimitry Andric}
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration>
2160b57cec5SDimitry Andriccv_status
2170b57cec5SDimitry Andriccondition_variable_any::wait_until(_Lock& __lock,
2180b57cec5SDimitry Andric                                   const chrono::time_point<_Clock, _Duration>& __t)
2190b57cec5SDimitry Andric{
2200b57cec5SDimitry Andric    shared_ptr<mutex> __mut = __mut_;
2210b57cec5SDimitry Andric    unique_lock<mutex> __lk(*__mut);
2220b57cec5SDimitry Andric    __lock.unlock();
2230b57cec5SDimitry Andric    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
2240b57cec5SDimitry Andric    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2250b57cec5SDimitry Andric    return __cv_.wait_until(__lk, __t);
2260b57cec5SDimitry Andric}  // __mut_.unlock(), __lock.lock()
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
2290b57cec5SDimitry Andricinline
2300b57cec5SDimitry Andricbool
2310b57cec5SDimitry Andriccondition_variable_any::wait_until(_Lock& __lock,
2320b57cec5SDimitry Andric                                   const chrono::time_point<_Clock, _Duration>& __t,
2330b57cec5SDimitry Andric                                   _Predicate __pred)
2340b57cec5SDimitry Andric{
2350b57cec5SDimitry Andric    while (!__pred())
2360b57cec5SDimitry Andric        if (wait_until(__lock, __t) == cv_status::timeout)
2370b57cec5SDimitry Andric            return __pred();
2380b57cec5SDimitry Andric    return true;
2390b57cec5SDimitry Andric}
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period>
2420b57cec5SDimitry Andricinline
2430b57cec5SDimitry Andriccv_status
2440b57cec5SDimitry Andriccondition_variable_any::wait_for(_Lock& __lock,
2450b57cec5SDimitry Andric                                 const chrono::duration<_Rep, _Period>& __d)
2460b57cec5SDimitry Andric{
2470b57cec5SDimitry Andric    return wait_until(__lock, chrono::steady_clock::now() + __d);
2480b57cec5SDimitry Andric}
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period, class _Predicate>
2510b57cec5SDimitry Andricinline
2520b57cec5SDimitry Andricbool
2530b57cec5SDimitry Andriccondition_variable_any::wait_for(_Lock& __lock,
2540b57cec5SDimitry Andric                                 const chrono::duration<_Rep, _Period>& __d,
2550b57cec5SDimitry Andric                                 _Predicate __pred)
2560b57cec5SDimitry Andric{
2570b57cec5SDimitry Andric    return wait_until(__lock, chrono::steady_clock::now() + __d,
2580b57cec5SDimitry Andric                      _VSTD::move(__pred));
2590b57cec5SDimitry Andric}
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric_LIBCPP_FUNC_VIS
2620b57cec5SDimitry Andricvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric#endif // _LIBCPP_CONDITION_VARIABLE
269