1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: no-threads
10 // UNSUPPORTED: c++03, c++11, c++14, c++17
12 // XFAIL: availability-synchronization_library-missing
14 // <condition_variable>
16 // class condition_variable_any;
18 // template<class Lock, class Clock, class Duration, class Predicate>
19 // bool wait_until(Lock& lock, stop_token stoken,
20 // const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
26 #include <condition_variable>
29 #include <shared_mutex>
34 #include "make_test_thread.h"
35 #include "test_macros.h"
37 template <class Mutex
, class Lock
>
39 using namespace std::chrono_literals
;
40 const auto oneHourAgo
= std::chrono::steady_clock::now() - 1h
;
41 const auto oneHourLater
= std::chrono::steady_clock::now() + 1h
;
43 // stop_requested before hand
46 std::condition_variable_any cv
;
50 ElapsedTimeCheck
check(1min
);
52 // [Note 4: The returned value indicates whether the predicate evaluated to true
53 // regardless of whether the timeout was triggered or a stop request was made.]
54 std::same_as
<bool> auto r1
= cv
.wait_until(lock
, ss
.get_token(), oneHourAgo
, []() { return false; });
57 std::same_as
<bool> auto r2
= cv
.wait_until(lock
, ss
.get_token(), oneHourLater
, []() { return false; });
60 std::same_as
<bool> auto r3
= cv
.wait_until(lock
, ss
.get_token(), oneHourAgo
, []() { return true; });
63 std::same_as
<bool> auto r4
= cv
.wait_until(lock
, ss
.get_token(), oneHourLater
, []() { return true; });
66 // Postconditions: lock is locked by the calling thread.
67 assert(lock
.owns_lock());
70 // no stop request, pred was true
73 std::condition_variable_any cv
;
76 ElapsedTimeCheck
check(1min
);
78 std::same_as
<bool> auto r1
= cv
.wait_until(lock
, ss
.get_token(), oneHourAgo
, []() { return true; });
81 std::same_as
<bool> auto r2
= cv
.wait_until(lock
, ss
.get_token(), oneHourLater
, []() { return true; });
85 // no stop request, pred was false, abs_time was in the past
88 std::condition_variable_any cv
;
91 ElapsedTimeCheck
check(1min
);
93 std::same_as
<bool> auto r1
= cv
.wait_until(lock
, ss
.get_token(), oneHourAgo
, []() { return false; });
97 // no stop request, pred was false until timeout
100 std::condition_variable_any cv
;
104 auto oldTime
= std::chrono::steady_clock::now();
106 std::same_as
<bool> auto r1
=
107 cv
.wait_until(lock
, ss
.get_token(), oldTime
+ std::chrono::milliseconds(2), [&]() { return false; });
109 assert((std::chrono::steady_clock::now() - oldTime
) >= std::chrono::milliseconds(2));
113 // no stop request, pred was false, changed to true before timeout
116 std::condition_variable_any cv
;
121 auto thread
= support::make_test_thread([&]() {
122 std::this_thread::sleep_for(std::chrono::milliseconds(2));
123 std::unique_lock
<Mutex
> lock2
{mutex
};
128 ElapsedTimeCheck
check(10min
);
130 std::same_as
<bool> auto r1
= cv
.wait_until(lock
, ss
.get_token(), oneHourLater
, [&]() { return flag
; });
137 // stop request comes while waiting
140 std::condition_variable_any cv
;
144 std::atomic_bool start
= false;
145 std::atomic_bool done
= false;
146 auto thread
= support::make_test_thread([&]() {
152 std::this_thread::sleep_for(std::chrono::milliseconds(2));
156 ElapsedTimeCheck
check(10min
);
158 std::same_as
<bool> auto r
= cv
.wait_until(lock
, ss
.get_token(), oneHourLater
, [&]() {
167 assert(lock
.owns_lock());
170 // #76807 Hangs in std::condition_variable_any when used with std::stop_token
175 thread_
= support::make_test_jthread([this](std::stop_token st
) {
176 while (!st
.stop_requested()) {
177 std::unique_lock lock
{m_
};
178 cv_
.wait_until(lock
, st
, std::chrono::steady_clock::now() + std::chrono::hours(1), [] { return false; });
185 std::condition_variable_any cv_
;
186 std::jthread thread_
;
189 ElapsedTimeCheck
check(10min
);
191 [[maybe_unused
]] MyThread my_thread
;
194 // request_stop potentially in-between check and wait
197 std::condition_variable_any cv
;
201 std::atomic_bool pred_started
= false;
202 std::atomic_bool request_stop_called
= false;
203 auto thread
= support::make_test_thread([&]() {
204 pred_started
.wait(false);
206 request_stop_called
.store(true);
207 request_stop_called
.notify_all();
210 ElapsedTimeCheck
check(10min
);
212 std::same_as
<bool> auto r
= cv
.wait_until(lock
, ss
.get_token(), oneHourLater
, [&]() {
213 pred_started
.store(true);
214 pred_started
.notify_all();
215 request_stop_called
.wait(false);
221 assert(lock
.owns_lock());
224 #if !defined(TEST_HAS_NO_EXCEPTIONS)
225 // Throws: Any exception thrown by pred.
228 std::condition_variable_any cv
;
233 cv
.wait_until(lock
, ss
.get_token(), oneHourLater
, []() -> bool { throw 5; });
239 #endif //!defined(TEST_HAS_NO_EXCEPTIONS)
242 int main(int, char**) {
243 test
<std::mutex
, std::unique_lock
<std::mutex
>>();
244 test
<std::shared_mutex
, std::shared_lock
<std::shared_mutex
>>();