xref: /freebsd/contrib/llvm-project/libcxx/include/condition_variable (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry 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>
112*04eeddc0SDimitry Andric#include <version>
1130b57cec5SDimitry Andric
1140b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1150b57cec5SDimitry Andric#pragma GCC system_header
1160b57cec5SDimitry Andric#endif
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS condition_variable_any
1230b57cec5SDimitry Andric{
1240b57cec5SDimitry Andric    condition_variable __cv_;
1250b57cec5SDimitry Andric    shared_ptr<mutex>  __mut_;
1260b57cec5SDimitry Andricpublic:
1270b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1280b57cec5SDimitry Andric    condition_variable_any();
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1310b57cec5SDimitry Andric    void notify_one() _NOEXCEPT;
1320b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1330b57cec5SDimitry Andric    void notify_all() _NOEXCEPT;
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric    template <class _Lock>
1360b57cec5SDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1370b57cec5SDimitry Andric        void wait(_Lock& __lock);
1380b57cec5SDimitry Andric    template <class _Lock, class _Predicate>
1390b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1400b57cec5SDimitry Andric        void wait(_Lock& __lock, _Predicate __pred);
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric    template <class _Lock, class _Clock, class _Duration>
1430b57cec5SDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1440b57cec5SDimitry Andric        cv_status
1450b57cec5SDimitry Andric        wait_until(_Lock& __lock,
1460b57cec5SDimitry Andric                   const chrono::time_point<_Clock, _Duration>& __t);
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric    template <class _Lock, class _Clock, class _Duration, class _Predicate>
1490b57cec5SDimitry Andric        bool
1500b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1510b57cec5SDimitry Andric        wait_until(_Lock& __lock,
1520b57cec5SDimitry Andric                   const chrono::time_point<_Clock, _Duration>& __t,
1530b57cec5SDimitry Andric                   _Predicate __pred);
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric    template <class _Lock, class _Rep, class _Period>
1560b57cec5SDimitry Andric        cv_status
1570b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1580b57cec5SDimitry Andric        wait_for(_Lock& __lock,
1590b57cec5SDimitry Andric                 const chrono::duration<_Rep, _Period>& __d);
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric    template <class _Lock, class _Rep, class _Period, class _Predicate>
1620b57cec5SDimitry Andric        bool
1630b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
1640b57cec5SDimitry Andric        wait_for(_Lock& __lock,
1650b57cec5SDimitry Andric                 const chrono::duration<_Rep, _Period>& __d,
1660b57cec5SDimitry Andric                 _Predicate __pred);
1670b57cec5SDimitry Andric};
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andricinline
1700b57cec5SDimitry Andriccondition_variable_any::condition_variable_any()
1710b57cec5SDimitry Andric    : __mut_(make_shared<mutex>()) {}
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andricinline
1740b57cec5SDimitry Andricvoid
1750b57cec5SDimitry Andriccondition_variable_any::notify_one() _NOEXCEPT
1760b57cec5SDimitry Andric{
1770b57cec5SDimitry Andric    {lock_guard<mutex> __lx(*__mut_);}
1780b57cec5SDimitry Andric    __cv_.notify_one();
1790b57cec5SDimitry Andric}
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andricinline
1820b57cec5SDimitry Andricvoid
1830b57cec5SDimitry Andriccondition_variable_any::notify_all() _NOEXCEPT
1840b57cec5SDimitry Andric{
1850b57cec5SDimitry Andric    {lock_guard<mutex> __lx(*__mut_);}
1860b57cec5SDimitry Andric    __cv_.notify_all();
1870b57cec5SDimitry Andric}
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andricstruct __lock_external
1900b57cec5SDimitry Andric{
1910b57cec5SDimitry Andric    template <class _Lock>
1920b57cec5SDimitry Andric    void operator()(_Lock* __m) {__m->lock();}
1930b57cec5SDimitry Andric};
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andrictemplate <class _Lock>
1960b57cec5SDimitry Andricvoid
1970b57cec5SDimitry Andriccondition_variable_any::wait(_Lock& __lock)
1980b57cec5SDimitry Andric{
1990b57cec5SDimitry Andric    shared_ptr<mutex> __mut = __mut_;
2000b57cec5SDimitry Andric    unique_lock<mutex> __lk(*__mut);
2010b57cec5SDimitry Andric    __lock.unlock();
2020b57cec5SDimitry Andric    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
2030b57cec5SDimitry Andric    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2040b57cec5SDimitry Andric    __cv_.wait(__lk);
2050b57cec5SDimitry Andric}  // __mut_.unlock(), __lock.lock()
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andrictemplate <class _Lock, class _Predicate>
2080b57cec5SDimitry Andricinline
2090b57cec5SDimitry Andricvoid
2100b57cec5SDimitry Andriccondition_variable_any::wait(_Lock& __lock, _Predicate __pred)
2110b57cec5SDimitry Andric{
2120b57cec5SDimitry Andric    while (!__pred())
2130b57cec5SDimitry Andric        wait(__lock);
2140b57cec5SDimitry Andric}
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration>
2170b57cec5SDimitry Andriccv_status
2180b57cec5SDimitry Andriccondition_variable_any::wait_until(_Lock& __lock,
2190b57cec5SDimitry Andric                                   const chrono::time_point<_Clock, _Duration>& __t)
2200b57cec5SDimitry Andric{
2210b57cec5SDimitry Andric    shared_ptr<mutex> __mut = __mut_;
2220b57cec5SDimitry Andric    unique_lock<mutex> __lk(*__mut);
2230b57cec5SDimitry Andric    __lock.unlock();
2240b57cec5SDimitry Andric    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
2250b57cec5SDimitry Andric    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
2260b57cec5SDimitry Andric    return __cv_.wait_until(__lk, __t);
2270b57cec5SDimitry Andric}  // __mut_.unlock(), __lock.lock()
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
2300b57cec5SDimitry Andricinline
2310b57cec5SDimitry Andricbool
2320b57cec5SDimitry Andriccondition_variable_any::wait_until(_Lock& __lock,
2330b57cec5SDimitry Andric                                   const chrono::time_point<_Clock, _Duration>& __t,
2340b57cec5SDimitry Andric                                   _Predicate __pred)
2350b57cec5SDimitry Andric{
2360b57cec5SDimitry Andric    while (!__pred())
2370b57cec5SDimitry Andric        if (wait_until(__lock, __t) == cv_status::timeout)
2380b57cec5SDimitry Andric            return __pred();
2390b57cec5SDimitry Andric    return true;
2400b57cec5SDimitry Andric}
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period>
2430b57cec5SDimitry Andricinline
2440b57cec5SDimitry Andriccv_status
2450b57cec5SDimitry Andriccondition_variable_any::wait_for(_Lock& __lock,
2460b57cec5SDimitry Andric                                 const chrono::duration<_Rep, _Period>& __d)
2470b57cec5SDimitry Andric{
2480b57cec5SDimitry Andric    return wait_until(__lock, chrono::steady_clock::now() + __d);
2490b57cec5SDimitry Andric}
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period, class _Predicate>
2520b57cec5SDimitry Andricinline
2530b57cec5SDimitry Andricbool
2540b57cec5SDimitry Andriccondition_variable_any::wait_for(_Lock& __lock,
2550b57cec5SDimitry Andric                                 const chrono::duration<_Rep, _Period>& __d,
2560b57cec5SDimitry Andric                                 _Predicate __pred)
2570b57cec5SDimitry Andric{
2580b57cec5SDimitry Andric    return wait_until(__lock, chrono::steady_clock::now() + __d,
2590b57cec5SDimitry Andric                      _VSTD::move(__pred));
2600b57cec5SDimitry Andric}
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric_LIBCPP_FUNC_VIS
2630b57cec5SDimitry Andricvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric#endif // _LIBCPP_CONDITION_VARIABLE
270