xref: /freebsd/contrib/llvm-project/libcxx/include/__cxx03/condition_variable (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric// -*- C++ -*-
2*700637cbSDimitry Andric//===----------------------------------------------------------------------===//
3*700637cbSDimitry Andric//
4*700637cbSDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*700637cbSDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
6*700637cbSDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*700637cbSDimitry Andric//
8*700637cbSDimitry Andric//===----------------------------------------------------------------------===//
9*700637cbSDimitry Andric
10*700637cbSDimitry Andric#ifndef _LIBCPP___CXX03_CONDITION_VARIABLE
11*700637cbSDimitry Andric#define _LIBCPP___CXX03_CONDITION_VARIABLE
12*700637cbSDimitry Andric
13*700637cbSDimitry Andric/*
14*700637cbSDimitry Andric    condition_variable synopsis
15*700637cbSDimitry Andric
16*700637cbSDimitry Andricnamespace std
17*700637cbSDimitry Andric{
18*700637cbSDimitry Andric
19*700637cbSDimitry Andricenum class cv_status { no_timeout, timeout };
20*700637cbSDimitry Andric
21*700637cbSDimitry Andricclass condition_variable
22*700637cbSDimitry Andric{
23*700637cbSDimitry Andricpublic:
24*700637cbSDimitry Andric    condition_variable();
25*700637cbSDimitry Andric    ~condition_variable();
26*700637cbSDimitry Andric
27*700637cbSDimitry Andric    condition_variable(const condition_variable&) = delete;
28*700637cbSDimitry Andric    condition_variable& operator=(const condition_variable&) = delete;
29*700637cbSDimitry Andric
30*700637cbSDimitry Andric    void notify_one() noexcept;
31*700637cbSDimitry Andric    void notify_all() noexcept;
32*700637cbSDimitry Andric
33*700637cbSDimitry Andric    void wait(unique_lock<mutex>& lock);
34*700637cbSDimitry Andric    template <class Predicate>
35*700637cbSDimitry Andric        void wait(unique_lock<mutex>& lock, Predicate pred);
36*700637cbSDimitry Andric
37*700637cbSDimitry Andric    template <class Clock, class Duration>
38*700637cbSDimitry Andric        cv_status
39*700637cbSDimitry Andric        wait_until(unique_lock<mutex>& lock,
40*700637cbSDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time);
41*700637cbSDimitry Andric
42*700637cbSDimitry Andric    template <class Clock, class Duration, class Predicate>
43*700637cbSDimitry Andric        bool
44*700637cbSDimitry Andric        wait_until(unique_lock<mutex>& lock,
45*700637cbSDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time,
46*700637cbSDimitry Andric                   Predicate pred);
47*700637cbSDimitry Andric
48*700637cbSDimitry Andric    template <class Rep, class Period>
49*700637cbSDimitry Andric        cv_status
50*700637cbSDimitry Andric        wait_for(unique_lock<mutex>& lock,
51*700637cbSDimitry Andric                 const chrono::duration<Rep, Period>& rel_time);
52*700637cbSDimitry Andric
53*700637cbSDimitry Andric    template <class Rep, class Period, class Predicate>
54*700637cbSDimitry Andric        bool
55*700637cbSDimitry Andric        wait_for(unique_lock<mutex>& lock,
56*700637cbSDimitry Andric                 const chrono::duration<Rep, Period>& rel_time,
57*700637cbSDimitry Andric                 Predicate pred);
58*700637cbSDimitry Andric
59*700637cbSDimitry Andric    typedef pthread_cond_t* native_handle_type;
60*700637cbSDimitry Andric    native_handle_type native_handle();
61*700637cbSDimitry Andric};
62*700637cbSDimitry Andric
63*700637cbSDimitry Andricvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
64*700637cbSDimitry Andric
65*700637cbSDimitry Andricclass condition_variable_any
66*700637cbSDimitry Andric{
67*700637cbSDimitry Andricpublic:
68*700637cbSDimitry Andric    condition_variable_any();
69*700637cbSDimitry Andric    ~condition_variable_any();
70*700637cbSDimitry Andric
71*700637cbSDimitry Andric    condition_variable_any(const condition_variable_any&) = delete;
72*700637cbSDimitry Andric    condition_variable_any& operator=(const condition_variable_any&) = delete;
73*700637cbSDimitry Andric
74*700637cbSDimitry Andric    void notify_one() noexcept;
75*700637cbSDimitry Andric    void notify_all() noexcept;
76*700637cbSDimitry Andric
77*700637cbSDimitry Andric    template <class Lock>
78*700637cbSDimitry Andric        void wait(Lock& lock);
79*700637cbSDimitry Andric    template <class Lock, class Predicate>
80*700637cbSDimitry Andric        void wait(Lock& lock, Predicate pred);
81*700637cbSDimitry Andric
82*700637cbSDimitry Andric    template <class Lock, class Clock, class Duration>
83*700637cbSDimitry Andric        cv_status
84*700637cbSDimitry Andric        wait_until(Lock& lock,
85*700637cbSDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time);
86*700637cbSDimitry Andric
87*700637cbSDimitry Andric    template <class Lock, class Clock, class Duration, class Predicate>
88*700637cbSDimitry Andric        bool
89*700637cbSDimitry Andric        wait_until(Lock& lock,
90*700637cbSDimitry Andric                   const chrono::time_point<Clock, Duration>& abs_time,
91*700637cbSDimitry Andric                   Predicate pred);
92*700637cbSDimitry Andric
93*700637cbSDimitry Andric    template <class Lock, class Rep, class Period>
94*700637cbSDimitry Andric        cv_status
95*700637cbSDimitry Andric        wait_for(Lock& lock,
96*700637cbSDimitry Andric                 const chrono::duration<Rep, Period>& rel_time);
97*700637cbSDimitry Andric
98*700637cbSDimitry Andric    template <class Lock, class Rep, class Period, class Predicate>
99*700637cbSDimitry Andric        bool
100*700637cbSDimitry Andric        wait_for(Lock& lock,
101*700637cbSDimitry Andric                 const chrono::duration<Rep, Period>& rel_time,
102*700637cbSDimitry Andric                 Predicate pred);
103*700637cbSDimitry Andric
104*700637cbSDimitry Andric    // [thread.condvarany.intwait], interruptible waits
105*700637cbSDimitry Andric    template <class Lock, class Predicate>
106*700637cbSDimitry Andric      bool wait(Lock& lock, stop_token stoken, Predicate pred);                               // since C++20
107*700637cbSDimitry Andric
108*700637cbSDimitry Andric    template <class Lock, class Clock, class Duration, class Predicate>
109*700637cbSDimitry Andric      bool wait_until(Lock& lock, stop_token stoken,
110*700637cbSDimitry Andric                      const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);   // since C++20
111*700637cbSDimitry Andric
112*700637cbSDimitry Andric    template <class Lock, class Rep, class Period, class Predicate>
113*700637cbSDimitry Andric      bool wait_for(Lock& lock, stop_token stoken,
114*700637cbSDimitry Andric                    const chrono::duration<Rep, Period>& rel_time, Predicate pred);           // since C++20
115*700637cbSDimitry Andric};
116*700637cbSDimitry Andric
117*700637cbSDimitry Andric}  // std
118*700637cbSDimitry Andric
119*700637cbSDimitry Andric*/
120*700637cbSDimitry Andric
121*700637cbSDimitry Andric#include <__cxx03/__chrono/duration.h>
122*700637cbSDimitry Andric#include <__cxx03/__chrono/steady_clock.h>
123*700637cbSDimitry Andric#include <__cxx03/__chrono/time_point.h>
124*700637cbSDimitry Andric#include <__cxx03/__condition_variable/condition_variable.h>
125*700637cbSDimitry Andric#include <__cxx03/__config>
126*700637cbSDimitry Andric#include <__cxx03/__memory/shared_ptr.h>
127*700637cbSDimitry Andric#include <__cxx03/__mutex/lock_guard.h>
128*700637cbSDimitry Andric#include <__cxx03/__mutex/mutex.h>
129*700637cbSDimitry Andric#include <__cxx03/__mutex/tag_types.h>
130*700637cbSDimitry Andric#include <__cxx03/__mutex/unique_lock.h>
131*700637cbSDimitry Andric#include <__cxx03/__utility/move.h>
132*700637cbSDimitry Andric#include <__cxx03/version>
133*700637cbSDimitry Andric
134*700637cbSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
135*700637cbSDimitry Andric#  pragma GCC system_header
136*700637cbSDimitry Andric#endif
137*700637cbSDimitry Andric
138*700637cbSDimitry Andric_LIBCPP_PUSH_MACROS
139*700637cbSDimitry Andric#include <__cxx03/__undef_macros>
140*700637cbSDimitry Andric
141*700637cbSDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS
142*700637cbSDimitry Andric
143*700637cbSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
144*700637cbSDimitry Andric
145*700637cbSDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI condition_variable_any {
146*700637cbSDimitry Andric  condition_variable __cv_;
147*700637cbSDimitry Andric  shared_ptr<mutex> __mut_;
148*700637cbSDimitry Andric
149*700637cbSDimitry Andricpublic:
150*700637cbSDimitry Andric  _LIBCPP_HIDE_FROM_ABI condition_variable_any();
151*700637cbSDimitry Andric
152*700637cbSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT;
153*700637cbSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT;
154*700637cbSDimitry Andric
155*700637cbSDimitry Andric  template <class _Lock>
156*700637cbSDimitry Andric  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(_Lock& __lock);
157*700637cbSDimitry Andric  template <class _Lock, class _Predicate>
158*700637cbSDimitry Andric  _LIBCPP_HIDE_FROM_ABI void wait(_Lock& __lock, _Predicate __pred);
159*700637cbSDimitry Andric
160*700637cbSDimitry Andric  template <class _Lock, class _Clock, class _Duration>
161*700637cbSDimitry Andric  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
162*700637cbSDimitry Andric  wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t);
163*700637cbSDimitry Andric
164*700637cbSDimitry Andric  template <class _Lock, class _Clock, class _Duration, class _Predicate>
165*700637cbSDimitry Andric  bool _LIBCPP_HIDE_FROM_ABI
166*700637cbSDimitry Andric  wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred);
167*700637cbSDimitry Andric
168*700637cbSDimitry Andric  template <class _Lock, class _Rep, class _Period>
169*700637cbSDimitry Andric  cv_status _LIBCPP_HIDE_FROM_ABI wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d);
170*700637cbSDimitry Andric
171*700637cbSDimitry Andric  template <class _Lock, class _Rep, class _Period, class _Predicate>
172*700637cbSDimitry Andric  bool _LIBCPP_HIDE_FROM_ABI wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
173*700637cbSDimitry Andric};
174*700637cbSDimitry Andric
175*700637cbSDimitry Andricinline condition_variable_any::condition_variable_any() : __mut_(make_shared<mutex>()) {}
176*700637cbSDimitry Andric
177*700637cbSDimitry Andricinline void condition_variable_any::notify_one() _NOEXCEPT {
178*700637cbSDimitry Andric  { lock_guard<mutex> __lx(*__mut_); }
179*700637cbSDimitry Andric  __cv_.notify_one();
180*700637cbSDimitry Andric}
181*700637cbSDimitry Andric
182*700637cbSDimitry Andricinline void condition_variable_any::notify_all() _NOEXCEPT {
183*700637cbSDimitry Andric  { lock_guard<mutex> __lx(*__mut_); }
184*700637cbSDimitry Andric  __cv_.notify_all();
185*700637cbSDimitry Andric}
186*700637cbSDimitry Andric
187*700637cbSDimitry Andrictemplate <class _Lock>
188*700637cbSDimitry Andricstruct __unlock_guard {
189*700637cbSDimitry Andric  _Lock& __lock_;
190*700637cbSDimitry Andric
191*700637cbSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __unlock_guard(_Lock& __lock) : __lock_(__lock) { __lock_.unlock(); }
192*700637cbSDimitry Andric
193*700637cbSDimitry Andric  _LIBCPP_HIDE_FROM_ABI ~__unlock_guard() _NOEXCEPT // turns exception to std::terminate
194*700637cbSDimitry Andric  {
195*700637cbSDimitry Andric    __lock_.lock();
196*700637cbSDimitry Andric  }
197*700637cbSDimitry Andric
198*700637cbSDimitry Andric  __unlock_guard(const __unlock_guard&)            = delete;
199*700637cbSDimitry Andric  __unlock_guard& operator=(const __unlock_guard&) = delete;
200*700637cbSDimitry Andric};
201*700637cbSDimitry Andric
202*700637cbSDimitry Andrictemplate <class _Lock>
203*700637cbSDimitry Andricvoid condition_variable_any::wait(_Lock& __lock) {
204*700637cbSDimitry Andric  shared_ptr<mutex> __mut = __mut_;
205*700637cbSDimitry Andric  unique_lock<mutex> __lk(*__mut);
206*700637cbSDimitry Andric  __unlock_guard<_Lock> __unlock(__lock);
207*700637cbSDimitry Andric  lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
208*700637cbSDimitry Andric  __cv_.wait(__lk);
209*700637cbSDimitry Andric} // __mut_.unlock(), __lock.lock()
210*700637cbSDimitry Andric
211*700637cbSDimitry Andrictemplate <class _Lock, class _Predicate>
212*700637cbSDimitry Andricinline void condition_variable_any::wait(_Lock& __lock, _Predicate __pred) {
213*700637cbSDimitry Andric  while (!__pred())
214*700637cbSDimitry Andric    wait(__lock);
215*700637cbSDimitry Andric}
216*700637cbSDimitry Andric
217*700637cbSDimitry Andrictemplate <class _Lock, class _Clock, class _Duration>
218*700637cbSDimitry Andriccv_status condition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t) {
219*700637cbSDimitry Andric  shared_ptr<mutex> __mut = __mut_;
220*700637cbSDimitry Andric  unique_lock<mutex> __lk(*__mut);
221*700637cbSDimitry Andric  __unlock_guard<_Lock> __unlock(__lock);
222*700637cbSDimitry Andric  lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
223*700637cbSDimitry Andric  return __cv_.wait_until(__lk, __t);
224*700637cbSDimitry Andric} // __mut_.unlock(), __lock.lock()
225*700637cbSDimitry Andric
226*700637cbSDimitry Andrictemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
227*700637cbSDimitry Andricinline bool
228*700637cbSDimitry Andriccondition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
229*700637cbSDimitry Andric  while (!__pred())
230*700637cbSDimitry Andric    if (wait_until(__lock, __t) == cv_status::timeout)
231*700637cbSDimitry Andric      return __pred();
232*700637cbSDimitry Andric  return true;
233*700637cbSDimitry Andric}
234*700637cbSDimitry Andric
235*700637cbSDimitry Andrictemplate <class _Lock, class _Rep, class _Period>
236*700637cbSDimitry Andricinline cv_status condition_variable_any::wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d) {
237*700637cbSDimitry Andric  return wait_until(__lock, chrono::steady_clock::now() + __d);
238*700637cbSDimitry Andric}
239*700637cbSDimitry Andric
240*700637cbSDimitry Andrictemplate <class _Lock, class _Rep, class _Period, class _Predicate>
241*700637cbSDimitry Andricinline bool
242*700637cbSDimitry Andriccondition_variable_any::wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) {
243*700637cbSDimitry Andric  return wait_until(__lock, chrono::steady_clock::now() + __d, std::move(__pred));
244*700637cbSDimitry Andric}
245*700637cbSDimitry Andric
246*700637cbSDimitry Andric_LIBCPP_EXPORTED_FROM_ABI void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);
247*700637cbSDimitry Andric
248*700637cbSDimitry Andric_LIBCPP_END_NAMESPACE_STD
249*700637cbSDimitry Andric
250*700637cbSDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
251*700637cbSDimitry Andric
252*700637cbSDimitry Andric_LIBCPP_POP_MACROS
253*700637cbSDimitry Andric
254*700637cbSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES)
255*700637cbSDimitry Andric#  include <__cxx03/atomic>
256*700637cbSDimitry Andric#  include <__cxx03/cstdint>
257*700637cbSDimitry Andric#  include <__cxx03/cstdlib>
258*700637cbSDimitry Andric#  include <__cxx03/cstring>
259*700637cbSDimitry Andric#  include <__cxx03/iosfwd>
260*700637cbSDimitry Andric#  include <__cxx03/new>
261*700637cbSDimitry Andric#  include <__cxx03/stdexcept>
262*700637cbSDimitry Andric#  include <__cxx03/system_error>
263*700637cbSDimitry Andric#  include <__cxx03/type_traits>
264*700637cbSDimitry Andric#  include <__cxx03/typeinfo>
265*700637cbSDimitry Andric#endif
266*700637cbSDimitry Andric
267*700637cbSDimitry Andric#endif // _LIBCPP___CXX03_CONDITION_VARIABLE
268