[FMV][AArch64] Changes in fmv-features metadata. (#122192)
[llvm-project.git] / libcxx / test / std / thread / thread.condition / thread.condition.condvarany / wait_terminates.sh.cpp
blobeab7a4fb2e51e7ee549eb3bbb1df8aea039c3fed
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: no-exceptions
10 // UNSUPPORTED: no-threads
12 // <condition_variable>
14 // class condition_variable_any;
16 // RUN: %{build}
17 // RUN: %{run} 1
18 // RUN: %{run} 2
19 // RUN: %{run} 3
20 // RUN: %{run} 4
21 // RUN: %{run} 5
22 // RUN: %{run} 6
23 // RUN: %{run} 7
24 // RUN: %{run} 8
25 // RUN: %{run} 9
27 // -----------------------------------------------------------------------------
28 // Overview
29 // Check that std::terminate is called if wait(...) fails to meet its post
30 // conditions. This can happen when reacquiring the mutex throws
31 // an exception.
33 // The following methods are tested within this file
34 // 1. void wait(Lock& lock);
35 // 2. void wait(Lock& lock, Pred);
36 // 3. void wait_for(Lock& lock, Duration);
37 // 4. void wait_for(Lock& lock, Duration, Pred);
38 // 5. void wait_until(Lock& lock, TimePoint);
39 // 6. void wait_until(Lock& lock, TimePoint, Pred);
40 // 7. bool wait(Lock& lock, stop_token stoken, Predicate pred);
41 // 8. bool wait_for(Lock& lock, stop_token stoken, Duration, Predicate pred);
42 // 9. bool wait_until(Lock& lock, stop_token stoken, TimePoint, Predicate pred);
44 // Plan
45 // 1 Create a mutex type, 'ThrowingMutex', that throws when the lock is acquired
46 // for the *second* time.
48 // 2 Replace the terminate handler with one that exits with a '0' exit code.
50 // 3 Create a 'condition_variable_any' object 'cv' and a 'ThrowingMutex'
51 // object 'm' and lock 'm'.
53 // 4 Start a thread 'T2' that will notify 'cv' once 'm' has been unlocked.
55 // 5 From the main thread call the specified wait method on 'cv' with 'm'.
56 // When 'T2' notifies 'cv' and the wait method attempts to re-lock
57 // 'm' an exception will be thrown from 'm.lock()'.
59 // 6 Check that control flow does not return from the wait method and that
60 // terminate is called (If the program exits with a 0 exit code we know
61 // that terminate has been called)
64 #include <atomic>
65 #include <cassert>
66 #include <chrono>
67 #include <condition_variable>
68 #include <cstdlib>
69 #include <exception>
70 #include <string>
71 #include <stop_token>
72 #include <thread>
74 #include "make_test_thread.h"
75 #include "test_macros.h"
77 void my_terminate() {
78 std::_Exit(0); // Use _Exit to prevent cleanup from taking place.
81 // The predicate used in the cv.wait calls.
82 bool pred = false;
83 bool pred_function() {
84 return pred == true;
87 class ThrowingMutex
89 std::atomic_bool locked;
90 unsigned state = 0;
91 ThrowingMutex(const ThrowingMutex&) = delete;
92 ThrowingMutex& operator=(const ThrowingMutex&) = delete;
93 public:
94 ThrowingMutex() {
95 locked = false;
97 ~ThrowingMutex() = default;
99 void lock() {
100 locked = true;
101 if (++state == 2) {
102 assert(pred); // Check that we actually waited until we were signaled.
103 throw 1; // this throw should end up calling terminate()
107 void unlock() { locked = false; }
108 bool isLocked() const { return locked == true; }
111 ThrowingMutex mut;
112 std::condition_variable_any cv;
114 void signal_me() {
115 while (mut.isLocked()) {} // wait until T1 releases mut inside the cv.wait call.
116 pred = true;
117 cv.notify_one();
120 typedef std::chrono::system_clock Clock;
121 typedef std::chrono::milliseconds MS;
123 int main(int argc, char **argv) {
124 assert(argc == 2);
125 int id = std::stoi(argv[1]);
126 assert(id >= 1 && id <= 9);
127 std::set_terminate(my_terminate); // set terminate after std::stoi because it can throw.
128 MS wait(250);
129 try {
130 mut.lock();
131 assert(pred == false);
132 support::make_test_thread(signal_me).detach();
133 switch (id) {
134 case 1: cv.wait(mut); break;
135 case 2: cv.wait(mut, pred_function); break;
136 case 3: cv.wait_for(mut, wait); break;
137 case 4: cv.wait_for(mut, wait, pred_function); break;
138 case 5: cv.wait_until(mut, Clock::now() + wait); break;
139 case 6: cv.wait_until(mut, Clock::now() + wait, pred_function); break;
140 #if TEST_STD_VER >= 20 && !(defined(_LIBCPP_VERSION) && !_LIBCPP_AVAILABILITY_HAS_SYNC)
141 case 7: cv.wait(mut, std::stop_source{}.get_token(), pred_function); break;
142 case 8: cv.wait_for(mut, std::stop_source{}.get_token(), wait, pred_function); break;
143 case 9: cv.wait_until(mut, std::stop_source{}.get_token(), Clock::now() + wait, pred_function); break;
144 #else
145 case 7:
146 case 8:
147 case 9:
148 return 0;
149 #endif
150 default: assert(false);
152 } catch (...) {}
153 assert(false);
155 return 0;