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