[InstrProf] Add frontend temporal profiling flag (#122385)
[llvm-project.git] / libcxx / test / std / thread / thread.mutex / thread.lock / thread.lock.scoped / mutex.pass.cpp
blobf953fa4f8d6df20385996f2b100f762b19716fce
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: no-threads
10 // UNSUPPORTED: c++03, c++11, c++14
12 // <mutex>
14 // template <class ...Mutex> class scoped_lock;
16 // explicit scoped_lock(mutex_type& m);
18 #include <mutex>
19 #include <cassert>
20 #include "test_macros.h"
22 struct TestMutex {
23 bool locked = false;
24 TestMutex() = default;
25 ~TestMutex() { assert(!locked); }
27 void lock() { assert(!locked); locked = true; }
28 bool try_lock() { if (locked) return false; locked = true; return true; }
29 void unlock() { assert(locked); locked = false; }
31 TestMutex(TestMutex const&) = delete;
32 TestMutex& operator=(TestMutex const&) = delete;
35 #if !defined(TEST_HAS_NO_EXCEPTIONS)
36 struct TestMutexThrows {
37 bool locked = false;
38 bool throws_on_lock = false;
40 TestMutexThrows() = default;
41 ~TestMutexThrows() { assert(!locked); }
43 void lock() {
44 assert(!locked);
45 if (throws_on_lock) {
46 throw 42;
48 locked = true;
51 bool try_lock() {
52 if (locked) return false;
53 lock();
54 return true;
57 void unlock() { assert(locked); locked = false; }
59 TestMutexThrows(TestMutexThrows const&) = delete;
60 TestMutexThrows& operator=(TestMutexThrows const&) = delete;
62 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
64 int main(int, char**)
67 using LG = std::scoped_lock<>;
68 LG lg;
69 (void)lg;
72 using LG = std::scoped_lock<TestMutex>;
73 TestMutex m1;
75 LG lg(m1);
76 assert(m1.locked);
78 assert(!m1.locked);
81 using LG = std::scoped_lock<TestMutex, TestMutex>;
82 TestMutex m1, m2;
84 LG lg(m1, m2);
85 assert(m1.locked && m2.locked);
87 assert(!m1.locked && !m2.locked);
90 using LG = std::scoped_lock<TestMutex, TestMutex, TestMutex>;
91 TestMutex m1, m2, m3;
93 LG lg(m1, m2, m3);
94 assert(m1.locked && m2.locked && m3.locked);
96 assert(!m1.locked && !m2.locked && !m3.locked);
98 #if !defined(TEST_HAS_NO_EXCEPTIONS)
100 using MT = TestMutexThrows;
101 using LG = std::scoped_lock<MT>;
102 MT m1;
103 m1.throws_on_lock = true;
104 try {
105 LG lg(m1);
106 assert(false);
107 } catch (int) {}
108 assert(!m1.locked);
111 using MT = TestMutexThrows;
112 using LG = std::scoped_lock<MT, MT>;
113 MT m1, m2;
114 m1.throws_on_lock = true;
115 try {
116 LG lg(m1, m2);
117 assert(false);
118 } catch (int) {}
119 assert(!m1.locked && !m2.locked);
122 using MT = TestMutexThrows;
123 using LG = std::scoped_lock<MT, MT, MT>;
124 MT m1, m2, m3;
125 m2.throws_on_lock = true;
126 try {
127 LG lg(m1, m2, m3);
128 assert(false);
129 } catch (int) {}
130 assert(!m1.locked && !m2.locked && !m3.locked);
132 #endif
134 #if TEST_STD_VER >= 17
136 TestMutex m1, m2, m3;
138 std::scoped_lock sl{};
139 static_assert((std::is_same<decltype(sl), std::scoped_lock<>>::value), "" );
142 std::scoped_lock sl{m1};
143 static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1)>>::value), "" );
146 std::scoped_lock sl{m1, m2};
147 static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2)>>::value), "" );
150 std::scoped_lock sl{m1, m2, m3};
151 static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2), decltype(m3)>>::value), "" );
154 #endif
156 return 0;