1227825Stheraven// -*- C++ -*-
2227825Stheraven//===---------------------- condition_variable ----------------------------===//
3227825Stheraven//
4227825Stheraven//                     The LLVM Compiler Infrastructure
5227825Stheraven//
6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
7227825Stheraven// Source Licenses. See LICENSE.TXT for details.
8227825Stheraven//
9227825Stheraven//===----------------------------------------------------------------------===//
10227825Stheraven
11227825Stheraven#ifndef _LIBCPP_CONDITION_VARIABLE
12227825Stheraven#define _LIBCPP_CONDITION_VARIABLE
13227825Stheraven
14227825Stheraven/*
15227825Stheraven    condition_variable synopsis
16227825Stheraven
17227825Stheravennamespace std
18227825Stheraven{
19227825Stheraven
20227825Stheravenenum class cv_status { no_timeout, timeout };
21227825Stheraven
22227825Stheravenclass condition_variable
23227825Stheraven{
24227825Stheravenpublic:
25227825Stheraven    condition_variable();
26227825Stheraven    ~condition_variable();
27227825Stheraven
28227825Stheraven    condition_variable(const condition_variable&) = delete;
29227825Stheraven    condition_variable& operator=(const condition_variable&) = delete;
30227825Stheraven
31241903Sdim    void notify_one() noexcept;
32241903Sdim    void notify_all() noexcept;
33227825Stheraven
34227825Stheraven    void wait(unique_lock<mutex>& lock);
35227825Stheraven    template <class Predicate>
36227825Stheraven        void wait(unique_lock<mutex>& lock, Predicate pred);
37227825Stheraven
38227825Stheraven    template <class Clock, class Duration>
39227825Stheraven        cv_status
40227825Stheraven        wait_until(unique_lock<mutex>& lock,
41227825Stheraven                   const chrono::time_point<Clock, Duration>& abs_time);
42227825Stheraven
43227825Stheraven    template <class Clock, class Duration, class Predicate>
44227825Stheraven        bool
45227825Stheraven        wait_until(unique_lock<mutex>& lock,
46227825Stheraven                   const chrono::time_point<Clock, Duration>& abs_time,
47227825Stheraven                   Predicate pred);
48227825Stheraven
49227825Stheraven    template <class Rep, class Period>
50227825Stheraven        cv_status
51227825Stheraven        wait_for(unique_lock<mutex>& lock,
52227825Stheraven                 const chrono::duration<Rep, Period>& rel_time);
53227825Stheraven
54227825Stheraven    template <class Rep, class Period, class Predicate>
55227825Stheraven        bool
56227825Stheraven        wait_for(unique_lock<mutex>& lock,
57227825Stheraven                 const chrono::duration<Rep, Period>& rel_time,
58227825Stheraven                 Predicate pred);
59227825Stheraven
60227825Stheraven    typedef pthread_cond_t* native_handle_type;
61227825Stheraven    native_handle_type native_handle();
62227825Stheraven};
63227825Stheraven
64227825Stheravenvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
65227825Stheraven
66227825Stheravenclass condition_variable_any
67227825Stheraven{
68227825Stheravenpublic:
69227825Stheraven    condition_variable_any();
70227825Stheraven    ~condition_variable_any();
71227825Stheraven
72227825Stheraven    condition_variable_any(const condition_variable_any&) = delete;
73227825Stheraven    condition_variable_any& operator=(const condition_variable_any&) = delete;
74227825Stheraven
75241903Sdim    void notify_one() noexcept;
76241903Sdim    void notify_all() noexcept;
77227825Stheraven
78227825Stheraven    template <class Lock>
79227825Stheraven        void wait(Lock& lock);
80227825Stheraven    template <class Lock, class Predicate>
81227825Stheraven        void wait(Lock& lock, Predicate pred);
82227825Stheraven
83227825Stheraven    template <class Lock, class Clock, class Duration>
84227825Stheraven        cv_status
85227825Stheraven        wait_until(Lock& lock,
86227825Stheraven                   const chrono::time_point<Clock, Duration>& abs_time);
87227825Stheraven
88227825Stheraven    template <class Lock, class Clock, class Duration, class Predicate>
89227825Stheraven        bool
90227825Stheraven        wait_until(Lock& lock,
91227825Stheraven                   const chrono::time_point<Clock, Duration>& abs_time,
92227825Stheraven                   Predicate pred);
93227825Stheraven
94227825Stheraven    template <class Lock, class Rep, class Period>
95227825Stheraven        cv_status
96227825Stheraven        wait_for(Lock& lock,
97227825Stheraven                 const chrono::duration<Rep, Period>& rel_time);
98227825Stheraven
99227825Stheraven    template <class Lock, class Rep, class Period, class Predicate>
100227825Stheraven        bool
101227825Stheraven        wait_for(Lock& lock,
102227825Stheraven                 const chrono::duration<Rep, Period>& rel_time,
103227825Stheraven                 Predicate pred);
104227825Stheraven};
105227825Stheraven
106227825Stheraven}  // std
107227825Stheraven
108227825Stheraven*/
109227825Stheraven
110227825Stheraven#include <__config>
111227825Stheraven#include <__mutex_base>
112227825Stheraven#include <memory>
113227825Stheraven
114227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
115227825Stheraven#pragma GCC system_header
116227825Stheraven#endif
117227825Stheraven
118278724Sdim#ifndef _LIBCPP_HAS_NO_THREADS
119278724Sdim
120227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
121227825Stheraven
122249998Sdimclass _LIBCPP_TYPE_VIS condition_variable_any
123227825Stheraven{
124227825Stheraven    condition_variable __cv_;
125227825Stheraven    shared_ptr<mutex>  __mut_;
126227825Stheravenpublic:
127227825Stheraven    condition_variable_any();
128227825Stheraven
129241903Sdim    void notify_one() _NOEXCEPT;
130241903Sdim    void notify_all() _NOEXCEPT;
131227825Stheraven
132227825Stheraven    template <class _Lock>
133227825Stheraven        void wait(_Lock& __lock);
134227825Stheraven    template <class _Lock, class _Predicate>
135227825Stheraven        void wait(_Lock& __lock, _Predicate __pred);
136227825Stheraven
137227825Stheraven    template <class _Lock, class _Clock, class _Duration>
138227825Stheraven        cv_status
139227825Stheraven        wait_until(_Lock& __lock,
140227825Stheraven                   const chrono::time_point<_Clock, _Duration>& __t);
141227825Stheraven
142227825Stheraven    template <class _Lock, class _Clock, class _Duration, class _Predicate>
143227825Stheraven        bool
144227825Stheraven        wait_until(_Lock& __lock,
145227825Stheraven                   const chrono::time_point<_Clock, _Duration>& __t,
146227825Stheraven                   _Predicate __pred);
147227825Stheraven
148227825Stheraven    template <class _Lock, class _Rep, class _Period>
149227825Stheraven        cv_status
150227825Stheraven        wait_for(_Lock& __lock,
151227825Stheraven                 const chrono::duration<_Rep, _Period>& __d);
152227825Stheraven
153227825Stheraven    template <class _Lock, class _Rep, class _Period, class _Predicate>
154227825Stheraven        bool
155227825Stheraven        wait_for(_Lock& __lock,
156227825Stheraven                 const chrono::duration<_Rep, _Period>& __d,
157227825Stheraven                 _Predicate __pred);
158227825Stheraven};
159227825Stheraven
160227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
161227825Stheravencondition_variable_any::condition_variable_any()
162227825Stheraven    : __mut_(make_shared<mutex>()) {}
163227825Stheraven
164227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
165227825Stheravenvoid
166241903Sdimcondition_variable_any::notify_one() _NOEXCEPT
167227825Stheraven{
168242945Stheraven    {lock_guard<mutex> __lx(*__mut_);}
169227825Stheraven    __cv_.notify_one();
170227825Stheraven}
171227825Stheraven
172227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
173227825Stheravenvoid
174241903Sdimcondition_variable_any::notify_all() _NOEXCEPT
175227825Stheraven{
176242945Stheraven    {lock_guard<mutex> __lx(*__mut_);}
177227825Stheraven    __cv_.notify_all();
178227825Stheraven}
179227825Stheraven
180227825Stheravenstruct __lock_external
181227825Stheraven{
182227825Stheraven    template <class _Lock>
183227825Stheraven    void operator()(_Lock* __m) {__m->lock();}
184227825Stheraven};
185227825Stheraven
186227825Stheraventemplate <class _Lock>
187227825Stheravenvoid
188227825Stheravencondition_variable_any::wait(_Lock& __lock)
189227825Stheraven{
190227825Stheraven    shared_ptr<mutex> __mut = __mut_;
191227825Stheraven    unique_lock<mutex> __lk(*__mut);
192227825Stheraven    __lock.unlock();
193242945Stheraven    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
194242945Stheraven    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
195227825Stheraven    __cv_.wait(__lk);
196227825Stheraven}  // __mut_.unlock(), __lock.lock()
197227825Stheraven
198227825Stheraventemplate <class _Lock, class _Predicate>
199227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
200227825Stheravenvoid
201227825Stheravencondition_variable_any::wait(_Lock& __lock, _Predicate __pred)
202227825Stheraven{
203227825Stheraven    while (!__pred())
204227825Stheraven        wait(__lock);
205227825Stheraven}
206227825Stheraven
207227825Stheraventemplate <class _Lock, class _Clock, class _Duration>
208227825Stheravencv_status
209227825Stheravencondition_variable_any::wait_until(_Lock& __lock,
210227825Stheraven                                   const chrono::time_point<_Clock, _Duration>& __t)
211227825Stheraven{
212227825Stheraven    shared_ptr<mutex> __mut = __mut_;
213227825Stheraven    unique_lock<mutex> __lk(*__mut);
214227825Stheraven    __lock.unlock();
215242945Stheraven    unique_ptr<_Lock, __lock_external> __lxx(&__lock);
216242945Stheraven    lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
217227825Stheraven    return __cv_.wait_until(__lk, __t);
218227825Stheraven}  // __mut_.unlock(), __lock.lock()
219227825Stheraven
220227825Stheraventemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
221227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
222227825Stheravenbool
223227825Stheravencondition_variable_any::wait_until(_Lock& __lock,
224227825Stheraven                                   const chrono::time_point<_Clock, _Duration>& __t,
225227825Stheraven                                   _Predicate __pred)
226227825Stheraven{
227227825Stheraven    while (!__pred())
228227825Stheraven        if (wait_until(__lock, __t) == cv_status::timeout)
229227825Stheraven            return __pred();
230227825Stheraven    return true;
231227825Stheraven}
232227825Stheraven
233227825Stheraventemplate <class _Lock, class _Rep, class _Period>
234227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
235227825Stheravencv_status
236227825Stheravencondition_variable_any::wait_for(_Lock& __lock,
237227825Stheraven                                 const chrono::duration<_Rep, _Period>& __d)
238227825Stheraven{
239227825Stheraven    return wait_until(__lock, chrono::steady_clock::now() + __d);
240227825Stheraven}
241227825Stheraven
242227825Stheraventemplate <class _Lock, class _Rep, class _Period, class _Predicate>
243227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
244227825Stheravenbool
245227825Stheravencondition_variable_any::wait_for(_Lock& __lock,
246227825Stheraven                                 const chrono::duration<_Rep, _Period>& __d,
247227825Stheraven                                 _Predicate __pred)
248227825Stheraven{
249227825Stheraven    return wait_until(__lock, chrono::steady_clock::now() + __d,
250227825Stheraven                      _VSTD::move(__pred));
251227825Stheraven}
252227825Stheraven
253249998Sdim_LIBCPP_FUNC_VIS
254227825Stheravenvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
255227825Stheraven
256227825Stheraven_LIBCPP_END_NAMESPACE_STD
257227825Stheraven
258278724Sdim#endif // !_LIBCPP_HAS_NO_THREADS
259278724Sdim
260227825Stheraven#endif  // _LIBCPP_CONDITION_VARIABLE
261