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 // UNSUPPORTED: c++98, c++03
12
13 // <mutex>
14
15 // template <class ...Mutex> class lock_guard;
16
17 // explicit lock_guard(mutex_type& m);
18
19 // MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD
20 #define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
21 #include <mutex>
22 #include <cassert>
23
24 #include "test_macros.h"
25
26 struct TestMutex {
27 bool locked = false;
28 TestMutex() = default;
~TestMutexTestMutex29 ~TestMutex() { assert(!locked); }
30
lockTestMutex31 void lock() { assert(!locked); locked = true; }
try_lockTestMutex32 bool try_lock() { if (locked) return false; locked = true; return true; }
unlockTestMutex33 void unlock() { assert(locked); locked = false; }
34
35 TestMutex(TestMutex const&) = delete;
36 TestMutex& operator=(TestMutex const&) = delete;
37 };
38
39 #if !defined(TEST_HAS_NO_EXCEPTIONS)
40 struct TestMutexThrows {
41 bool locked = false;
42 bool throws_on_lock = false;
43
44 TestMutexThrows() = default;
~TestMutexThrowsTestMutexThrows45 ~TestMutexThrows() { assert(!locked); }
46
lockTestMutexThrows47 void lock() {
48 assert(!locked);
49 if (throws_on_lock) {
50 throw 42;
51 }
52 locked = true;
53 }
54
try_lockTestMutexThrows55 bool try_lock() {
56 if (locked) return false;
57 lock();
58 return true;
59 }
60
unlockTestMutexThrows61 void unlock() { assert(locked); locked = false; }
62
63 TestMutexThrows(TestMutexThrows const&) = delete;
64 TestMutexThrows& operator=(TestMutexThrows const&) = delete;
65 };
66 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
67
main()68 int main()
69 {
70 {
71 using LG = std::lock_guard<>;
72 LG lg;
73 }
74 {
75 using LG = std::lock_guard<TestMutex, TestMutex>;
76 TestMutex m1, m2;
77 {
78 LG lg(m1, m2);
79 assert(m1.locked && m2.locked);
80 }
81 assert(!m1.locked && !m2.locked);
82 }
83 {
84 using LG = std::lock_guard<TestMutex, TestMutex, TestMutex>;
85 TestMutex m1, m2, m3;
86 {
87 LG lg(m1, m2, m3);
88 assert(m1.locked && m2.locked && m3.locked);
89 }
90 assert(!m1.locked && !m2.locked && !m3.locked);
91 }
92 #if !defined(TEST_HAS_NO_EXCEPTIONS)
93 {
94 using MT = TestMutexThrows;
95 using LG = std::lock_guard<MT, MT>;
96 MT m1, m2;
97 m1.throws_on_lock = true;
98 try {
99 LG lg(m1, m2);
100 assert(false);
101 } catch (int) {}
102 assert(!m1.locked && !m2.locked);
103 }
104 {
105 using MT = TestMutexThrows;
106 using LG = std::lock_guard<MT, MT, MT>;
107 MT m1, m2, m3;
108 m2.throws_on_lock = true;
109 try {
110 LG lg(m1, m2, m3);
111 assert(false);
112 } catch (int) {}
113 assert(!m1.locked && !m2.locked && !m3.locked);
114 }
115 #endif
116 }
117