source: mainline/uspace/lib/cpp/include/__bits/thread/condition_variable.hpp@ 8e24583

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8e24583 was bc56f30, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Make some libc and libposix headers usable in C++

These headers either get included from standard C++ headers,
or are standard themselves, which means any unnamespaced nonstandard
identifiers are a problem. This commit attempts to fix those
issues, and removes hacks previously used in libcpp to work around it.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_BITS_THREAD_CONDITION_VARIABLE
30#define LIBCPP_BITS_THREAD_CONDITION_VARIABLE
31
32#include <__bits/thread/threading.hpp>
33#include <mutex>
34
35namespace std
36{
37 enum class cv_status
38 {
39 no_timeout,
40 timeout
41 };
42
43 namespace aux
44 {
45 template<class Clock, class Duration>
46 aux::time_unit_t time_until(const chrono::time_point<Clock, Duration>& abs_time)
47 {
48 return aux::threading::time::convert(abs_time - Clock::now());
49 }
50 }
51
52 /**
53 * 30.5.1, class condition_variable:
54 */
55
56 class condition_variable
57 {
58 public:
59 condition_variable();
60 ~condition_variable();
61
62 condition_variable(const condition_variable&) = delete;
63 condition_variable& operator=(const condition_variable&) = delete;
64
65 void notify_one() noexcept;
66 void notify_all() noexcept;
67
68 void wait(unique_lock<mutex>&);
69
70 template<class Predicate>
71 void wait(unique_lock<mutex>& lock, Predicate pred)
72 {
73 /**
74 * Note: lock is supposed to be locked here,
75 * so no need to lock it.
76 */
77 while (!pred())
78 wait(lock);
79 }
80
81 template<class Clock, class Duration>
82 cv_status wait_until(unique_lock<mutex>& lock,
83 const chrono::time_point<Clock, Duration>& abs_time)
84 {
85 auto ret = aux::threading::condvar::wait_for(
86 cv_, *lock.mutex()->native_handle(), aux::time_until(abs_time)
87 );
88
89 if (ret == EOK)
90 return cv_status::no_timeout;
91 else
92 return cv_status::timeout;
93 }
94
95 template<class Clock, class Duration, class Predicate>
96 bool wait_until(unique_lock<mutex>& lock,
97 const chrono::time_point<Clock, Duration>& abs_time,
98 Predicate pred)
99 {
100 while (!pred())
101 {
102 if (wait_until(lock, abs_time) == cv_status::timeout)
103 return pred();
104 }
105
106 return true;
107 }
108
109 template<class Rep, class Period>
110 cv_status wait_for(unique_lock<mutex>& lock,
111 const chrono::duration<Rep, Period>& rel_time)
112 {
113 return wait_until(
114 lock, chrono::steady_clock::now() + rel_time
115 );
116 }
117
118 template<class Rep, class Period, class Predicate>
119 bool wait_for(unique_lock<mutex>& lock,
120 const chrono::duration<Rep, Period>& rel_time,
121 Predicate pred)
122 {
123 return wait_until(
124 lock, chrono::steady_clock::now() + rel_time,
125 move(pred)
126 );
127 }
128
129 using native_handle_type = aux::condvar_t*;
130 native_handle_type native_handle();
131
132 private:
133 aux::condvar_t cv_;
134 };
135
136 /**
137 * 30.5.2, class condition_variable_any:
138 */
139
140 class condition_variable_any
141 {
142 public:
143 condition_variable_any();
144 ~condition_variable_any();
145
146 condition_variable_any(const condition_variable_any&) = delete;
147 condition_variable_any& operator=(const condition_variable_any&) = delete;
148
149 void notify_one() noexcept;
150 void notify_all() noexcept;
151
152 template<class Lock>
153 void wait(Lock& lock)
154 {
155 aux::threading::condvar::wait(cv_, *lock.native_handle());
156 }
157
158 template<class Lock, class Predicate>
159 void wait(Lock& lock, Predicate pred)
160 {
161 while (!pred())
162 wait(lock);
163 }
164
165 template<class Lock, class Clock, class Duration>
166 cv_status wait_until(Lock& lock,
167 const chrono::time_point<Clock, Duration>& abs_time)
168 {
169 auto ret = aux::threading::condvar::wait_for(
170 cv_, *lock.mutex()->native_handle(), aux::time_until(abs_time)
171 );
172
173 if (ret == EOK)
174 return cv_status::no_timeout;
175 else
176 return cv_status::timeout;
177 }
178
179 template<class Lock, class Clock, class Duration, class Predicate>
180 bool wait_until(Lock& lock,
181 const chrono::time_point<Clock, Duration>& abs_time,
182 Predicate pred)
183 {
184 while (!pred())
185 {
186 if (wait_until(lock, abs_time) == cv_status::timeout)
187 return pred();
188 }
189
190 return true;
191 }
192
193 template<class Lock, class Rep, class Period>
194 cv_status wait_for(Lock& lock,
195 const chrono::duration<Rep, Period>& rel_time)
196 {
197 return wait_until(
198 lock, chrono::steady_clock::now() + rel_time
199 );
200 }
201
202 template<class Lock, class Rep, class Period, class Predicate>
203 bool wait_for(Lock& lock,
204 const chrono::duration<Rep, Period>& rel_time,
205 Predicate pred)
206 {
207 return wait_until(
208 lock, chrono::steady_clock::now() + rel_time,
209 move(pred)
210 );
211 }
212
213 using native_handle_type = aux::condvar_t*;
214 native_handle_type native_handle();
215
216 private:
217 aux::condvar_t cv_;
218 };
219
220 void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>&);
221}
222
223#endif
Note: See TracBrowser for help on using the repository browser.