xref: /llvm-project/libcxx/test/std/thread/thread.mutex/thread.lock.algorithm/lock.pass.cpp (revision a7f9895cc18995549c7facb96e72718da282a864)
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 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: no-threads
10 
11 // This test hangs forever when built against libstdc++ (Oct 2016).
12 // UNSUPPORTED: stdlib=libstdc++
13 
14 // This test isn't quite standards-conforming: it's testing our specific
15 // algorithm, where when lx.try_lock() fails we start the next attempt
16 // with an unconditional lx.lock(). Thus our algorithm can handle a list
17 // of mutexes where at-most-one of them is of the evil type `class L1`,
18 // but will loop forever if two or more of them are `class L1`.
19 
20 // <mutex>
21 
22 // template <class L1, class L2, class... L3>
23 //   void lock(L1&, L2&, L3&...);
24 
25 #include <mutex>
26 #include <cassert>
27 
28 #include "test_macros.h"
29 
30 class L0
31 {
32     bool locked_;
33 
34 public:
L0()35     L0() : locked_(false) {}
36 
lock()37     void lock()
38     {
39         locked_ = true;
40     }
41 
try_lock()42     bool try_lock()
43     {
44         locked_ = true;
45         return locked_;
46     }
47 
unlock()48     void unlock() {locked_ = false;}
49 
locked() const50     bool locked() const {return locked_;}
51 };
52 
53 class L1
54 {
55     bool locked_;
56 
57 public:
L1()58     L1() : locked_(false) {}
59 
lock()60     void lock()
61     {
62         locked_ = true;
63     }
64 
try_lock()65     bool try_lock()
66     {
67         locked_ = false;
68         return locked_;
69     }
70 
unlock()71     void unlock() {locked_ = false;}
72 
locked() const73     bool locked() const {return locked_;}
74 };
75 
76 class L2
77 {
78     bool locked_;
79 
80 public:
L2()81     L2() : locked_(false) {}
82 
lock()83     void lock()
84     {
85         TEST_THROW(1);
86     }
87 
try_lock()88     bool try_lock()
89     {
90         TEST_THROW(1);
91         return locked_;
92     }
93 
unlock()94     void unlock() {locked_ = false;}
95 
locked() const96     bool locked() const {return locked_;}
97 };
98 
main(int,char **)99 int main(int, char**)
100 {
101     {
102         L0 l0;
103         L0 l1;
104         std::lock(l0, l1);
105         assert(l0.locked());
106         assert(l1.locked());
107     }
108     {
109         L0 l0;
110         L1 l1;
111         std::lock(l0, l1);
112         assert(l0.locked());
113         assert(l1.locked());
114     }
115     {
116         L1 l0;
117         L0 l1;
118         std::lock(l0, l1);
119         assert(l0.locked());
120         assert(l1.locked());
121     }
122 #ifndef TEST_HAS_NO_EXCEPTIONS
123     {
124         L0 l0;
125         L2 l1;
126         try
127         {
128             std::lock(l0, l1);
129             assert(false);
130         }
131         catch (int)
132         {
133             assert(!l0.locked());
134             assert(!l1.locked());
135         }
136     }
137     {
138         L2 l0;
139         L0 l1;
140         try
141         {
142             std::lock(l0, l1);
143             assert(false);
144         }
145         catch (int)
146         {
147             assert(!l0.locked());
148             assert(!l1.locked());
149         }
150     }
151     {
152         L1 l0;
153         L2 l1;
154         try
155         {
156             std::lock(l0, l1);
157             assert(false);
158         }
159         catch (int)
160         {
161             assert(!l0.locked());
162             assert(!l1.locked());
163         }
164     }
165     {
166         L2 l0;
167         L1 l1;
168         try
169         {
170             std::lock(l0, l1);
171             assert(false);
172         }
173         catch (int)
174         {
175             assert(!l0.locked());
176             assert(!l1.locked());
177         }
178     }
179     {
180         L2 l0;
181         L2 l1;
182         try
183         {
184             std::lock(l0, l1);
185             assert(false);
186         }
187         catch (int)
188         {
189             assert(!l0.locked());
190             assert(!l1.locked());
191         }
192     }
193 #endif
194 #if TEST_STD_VER >= 11
195     {
196         L0 l0;
197         L0 l1;
198         L0 l2;
199         std::lock(l0, l1, l2);
200         assert(l0.locked());
201         assert(l1.locked());
202         assert(l2.locked());
203     }
204 #ifndef TEST_HAS_NO_EXCEPTIONS
205     {
206         L2 l0;
207         L2 l1;
208         L2 l2;
209         try
210         {
211             std::lock(l0, l1, l2);
212             assert(false);
213         }
214         catch (int)
215         {
216             assert(!l0.locked());
217             assert(!l1.locked());
218             assert(!l2.locked());
219         }
220     }
221 #endif
222     {
223         L0 l0;
224         L0 l1;
225         L1 l2;
226         std::lock(l0, l1, l2);
227         assert(l0.locked());
228         assert(l1.locked());
229         assert(l2.locked());
230     }
231     {
232         L0 l0;
233         L1 l1;
234         L0 l2;
235         std::lock(l0, l1, l2);
236         assert(l0.locked());
237         assert(l1.locked());
238         assert(l2.locked());
239     }
240     {
241         L1 l0;
242         L0 l1;
243         L0 l2;
244         std::lock(l0, l1, l2);
245         assert(l0.locked());
246         assert(l1.locked());
247         assert(l2.locked());
248     }
249 #ifndef TEST_HAS_NO_EXCEPTIONS
250     {
251         L0 l0;
252         L0 l1;
253         L2 l2;
254         try
255         {
256             std::lock(l0, l1, l2);
257             assert(false);
258         }
259         catch (int)
260         {
261             assert(!l0.locked());
262             assert(!l1.locked());
263             assert(!l2.locked());
264         }
265     }
266     {
267         L0 l0;
268         L2 l1;
269         L0 l2;
270         try
271         {
272             std::lock(l0, l1, l2);
273             assert(false);
274         }
275         catch (int)
276         {
277             assert(!l0.locked());
278             assert(!l1.locked());
279             assert(!l2.locked());
280         }
281     }
282     {
283         L2 l0;
284         L0 l1;
285         L0 l2;
286         try
287         {
288             std::lock(l0, l1, l2);
289             assert(false);
290         }
291         catch (int)
292         {
293             assert(!l0.locked());
294             assert(!l1.locked());
295             assert(!l2.locked());
296         }
297     }
298     {
299         L2 l0;
300         L2 l1;
301         L0 l2;
302         try
303         {
304             std::lock(l0, l1, l2);
305             assert(false);
306         }
307         catch (int)
308         {
309             assert(!l0.locked());
310             assert(!l1.locked());
311             assert(!l2.locked());
312         }
313     }
314     {
315         L2 l0;
316         L0 l1;
317         L2 l2;
318         try
319         {
320             std::lock(l0, l1, l2);
321             assert(false);
322         }
323         catch (int)
324         {
325             assert(!l0.locked());
326             assert(!l1.locked());
327             assert(!l2.locked());
328         }
329     }
330     {
331         L0 l0;
332         L2 l1;
333         L2 l2;
334         try
335         {
336             std::lock(l0, l1, l2);
337             assert(false);
338         }
339         catch (int)
340         {
341             assert(!l0.locked());
342             assert(!l1.locked());
343             assert(!l2.locked());
344         }
345     }
346     {
347         L2 l0;
348         L2 l1;
349         L1 l2;
350         try
351         {
352             std::lock(l0, l1, l2);
353             assert(false);
354         }
355         catch (int)
356         {
357             assert(!l0.locked());
358             assert(!l1.locked());
359             assert(!l2.locked());
360         }
361     }
362     {
363         L2 l0;
364         L1 l1;
365         L2 l2;
366         try
367         {
368             std::lock(l0, l1, l2);
369             assert(false);
370         }
371         catch (int)
372         {
373             assert(!l0.locked());
374             assert(!l1.locked());
375             assert(!l2.locked());
376         }
377     }
378     {
379         L1 l0;
380         L2 l1;
381         L2 l2;
382         try
383         {
384             std::lock(l0, l1, l2);
385             assert(false);
386         }
387         catch (int)
388         {
389             assert(!l0.locked());
390             assert(!l1.locked());
391             assert(!l2.locked());
392         }
393     }
394 #endif // TEST_HAS_NO_EXCEPTIONS
395     {
396         L0 l0;
397         L0 l1;
398         L0 l2;
399         L0 l3;
400         std::lock(l0, l1, l2, l3);
401         assert(l0.locked());
402         assert(l1.locked());
403         assert(l2.locked());
404         assert(l3.locked());
405     }
406     {
407         L0 l0;
408         L0 l1;
409         L0 l2;
410         L1 l3;
411         std::lock(l0, l1, l2, l3);
412         assert(l0.locked());
413         assert(l1.locked());
414         assert(l2.locked());
415         assert(l3.locked());
416     }
417     {
418         L0 l0;
419         L0 l1;
420         L1 l2;
421         L0 l3;
422         std::lock(l0, l1, l2, l3);
423         assert(l0.locked());
424         assert(l1.locked());
425         assert(l2.locked());
426         assert(l3.locked());
427     }
428     {
429         L0 l0;
430         L1 l1;
431         L0 l2;
432         L0 l3;
433         std::lock(l0, l1, l2, l3);
434         assert(l0.locked());
435         assert(l1.locked());
436         assert(l2.locked());
437         assert(l3.locked());
438     }
439     {
440         L1 l0;
441         L0 l1;
442         L0 l2;
443         L0 l3;
444         std::lock(l0, l1, l2, l3);
445         assert(l0.locked());
446         assert(l1.locked());
447         assert(l2.locked());
448         assert(l3.locked());
449     }
450 #ifndef TEST_HAS_NO_EXCEPTIONS
451     {
452         L0 l0;
453         L0 l1;
454         L0 l2;
455         L2 l3;
456         try
457         {
458             std::lock(l0, l1, l2, l3);
459             assert(false);
460         }
461         catch (int)
462         {
463             assert(!l0.locked());
464             assert(!l1.locked());
465             assert(!l2.locked());
466             assert(!l3.locked());
467         }
468     }
469     {
470         L0 l0;
471         L0 l1;
472         L2 l2;
473         L0 l3;
474         try
475         {
476             std::lock(l0, l1, l2, l3);
477             assert(false);
478         }
479         catch (int)
480         {
481             assert(!l0.locked());
482             assert(!l1.locked());
483             assert(!l2.locked());
484             assert(!l3.locked());
485         }
486     }
487     {
488         L0 l0;
489         L2 l1;
490         L0 l2;
491         L0 l3;
492         try
493         {
494             std::lock(l0, l1, l2, l3);
495             assert(false);
496         }
497         catch (int)
498         {
499             assert(!l0.locked());
500             assert(!l1.locked());
501             assert(!l2.locked());
502             assert(!l3.locked());
503         }
504     }
505     {
506         L2 l0;
507         L0 l1;
508         L0 l2;
509         L0 l3;
510         try
511         {
512             std::lock(l0, l1, l2, l3);
513             assert(false);
514         }
515         catch (int)
516         {
517             assert(!l0.locked());
518             assert(!l1.locked());
519             assert(!l2.locked());
520             assert(!l3.locked());
521         }
522     }
523 #endif // TEST_HAS_NO_EXCEPTIONS
524 #endif // TEST_STD_VER >= 11
525 
526   return 0;
527 }
528