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
18class L0
19{
20    bool locked_;
21
22public:
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
36class L1
37{
38    bool locked_;
39
40public:
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
54class L2
55{
56    bool locked_;
57
58public:
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
72int 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