]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/30_threads/lock/4.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 30_threads / lock / 4.cc
CommitLineData
d1236680 1// { dg-do run }
1e42d2f4 2// { dg-additional-options "-pthread" { target pthread } }
71c54f8e 3// { dg-require-effective-target c++11 }
9b2b801a
JW
4// { dg-require-gthreads "" }
5
a945c346 6// Copyright (C) 2010-2024 Free Software Foundation, Inc.
9b2b801a
JW
7//
8// This file is part of the GNU ISO C++ Library. This library is free
9// software; you can redistribute it and/or modify it under the
10// terms of the GNU General Public License as published by the
11// Free Software Foundation; either version 3, or (at your option)
12// any later version.
13
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18
19// You should have received a copy of the GNU General Public License along
20// with this library; see the file COPYING3. If not see
21// <http://www.gnu.org/licenses/>.
22
23
24#include <mutex>
25#include <testsuite_hooks.h>
26
27struct unreliable_lock
28{
29 std::mutex m;
30 std::unique_lock<std::mutex> l;
31
32 static int count;
33 static int throw_on;
34 static int lock_on;
35
36 unreliable_lock() : l(m, std::defer_lock) { }
37
38 ~unreliable_lock()
39 {
9b2b801a
JW
40 VERIFY( !l.owns_lock() );
41 }
42
43 void lock()
44 {
45 if (count == throw_on)
46 throw throw_on;
47 ++count;
48 l.lock();
49 }
50 bool try_lock()
51 {
52 if (count == throw_on)
53 throw throw_on;
54 std::unique_lock<std::mutex> l2(m, std::defer_lock);
55 if (count == lock_on)
56 l2.lock();
57 ++count;
58 return l.try_lock();
59 }
60
61 void unlock()
62 {
9b2b801a
JW
63 VERIFY( l.owns_lock() );
64 l.unlock();
65 }
66
67};
68
69int unreliable_lock::count = 0;
70int unreliable_lock::throw_on = -1;
71int unreliable_lock::lock_on = -1;
72
73void test01()
74{
9b2b801a 75 unreliable_lock l1, l2, l3;
c5565961 76 std::mutex m1, m2, m3;
9b2b801a
JW
77
78 try
79 {
80 unreliable_lock::count = 0;
81 std::lock(l1, l2, l3);
82 VERIFY( unreliable_lock::count == 3 );
83 l1.unlock();
84 l2.unlock();
85 l3.unlock();
86 }
87 catch (...)
88 {
89 VERIFY( false );
90 }
c5565961
JW
91
92 // Repeat with non-heterogeneous arguments
93
94 try
95 {
96 unreliable_lock::count = 0;
97 std::lock(l1, l2, l3, m1);
98 VERIFY( unreliable_lock::count == 3 );
99 l1.unlock();
100 l2.unlock();
101 l3.unlock();
102 VERIFY( !m1.try_lock() ); // already locked
103 m1.unlock();
104 }
105 catch (...)
106 {
107 VERIFY( false );
108 }
109
110 try
111 {
112 unreliable_lock::count = 0;
113 std::lock(m1, l1, l2, l3);
114 VERIFY( unreliable_lock::count == 3 );
115 VERIFY( !m1.try_lock() ); // already locked
116 m1.unlock();
117 l1.unlock();
118 l2.unlock();
119 l3.unlock();
120 }
121 catch (...)
122 {
123 VERIFY( false );
124 }
125
126 try
127 {
128 unreliable_lock::count = 0;
129 std::lock(l1, m1, l2, m2, l3, m3);
130 VERIFY( unreliable_lock::count == 3 );
131 l1.unlock();
132 l2.unlock();
133 l3.unlock();
134 VERIFY( !m1.try_lock() ); // already locked
135 VERIFY( !m2.try_lock() ); // already locked
136 VERIFY( !m3.try_lock() ); // already locked
137 m1.unlock();
138 m2.unlock();
139 m3.unlock();
140 }
141 catch (...)
142 {
143 VERIFY( false );
144 }
9b2b801a
JW
145}
146
147void test02()
148{
9b2b801a
JW
149 // test behaviour when a lock is already held
150 try
151 {
152 unreliable_lock::lock_on = 1;
153 while (unreliable_lock::lock_on < 3)
154 {
155 unreliable_lock::count = 0;
156 unreliable_lock l1, l2, l3;
157 std::lock(l1, l2, l3);
158 VERIFY( unreliable_lock::count > 3 );
159 l1.unlock();
160 l2.unlock();
161 l3.unlock();
162 ++unreliable_lock::lock_on;
163 }
164 }
165 catch (...)
166 {
167 VERIFY( false );
168 }
c5565961
JW
169
170 // Repeat with non-heterogeneous arguments
171
172 try
173 {
174 unreliable_lock::lock_on = 1;
175 while (unreliable_lock::lock_on < 3)
176 {
177 unreliable_lock::count = 0;
178 unreliable_lock l1, l2, l3;
179 std::mutex m1;
180 std::lock(l1, l2, l3, m1);
181 VERIFY( unreliable_lock::count > 3 );
182 l1.unlock();
183 l2.unlock();
184 l3.unlock();
185 VERIFY( !m1.try_lock() ); // already locked
186 m1.unlock();
187 ++unreliable_lock::lock_on;
188 }
189 }
190 catch (...)
191 {
192 VERIFY( false );
193 }
9b2b801a
JW
194}
195
196void test03()
197{
198 // test behaviour when an exception is thrown
199 unreliable_lock::throw_on = 0;
200 while (unreliable_lock::throw_on < 3)
201 {
202 unreliable_lock::count = 0;
203 unreliable_lock l1, l2, l3;
204 bool test = false;
205 try
206 {
207 std::lock(l1, l2, l3);
208 }
209 catch (...)
210 {
211 test = true;
212 }
213 VERIFY( test );
214 ++unreliable_lock::throw_on;
215 }
c5565961
JW
216
217 // Repeat with non-heterogeneous arguments
218
219 unreliable_lock::throw_on = 0;
220 while (unreliable_lock::throw_on < 3)
221 {
222 unreliable_lock::count = 0;
223 unreliable_lock l1, l2, l3;
224 std::mutex m1;
225 bool test = false;
226 try
227 {
228 std::lock(l1, l2, l3, m1);
229 }
230 catch (...)
231 {
232 test = true;
233 }
234 VERIFY( test );
235 VERIFY( m1.try_lock() ); // m1 was not left locked by failed std::lock
236 m1.unlock();
237 ++unreliable_lock::throw_on;
238 }
239
240 unreliable_lock::throw_on = 0;
241 while (unreliable_lock::throw_on < 3)
242 {
243 unreliable_lock::count = 0;
244 unreliable_lock l1, l2, l3;
245 std::mutex m1;
246 bool test = false;
247 try
248 {
249 std::lock(m1, l1, l2, l3);
250 }
251 catch (...)
252 {
253 test = true;
254 }
255 VERIFY( test );
256 VERIFY( m1.try_lock() ); // m1 was not left locked by failed std::lock
257 m1.unlock();
258 ++unreliable_lock::throw_on;
259 }
9b2b801a
JW
260}
261
262int main()
263{
264 test01();
265 test02();
266 test03();
267 return 0;
268}