]>
Commit | Line | Data |
---|---|---|
7adcbafe | 1 | // Copyright (C) 2019-2022 Free Software Foundation, Inc. |
942c4b32 TR |
2 | // |
3 | // This file is part of the GNU ISO C++ Library. This library is free | |
4 | // software; you can redistribute it and/or modify it under the | |
5 | // terms of the GNU General Public License as published by the | |
6 | // Free Software Foundation; either version 3, or (at your option) | |
7 | // any later version. | |
8 | ||
9 | // This library is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | ||
14 | // You should have received a copy of the GNU General Public License along | |
15 | // with this library; see the file COPYING3. If not see | |
16 | // <http://www.gnu.org/licenses/>. | |
17 | ||
ebc46494 JW |
18 | // { dg-options "-std=gnu++2a -pthread" } |
19 | // { dg-do run { target c++2a } } | |
60a156ae JW |
20 | // { dg-add-options libatomic } |
21 | // { dg-additional-options "-pthread" { target pthread } } | |
ebc46494 | 22 | // { dg-require-gthreads "" } |
942c4b32 TR |
23 | |
24 | #include <thread> | |
25 | #include <chrono> | |
942c4b32 | 26 | #include <atomic> |
ebc46494 | 27 | #include <testsuite_hooks.h> |
942c4b32 | 28 | |
ebc46494 | 29 | using namespace std::literals; |
942c4b32 TR |
30 | |
31 | //------------------------------------------------------ | |
32 | ||
33 | void test_no_stop_token() | |
34 | { | |
35 | // test the basic jthread API (not taking stop_token arg) | |
36 | ||
ebc46494 | 37 | VERIFY(std::jthread::hardware_concurrency() == std::thread::hardware_concurrency()); |
942c4b32 | 38 | std::stop_token stoken; |
ebc46494 | 39 | VERIFY(!stoken.stop_possible()); |
942c4b32 TR |
40 | { |
41 | std::jthread::id t1ID{std::this_thread::get_id()}; | |
42 | std::atomic<bool> t1AllSet{false}; | |
43 | std::jthread t1([&t1ID, &t1AllSet] { | |
44 | t1ID = std::this_thread::get_id(); | |
45 | t1AllSet.store(true); | |
46 | for (int c='9'; c>='0'; --c) { | |
47 | std::this_thread::sleep_for(222ms); | |
48 | } | |
49 | }); | |
50 | for (int i=0; !t1AllSet.load(); ++i) { | |
51 | std::this_thread::sleep_for(10ms); | |
52 | } | |
ebc46494 JW |
53 | VERIFY(t1.joinable()); |
54 | VERIFY(t1ID == t1.get_id()); | |
942c4b32 | 55 | stoken = t1.get_stop_token(); |
ebc46494 JW |
56 | VERIFY(!stoken.stop_requested()); |
57 | } | |
58 | VERIFY(stoken.stop_requested()); | |
942c4b32 TR |
59 | } |
60 | ||
61 | //------------------------------------------------------ | |
62 | ||
63 | void test_stop_token() | |
64 | { | |
65 | // test the basic thread API (taking stop_token arg) | |
66 | ||
67 | std::stop_source ssource; | |
68 | std::stop_source origsource; | |
ebc46494 JW |
69 | VERIFY(ssource.stop_possible()); |
70 | VERIFY(!ssource.stop_requested()); | |
942c4b32 TR |
71 | { |
72 | std::jthread::id t1ID{std::this_thread::get_id()}; | |
73 | std::atomic<bool> t1AllSet{false}; | |
74 | std::atomic<bool> t1done{false}; | |
75 | std::jthread t1([&t1ID, &t1AllSet, &t1done] (std::stop_token st) { | |
76 | // check some values of the started thread: | |
77 | t1ID = std::this_thread::get_id(); | |
78 | t1AllSet.store(true); | |
79 | for (int i=0; !st.stop_requested(); ++i) { | |
80 | std::this_thread::sleep_for(100ms); | |
81 | } | |
82 | t1done.store(true); | |
83 | }, | |
84 | ssource.get_token()); | |
85 | for (int i=0; !t1AllSet.load(); ++i) { | |
86 | std::this_thread::sleep_for(10ms); | |
87 | } | |
88 | // and check all values: | |
ebc46494 JW |
89 | VERIFY(t1.joinable()); |
90 | VERIFY(t1ID == t1.get_id()); | |
942c4b32 TR |
91 | |
92 | std::this_thread::sleep_for(470ms); | |
93 | origsource = std::move(ssource); | |
94 | ssource = t1.get_stop_source(); | |
ebc46494 | 95 | VERIFY(!ssource.stop_requested()); |
942c4b32 | 96 | auto ret = ssource.request_stop(); |
ebc46494 | 97 | VERIFY(ret); |
942c4b32 | 98 | ret = ssource.request_stop(); |
ebc46494 JW |
99 | VERIFY(!ret); |
100 | VERIFY(ssource.stop_requested()); | |
101 | VERIFY(!t1done.load()); | |
102 | VERIFY(!origsource.stop_requested()); | |
942c4b32 TR |
103 | |
104 | std::this_thread::sleep_for(470ms); | |
105 | origsource.request_stop(); | |
ebc46494 JW |
106 | } |
107 | VERIFY(origsource.stop_requested()); | |
108 | VERIFY(ssource.stop_requested()); | |
942c4b32 TR |
109 | } |
110 | ||
111 | //------------------------------------------------------ | |
112 | ||
113 | void test_join() | |
114 | { | |
115 | std::stop_source ssource; | |
ebc46494 | 116 | VERIFY(ssource.stop_possible()); |
942c4b32 TR |
117 | { |
118 | std::jthread t1([](std::stop_token stoken) { | |
119 | for (int i=0; !stoken.stop_requested(); ++i) { | |
120 | std::this_thread::sleep_for(100ms); | |
121 | } | |
122 | }); | |
123 | ssource = t1.get_stop_source(); | |
124 | std::jthread t2([ssource] () mutable { | |
125 | for (int i=0; i < 10; ++i) { | |
126 | std::this_thread::sleep_for(70ms); | |
127 | } | |
128 | ssource.request_stop(); | |
129 | }); | |
130 | // wait for all thread to finish: | |
131 | t2.join(); | |
ebc46494 JW |
132 | VERIFY(!t2.joinable()); |
133 | VERIFY(t1.joinable()); | |
942c4b32 | 134 | t1.join(); |
ebc46494 | 135 | VERIFY(!t1.joinable()); |
942c4b32 TR |
136 | } |
137 | } | |
138 | ||
139 | //------------------------------------------------------ | |
140 | ||
141 | void test_detach() | |
142 | { | |
143 | std::stop_source ssource; | |
ebc46494 | 144 | VERIFY(ssource.stop_possible()); |
942c4b32 TR |
145 | std::atomic<bool> t1FinallyInterrupted{false}; |
146 | { | |
147 | std::jthread t0; | |
148 | std::jthread::id t1ID{std::this_thread::get_id()}; | |
149 | bool t1IsInterrupted; | |
150 | std::stop_token t1InterruptToken; | |
151 | std::atomic<bool> t1AllSet{false}; | |
152 | std::jthread t1([&t1ID, &t1IsInterrupted, &t1InterruptToken, &t1AllSet, &t1FinallyInterrupted] | |
153 | (std::stop_token stoken) { | |
154 | // check some values of the started thread: | |
155 | t1ID = std::this_thread::get_id(); | |
156 | t1InterruptToken = stoken; | |
157 | t1IsInterrupted = stoken.stop_requested(); | |
ebc46494 JW |
158 | VERIFY(stoken.stop_possible()); |
159 | VERIFY(!stoken.stop_requested()); | |
942c4b32 TR |
160 | t1AllSet.store(true); |
161 | for (int i=0; !stoken.stop_requested(); ++i) { | |
162 | std::this_thread::sleep_for(100ms); | |
163 | } | |
164 | t1FinallyInterrupted.store(true); | |
165 | }); | |
166 | for (int i=0; !t1AllSet.load(); ++i) { | |
167 | std::this_thread::sleep_for(10ms); | |
168 | } | |
ebc46494 JW |
169 | VERIFY(!t0.joinable()); |
170 | VERIFY(t1.joinable()); | |
171 | VERIFY(t1ID == t1.get_id()); | |
172 | VERIFY(t1IsInterrupted == false); | |
173 | VERIFY(t1InterruptToken == t1.get_stop_source().get_token()); | |
942c4b32 | 174 | ssource = t1.get_stop_source(); |
ebc46494 JW |
175 | VERIFY(t1InterruptToken.stop_possible()); |
176 | VERIFY(!t1InterruptToken.stop_requested()); | |
942c4b32 | 177 | t1.detach(); |
ebc46494 | 178 | VERIFY(!t1.joinable()); |
942c4b32 TR |
179 | } |
180 | ||
ebc46494 | 181 | VERIFY(!t1FinallyInterrupted.load()); |
942c4b32 | 182 | ssource.request_stop(); |
ebc46494 | 183 | VERIFY(ssource.stop_requested()); |
942c4b32 TR |
184 | for (int i=0; !t1FinallyInterrupted.load() && i < 100; ++i) { |
185 | std::this_thread::sleep_for(100ms); | |
186 | } | |
ebc46494 | 187 | VERIFY(t1FinallyInterrupted.load()); |
942c4b32 TR |
188 | } |
189 | ||
0ebaea3b PS |
190 | //------------------------------------------------------ |
191 | ||
192 | void test_move_assignment() | |
193 | { | |
194 | std::jthread thread1([]{}); | |
195 | std::jthread thread2([]{}); | |
196 | ||
197 | const auto id2 = thread2.get_id(); | |
198 | const auto ssource2 = thread2.get_stop_source(); | |
199 | ||
200 | thread1 = std::move(thread2); | |
201 | ||
202 | VERIFY(thread1.get_id() == id2); | |
203 | VERIFY(thread2.get_id() == std::jthread::id()); | |
204 | ||
205 | VERIFY(thread1.get_stop_source() == ssource2); | |
206 | VERIFY(!thread2.get_stop_source().stop_possible()); | |
207 | } | |
208 | ||
942c4b32 TR |
209 | int main() |
210 | { | |
211 | std::set_terminate([](){ | |
ebc46494 | 212 | VERIFY(false); |
942c4b32 TR |
213 | }); |
214 | ||
215 | test_no_stop_token(); | |
216 | test_stop_token(); | |
217 | test_join(); | |
218 | test_detach(); | |
0ebaea3b | 219 | test_move_assignment(); |
942c4b32 | 220 | } |