]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/30_threads/jthread/jthread.cc
aeb9f1f1b7f8c7da7886efbf1feb5421a6fd01bd
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 30_threads / jthread / jthread.cc
1 // Copyright (C) 2019 Free Software Foundation, Inc.
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
18 // { dg-options "-std=gnu++2a -pthread" }
19 // { dg-do run { target c++2a } }
20 // { dg-require-effective-target pthread }
21 // { dg-require-gthreads "" }
22
23 #include <thread>
24 #include <chrono>
25 #include <atomic>
26 #include <testsuite_hooks.h>
27
28 using namespace std::literals;
29
30 //------------------------------------------------------
31
32 void test_no_stop_token()
33 {
34 // test the basic jthread API (not taking stop_token arg)
35
36 VERIFY(std::jthread::hardware_concurrency() == std::thread::hardware_concurrency());
37 std::stop_token stoken;
38 VERIFY(!stoken.stop_possible());
39 {
40 std::jthread::id t1ID{std::this_thread::get_id()};
41 std::atomic<bool> t1AllSet{false};
42 std::jthread t1([&t1ID, &t1AllSet] {
43 t1ID = std::this_thread::get_id();
44 t1AllSet.store(true);
45 for (int c='9'; c>='0'; --c) {
46 std::this_thread::sleep_for(222ms);
47 }
48 });
49 for (int i=0; !t1AllSet.load(); ++i) {
50 std::this_thread::sleep_for(10ms);
51 }
52 VERIFY(t1.joinable());
53 VERIFY(t1ID == t1.get_id());
54 stoken = t1.get_stop_token();
55 VERIFY(!stoken.stop_requested());
56 }
57 VERIFY(stoken.stop_requested());
58 }
59
60 //------------------------------------------------------
61
62 void test_stop_token()
63 {
64 // test the basic thread API (taking stop_token arg)
65
66 std::stop_source ssource;
67 std::stop_source origsource;
68 VERIFY(ssource.stop_possible());
69 VERIFY(!ssource.stop_requested());
70 {
71 std::jthread::id t1ID{std::this_thread::get_id()};
72 std::atomic<bool> t1AllSet{false};
73 std::atomic<bool> t1done{false};
74 std::jthread t1([&t1ID, &t1AllSet, &t1done] (std::stop_token st) {
75 // check some values of the started thread:
76 t1ID = std::this_thread::get_id();
77 t1AllSet.store(true);
78 for (int i=0; !st.stop_requested(); ++i) {
79 std::this_thread::sleep_for(100ms);
80 }
81 t1done.store(true);
82 },
83 ssource.get_token());
84 for (int i=0; !t1AllSet.load(); ++i) {
85 std::this_thread::sleep_for(10ms);
86 }
87 // and check all values:
88 VERIFY(t1.joinable());
89 VERIFY(t1ID == t1.get_id());
90
91 std::this_thread::sleep_for(470ms);
92 origsource = std::move(ssource);
93 ssource = t1.get_stop_source();
94 VERIFY(!ssource.stop_requested());
95 auto ret = ssource.request_stop();
96 VERIFY(ret);
97 ret = ssource.request_stop();
98 VERIFY(!ret);
99 VERIFY(ssource.stop_requested());
100 VERIFY(!t1done.load());
101 VERIFY(!origsource.stop_requested());
102
103 std::this_thread::sleep_for(470ms);
104 origsource.request_stop();
105 }
106 VERIFY(origsource.stop_requested());
107 VERIFY(ssource.stop_requested());
108 }
109
110 //------------------------------------------------------
111
112 void test_join()
113 {
114 std::stop_source ssource;
115 VERIFY(ssource.stop_possible());
116 {
117 std::jthread t1([](std::stop_token stoken) {
118 for (int i=0; !stoken.stop_requested(); ++i) {
119 std::this_thread::sleep_for(100ms);
120 }
121 });
122 ssource = t1.get_stop_source();
123 std::jthread t2([ssource] () mutable {
124 for (int i=0; i < 10; ++i) {
125 std::this_thread::sleep_for(70ms);
126 }
127 ssource.request_stop();
128 });
129 // wait for all thread to finish:
130 t2.join();
131 VERIFY(!t2.joinable());
132 VERIFY(t1.joinable());
133 t1.join();
134 VERIFY(!t1.joinable());
135 }
136 }
137
138 //------------------------------------------------------
139
140 void test_detach()
141 {
142 std::stop_source ssource;
143 VERIFY(ssource.stop_possible());
144 std::atomic<bool> t1FinallyInterrupted{false};
145 {
146 std::jthread t0;
147 std::jthread::id t1ID{std::this_thread::get_id()};
148 bool t1IsInterrupted;
149 std::stop_token t1InterruptToken;
150 std::atomic<bool> t1AllSet{false};
151 std::jthread t1([&t1ID, &t1IsInterrupted, &t1InterruptToken, &t1AllSet, &t1FinallyInterrupted]
152 (std::stop_token stoken) {
153 // check some values of the started thread:
154 t1ID = std::this_thread::get_id();
155 t1InterruptToken = stoken;
156 t1IsInterrupted = stoken.stop_requested();
157 VERIFY(stoken.stop_possible());
158 VERIFY(!stoken.stop_requested());
159 t1AllSet.store(true);
160 for (int i=0; !stoken.stop_requested(); ++i) {
161 std::this_thread::sleep_for(100ms);
162 }
163 t1FinallyInterrupted.store(true);
164 });
165 for (int i=0; !t1AllSet.load(); ++i) {
166 std::this_thread::sleep_for(10ms);
167 }
168 VERIFY(!t0.joinable());
169 VERIFY(t1.joinable());
170 VERIFY(t1ID == t1.get_id());
171 VERIFY(t1IsInterrupted == false);
172 VERIFY(t1InterruptToken == t1.get_stop_source().get_token());
173 ssource = t1.get_stop_source();
174 VERIFY(t1InterruptToken.stop_possible());
175 VERIFY(!t1InterruptToken.stop_requested());
176 t1.detach();
177 VERIFY(!t1.joinable());
178 }
179
180 VERIFY(!t1FinallyInterrupted.load());
181 ssource.request_stop();
182 VERIFY(ssource.stop_requested());
183 for (int i=0; !t1FinallyInterrupted.load() && i < 100; ++i) {
184 std::this_thread::sleep_for(100ms);
185 }
186 VERIFY(t1FinallyInterrupted.load());
187 }
188
189 int main()
190 {
191 std::set_terminate([](){
192 VERIFY(false);
193 });
194
195 test_no_stop_token();
196 test_stop_token();
197 test_join();
198 test_detach();
199 }