Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / thread / thread.condition / thread.condition.condvarany / wait_until_token_pred.pass.cpp
blob6cdcbe36d98598bb365d25f68ce382974a429d2b
1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: no-threads
10 // UNSUPPORTED: c++03, c++11, c++14, c++17
11 // UNSUPPORTED: libcpp-has-no-experimental-stop_token
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);
22 #include <cassert>
23 #include <chrono>
24 #include <concepts>
25 #include <condition_variable>
26 #include <functional>
27 #include <mutex>
28 #include <shared_mutex>
29 #include <stop_token>
30 #include <thread>
32 #include "make_test_thread.h"
33 #include "test_macros.h"
35 template <class Mutex, class Lock>
36 void test() {
37 const auto past = std::chrono::steady_clock::now() - std::chrono::hours(1);
38 const auto future = std::chrono::steady_clock::now() + std::chrono::hours(1);
40 // stop_requested before hand
42 std::stop_source ss;
43 std::condition_variable_any cv;
44 Mutex mutex;
45 Lock lock{mutex};
46 ss.request_stop();
48 // [Note 4: The returned value indicates whether the predicate evaluated to true
49 // regardless of whether the timeout was triggered or a stop request was made.]
50 std::same_as<bool> auto r1 = cv.wait_until(lock, ss.get_token(), past, []() { return false; });
51 assert(!r1);
53 std::same_as<bool> auto r2 = cv.wait_until(lock, ss.get_token(), future, []() { return false; });
54 assert(!r2);
56 std::same_as<bool> auto r3 = cv.wait_until(lock, ss.get_token(), past, []() { return true; });
57 assert(r3);
59 std::same_as<bool> auto r4 = cv.wait_until(lock, ss.get_token(), future, []() { return true; });
60 assert(r4);
62 // Postconditions: lock is locked by the calling thread.
63 assert(lock.owns_lock());
66 // no stop request, pred was true
68 std::stop_source ss;
69 std::condition_variable_any cv;
70 Mutex mutex;
71 Lock lock{mutex};
73 std::same_as<bool> auto r1 = cv.wait_until(lock, ss.get_token(), past, []() { return true; });
74 assert(r1);
76 std::same_as<bool> auto r2 = cv.wait_until(lock, ss.get_token(), future, []() { return true; });
77 assert(r2);
80 // no stop request, pred was false, abs_time was in the past
82 std::stop_source ss;
83 std::condition_variable_any cv;
84 Mutex mutex;
85 Lock lock{mutex};
87 std::same_as<bool> auto r1 = cv.wait_until(lock, ss.get_token(), past, []() { return false; });
88 assert(!r1);
91 // no stop request, pred was false until timeout
93 std::stop_source ss;
94 std::condition_variable_any cv;
95 Mutex mutex;
96 Lock lock{mutex};
98 auto oldTime = std::chrono::steady_clock::now();
100 std::same_as<bool> auto r1 =
101 cv.wait_until(lock, ss.get_token(), oldTime + std::chrono::milliseconds(2), [&]() { return false; });
103 assert((std::chrono::steady_clock::now() - oldTime) >= std::chrono::milliseconds(2));
104 assert(!r1);
107 // no stop request, pred was false, changed to true before timeout
109 std::stop_source ss;
110 std::condition_variable_any cv;
111 Mutex mutex;
112 Lock lock{mutex};
114 bool flag = false;
115 auto thread = support::make_test_thread([&]() {
116 std::this_thread::sleep_for(std::chrono::milliseconds(2));
117 Lock lock2{mutex};
118 flag = true;
119 cv.notify_all();
122 std::same_as<bool> auto r1 = cv.wait_until(lock, ss.get_token(), future, [&]() { return flag; });
123 assert(flag);
124 assert(r1);
126 thread.join();
129 // stop request comes while waiting
131 std::stop_source ss;
132 std::condition_variable_any cv;
133 Mutex mutex;
134 Lock lock{mutex};
136 std::atomic_bool start = false;
137 std::atomic_bool done = false;
138 auto thread = support::make_test_thread([&]() {
139 start.wait(false);
140 ss.request_stop();
142 while (!done) {
143 cv.notify_all();
144 std::this_thread::sleep_for(std::chrono::milliseconds(2));
148 std::same_as<bool> auto r = cv.wait_until(lock, ss.get_token(), future, [&]() {
149 start.store(true);
150 start.notify_all();
151 return false;
153 assert(!r);
154 done = true;
155 thread.join();
157 assert(lock.owns_lock());
160 #if !defined(TEST_HAS_NO_EXCEPTIONS)
161 // Throws: Any exception thrown by pred.
163 std::stop_source ss;
164 std::condition_variable_any cv;
165 Mutex mutex;
166 Lock lock{mutex};
168 try {
169 cv.wait_until(lock, ss.get_token(), future, []() -> bool { throw 5; });
170 assert(false);
171 } catch (int i) {
172 assert(i == 5);
175 #endif //!defined(TEST_HAS_NO_EXCEPTIONS)
178 int main(int, char**) {
179 test<std::mutex, std::unique_lock<std::mutex>>();
180 test<std::shared_mutex, std::shared_lock<std::shared_mutex>>();
182 return 0;