]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/30_threads/jthread/jthread.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 30_threads / jthread / jthread.cc
CommitLineData
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 29using namespace std::literals;
942c4b32
TR
30
31//------------------------------------------------------
32
33void 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
63void 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
113void 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
141void 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
192void 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
209int 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}