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