]> gcc.gnu.org Git - gcc.git/blame - libstdc++-v3/include/std/condition_variable
testsuite: adjustments for amdgcn
[gcc.git] / libstdc++-v3 / include / std / condition_variable
CommitLineData
68a97d24
BK
1// <condition_variable> -*- C++ -*-
2
8d9254fc 3// Copyright (C) 2008-2020 Free Software Foundation, Inc.
68a97d24
BK
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
748086b7 8// Free Software Foundation; either version 3, or (at your option)
68a97d24
BK
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
748086b7
JJ
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
68a97d24 19
748086b7
JJ
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
68a97d24 24
f910786b 25/** @file include/condition_variable
68a97d24
BK
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_CONDITION_VARIABLE
30#define _GLIBCXX_CONDITION_VARIABLE 1
31
32#pragma GCC system_header
33
734f5023 34#if __cplusplus < 201103L
ab65a4c7 35# include <bits/c++0x_warning.h>
57317d2a 36#else
68a97d24 37
7b800287 38#include <chrono>
942c4b32 39
0c3e5dd1 40#include <bits/std_mutex.h>
1fba0606 41#include <bits/unique_lock.h>
3429db0f
JW
42#include <ext/concurrence.h>
43#include <bits/alloc_traits.h>
44#include <bits/allocator.h>
45#include <bits/unique_ptr.h>
46#include <bits/shared_ptr.h>
c8c03058 47#include <bits/cxxabi_forced.h>
68a97d24 48
942c4b32
TR
49#if __cplusplus > 201703L
50#define __cpp_lib_jthread 201907L
51#include <stop_token>
52#endif
53
8ba7f29e 54#if defined(_GLIBCXX_HAS_GTHREADS)
7b800287 55
12ffa228
BK
56namespace std _GLIBCXX_VISIBILITY(default)
57{
58_GLIBCXX_BEGIN_NAMESPACE_VERSION
53dc5044 59
5b9daa7e
BK
60 /**
61 * @defgroup condition_variables Condition Variables
62 * @ingroup concurrency
63 *
64 * Classes for condition_variable support.
65 * @{
66 */
67
cdf5f5a3
PC
68 /// cv_status
69 enum class cv_status { no_timeout, timeout };
33ac58d5 70
68a97d24
BK
71 /// condition_variable
72 class condition_variable
73 {
ad4d1d21
MC
74 using steady_clock = chrono::steady_clock;
75 using system_clock = chrono::system_clock;
76#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
77 using __clock_t = steady_clock;
78#else
79 using __clock_t = system_clock;
80#endif
f7459b6c 81 typedef __gthread_cond_t __native_type;
b81e920e
JW
82
83#ifdef __GTHREAD_COND_INIT
84 __native_type _M_cond = __GTHREAD_COND_INIT;
85#else
f7459b6c 86 __native_type _M_cond;
b81e920e 87#endif
88399079 88
68a97d24 89 public:
f7459b6c 90 typedef __native_type* native_handle_type;
68a97d24 91
b81e920e
JW
92 condition_variable() noexcept;
93 ~condition_variable() noexcept;
68a97d24 94
7b800287
CF
95 condition_variable(const condition_variable&) = delete;
96 condition_variable& operator=(const condition_variable&) = delete;
97
d5cf2021 98 void
b81e920e 99 notify_one() noexcept;
68a97d24 100
d5cf2021 101 void
b81e920e 102 notify_all() noexcept;
68a97d24 103
d5cf2021 104 void
80400b04 105 wait(unique_lock<mutex>& __lock) noexcept;
68a97d24
BK
106
107 template<typename _Predicate>
d5cf2021 108 void
68a97d24
BK
109 wait(unique_lock<mutex>& __lock, _Predicate __p)
110 {
111 while (!__p())
112 wait(__lock);
113 }
d5cf2021 114
ad4d1d21
MC
115#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
116 template<typename _Duration>
117 cv_status
118 wait_until(unique_lock<mutex>& __lock,
119 const chrono::time_point<steady_clock, _Duration>& __atime)
120 { return __wait_until_impl(__lock, __atime); }
121#endif
122
88399079 123 template<typename _Duration>
cdf5f5a3 124 cv_status
88399079 125 wait_until(unique_lock<mutex>& __lock,
ad4d1d21 126 const chrono::time_point<system_clock, _Duration>& __atime)
88399079
CF
127 { return __wait_until_impl(__lock, __atime); }
128
129 template<typename _Clock, typename _Duration>
cdf5f5a3 130 cv_status
88399079 131 wait_until(unique_lock<mutex>& __lock,
7b800287
CF
132 const chrono::time_point<_Clock, _Duration>& __atime)
133 {
023cee96
PC
134 const typename _Clock::time_point __c_entry = _Clock::now();
135 const __clock_t::time_point __s_entry = __clock_t::now();
c25639b1
JW
136 const auto __delta = __atime - __c_entry;
137 const auto __s_atime = __s_entry + __delta;
7b800287 138
2f593432
MC
139 if (__wait_until_impl(__lock, __s_atime) == cv_status::no_timeout)
140 return cv_status::no_timeout;
141 // We got a timeout when measured against __clock_t but
142 // we need to check against the caller-supplied clock
143 // to tell whether we should return a timeout.
144 if (_Clock::now() < __atime)
145 return cv_status::no_timeout;
146 return cv_status::timeout;
7b800287 147 }
d3098c94
CF
148
149 template<typename _Clock, typename _Duration, typename _Predicate>
150 bool
151 wait_until(unique_lock<mutex>& __lock,
152 const chrono::time_point<_Clock, _Duration>& __atime,
88399079
CF
153 _Predicate __p)
154 {
f7459b6c 155 while (!__p())
cdf5f5a3 156 if (wait_until(__lock, __atime) == cv_status::timeout)
88399079 157 return __p();
88399079
CF
158 return true;
159 }
d3098c94
CF
160
161 template<typename _Rep, typename _Period>
cdf5f5a3 162 cv_status
d3098c94 163 wait_for(unique_lock<mutex>& __lock,
7b800287 164 const chrono::duration<_Rep, _Period>& __rtime)
83fd5e73 165 {
ad4d1d21 166 using __dur = typename steady_clock::duration;
83fd5e73
JW
167 auto __reltime = chrono::duration_cast<__dur>(__rtime);
168 if (__reltime < __rtime)
169 ++__reltime;
ad4d1d21 170 return wait_until(__lock, steady_clock::now() + __reltime);
83fd5e73 171 }
d3098c94
CF
172
173 template<typename _Rep, typename _Period, typename _Predicate>
174 bool
175 wait_for(unique_lock<mutex>& __lock,
176 const chrono::duration<_Rep, _Period>& __rtime,
88399079 177 _Predicate __p)
83fd5e73 178 {
ad4d1d21 179 using __dur = typename steady_clock::duration;
83fd5e73
JW
180 auto __reltime = chrono::duration_cast<__dur>(__rtime);
181 if (__reltime < __rtime)
182 ++__reltime;
ad4d1d21 183 return wait_until(__lock, steady_clock::now() + __reltime,
29b26763 184 std::move(__p));
83fd5e73 185 }
68a97d24 186
d5cf2021
BK
187 native_handle_type
188 native_handle()
7b800287 189 { return &_M_cond; }
68a97d24
BK
190
191 private:
ad4d1d21
MC
192#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
193 template<typename _Dur>
194 cv_status
195 __wait_until_impl(unique_lock<mutex>& __lock,
196 const chrono::time_point<steady_clock, _Dur>& __atime)
197 {
198 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
199 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
200
201 __gthread_time_t __ts =
202 {
203 static_cast<std::time_t>(__s.time_since_epoch().count()),
204 static_cast<long>(__ns.count())
205 };
206
207 pthread_cond_clockwait(&_M_cond, __lock.mutex()->native_handle(),
208 CLOCK_MONOTONIC,
209 &__ts);
210
211 return (steady_clock::now() < __atime
212 ? cv_status::no_timeout : cv_status::timeout);
213 }
214#endif
215
c25639b1 216 template<typename _Dur>
cdf5f5a3 217 cv_status
88399079 218 __wait_until_impl(unique_lock<mutex>& __lock,
ad4d1d21 219 const chrono::time_point<system_clock, _Dur>& __atime)
88399079 220 {
c25639b1
JW
221 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
222 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
d5cf2021
BK
223
224 __gthread_time_t __ts =
225 {
226 static_cast<std::time_t>(__s.time_since_epoch().count()),
227 static_cast<long>(__ns.count())
228 };
229
230 __gthread_cond_timedwait(&_M_cond, __lock.mutex()->native_handle(),
231 &__ts);
232
ad4d1d21 233 return (system_clock::now() < __atime
cdf5f5a3 234 ? cv_status::no_timeout : cv_status::timeout);
88399079 235 }
68a97d24
BK
236 };
237
9db7c931
JW
238 void
239 notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);
240
241 struct __at_thread_exit_elt
242 {
243 __at_thread_exit_elt* _M_next;
244 void (*_M_cb)(void*);
245 };
246
3429db0f
JW
247 inline namespace _V2 {
248
68a97d24 249 /// condition_variable_any
b7200e3f 250 // Like above, but mutex is not required to have try_lock.
68a97d24
BK
251 class condition_variable_any
252 {
ad4d1d21
MC
253#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
254 using __clock_t = chrono::steady_clock;
255#else
256 using __clock_t = chrono::system_clock;
257#endif
b7200e3f 258 condition_variable _M_cond;
3429db0f 259 shared_ptr<mutex> _M_mutex;
f7459b6c 260
7f426c93
JW
261 // scoped unlock - unlocks in ctor, re-locks in dtor
262 template<typename _Lock>
263 struct _Unlock
264 {
265 explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); }
266
267 ~_Unlock() noexcept(false)
268 {
269 if (uncaught_exception())
315eb4bb
JW
270 {
271 __try
272 { _M_lock.lock(); }
273 __catch(const __cxxabiv1::__forced_unwind&)
274 { __throw_exception_again; }
275 __catch(...)
276 { }
277 }
7f426c93
JW
278 else
279 _M_lock.lock();
280 }
281
282 _Unlock(const _Unlock&) = delete;
283 _Unlock& operator=(const _Unlock&) = delete;
284
285 _Lock& _M_lock;
286 };
287
68a97d24 288 public:
3429db0f
JW
289 condition_variable_any() : _M_mutex(std::make_shared<mutex>()) { }
290 ~condition_variable_any() = default;
d5cf2021 291
7b800287
CF
292 condition_variable_any(const condition_variable_any&) = delete;
293 condition_variable_any& operator=(const condition_variable_any&) = delete;
68a97d24 294
d5cf2021 295 void
b81e920e 296 notify_one() noexcept
b7200e3f 297 {
3429db0f 298 lock_guard<mutex> __lock(*_M_mutex);
b7200e3f
JW
299 _M_cond.notify_one();
300 }
68a97d24 301
d5cf2021 302 void
b81e920e 303 notify_all() noexcept
b7200e3f 304 {
3429db0f 305 lock_guard<mutex> __lock(*_M_mutex);
b7200e3f
JW
306 _M_cond.notify_all();
307 }
68a97d24
BK
308
309 template<typename _Lock>
d5cf2021 310 void
b7200e3f
JW
311 wait(_Lock& __lock)
312 {
3429db0f
JW
313 shared_ptr<mutex> __mutex = _M_mutex;
314 unique_lock<mutex> __my_lock(*__mutex);
7f426c93 315 _Unlock<_Lock> __unlock(__lock);
3429db0f
JW
316 // *__mutex must be unlocked before re-locking __lock so move
317 // ownership of *__mutex lock to an object with shorter lifetime.
5d020aa2
JW
318 unique_lock<mutex> __my_lock2(std::move(__my_lock));
319 _M_cond.wait(__my_lock2);
b7200e3f 320 }
33ac58d5 321
68a97d24
BK
322
323 template<typename _Lock, typename _Predicate>
d5cf2021 324 void
cdf5f5a3
PC
325 wait(_Lock& __lock, _Predicate __p)
326 {
327 while (!__p())
328 wait(__lock);
329 }
68a97d24 330
d3098c94 331 template<typename _Lock, typename _Clock, typename _Duration>
cdf5f5a3 332 cv_status
d3098c94 333 wait_until(_Lock& __lock,
b7200e3f
JW
334 const chrono::time_point<_Clock, _Duration>& __atime)
335 {
3429db0f
JW
336 shared_ptr<mutex> __mutex = _M_mutex;
337 unique_lock<mutex> __my_lock(*__mutex);
7f426c93 338 _Unlock<_Lock> __unlock(__lock);
3429db0f
JW
339 // *__mutex must be unlocked before re-locking __lock so move
340 // ownership of *__mutex lock to an object with shorter lifetime.
7f426c93
JW
341 unique_lock<mutex> __my_lock2(std::move(__my_lock));
342 return _M_cond.wait_until(__my_lock2, __atime);
b7200e3f 343 }
68a97d24 344
d5cf2021 345 template<typename _Lock, typename _Clock,
d3098c94 346 typename _Duration, typename _Predicate>
d5cf2021 347 bool
d3098c94
CF
348 wait_until(_Lock& __lock,
349 const chrono::time_point<_Clock, _Duration>& __atime,
cdf5f5a3
PC
350 _Predicate __p)
351 {
352 while (!__p())
353 if (wait_until(__lock, __atime) == cv_status::timeout)
354 return __p();
355 return true;
356 }
d5cf2021 357
d3098c94 358 template<typename _Lock, typename _Rep, typename _Period>
cdf5f5a3 359 cv_status
b7200e3f
JW
360 wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime)
361 { return wait_until(__lock, __clock_t::now() + __rtime); }
d3098c94
CF
362
363 template<typename _Lock, typename _Rep,
364 typename _Period, typename _Predicate>
365 bool
d5cf2021 366 wait_for(_Lock& __lock,
b7200e3f
JW
367 const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p)
368 { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); }
942c4b32
TR
369
370#ifdef __cpp_lib_jthread
371 template <class _Lock, class _Predicate>
9e3c1eb7
TR
372 bool wait(_Lock& __lock,
373 stop_token __stoken,
374 _Predicate __p)
942c4b32
TR
375 {
376 if (__stoken.stop_requested())
377 {
378 return __p();
379 }
380
381 std::stop_callback __cb(__stoken, [this] { notify_all(); });
382 shared_ptr<mutex> __mutex = _M_mutex;
383 while (!__p())
384 {
385 unique_lock<mutex> __my_lock(*__mutex);
386 if (__stoken.stop_requested())
387 {
388 return false;
389 }
390 // *__mutex must be unlocked before re-locking __lock so move
391 // ownership of *__mutex lock to an object with shorter lifetime.
392 _Unlock<_Lock> __unlock(__lock);
393 unique_lock<mutex> __my_lock2(std::move(__my_lock));
394 _M_cond.wait(__my_lock2);
395 }
396 return true;
397 }
398
399 template <class _Lock, class _Clock, class _Duration, class _Predicate>
9e3c1eb7
TR
400 bool wait_until(_Lock& __lock,
401 stop_token __stoken,
402 const chrono::time_point<_Clock, _Duration>& __abs_time,
403 _Predicate __p)
942c4b32
TR
404 {
405 if (__stoken.stop_requested())
406 {
407 return __p();
408 }
409
410 std::stop_callback __cb(__stoken, [this] { notify_all(); });
411 shared_ptr<mutex> __mutex = _M_mutex;
412 while (!__p())
413 {
414 bool __stop;
415 {
416 unique_lock<mutex> __my_lock(*__mutex);
417 if (__stoken.stop_requested())
418 {
419 return false;
420 }
421 _Unlock<_Lock> __u(__lock);
422 unique_lock<mutex> __my_lock2(std::move(__my_lock));
423 const auto __status = _M_cond.wait_until(__my_lock2, __abs_time);
424 __stop = (__status == std::cv_status::timeout) || __stoken.stop_requested();
425 }
426 if (__stop)
427 {
428 return __p();
429 }
430 }
431 return true;
432 }
433
434 template <class _Lock, class _Rep, class _Period, class _Predicate>
9e3c1eb7
TR
435 bool wait_for(_Lock& __lock,
436 stop_token __stoken,
437 const chrono::duration<_Rep, _Period>& __rel_time,
438 _Predicate __p)
942c4b32
TR
439 {
440 auto __abst = std::chrono::steady_clock::now() + __rel_time;
9e3c1eb7
TR
441 return wait_until(__lock,
442 std::move(__stoken),
443 __abst,
444 std::move(__p));
942c4b32
TR
445 }
446#endif
68a97d24 447 };
5b9daa7e 448
3429db0f
JW
449 } // end inline namespace
450
5b9daa7e 451 // @} group condition_variables
12ffa228
BK
452_GLIBCXX_END_NAMESPACE_VERSION
453} // namespace
68a97d24 454
8ba7f29e 455#endif // _GLIBCXX_HAS_GTHREADS
734f5023 456#endif // C++11
57317d2a 457#endif // _GLIBCXX_CONDITION_VARIABLE
This page took 1.286769 seconds and 5 git commands to generate.