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