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