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