]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/mutex.pass.cpp
Vendor import of libc++ trunk r300422:
[FreeBSD/FreeBSD.git] / test / std / thread / thread.mutex / thread.lock / thread.lock.scoped / mutex.pass.cpp
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, c++11, c++14
12
13 // <mutex>
14
15 // template <class ...Mutex> class scoped_lock;
16
17 // explicit scoped_lock(mutex_type& m);
18
19 #include <mutex>
20 #include <cassert>
21 #include "test_macros.h"
22
23 struct TestMutex {
24     bool locked = false;
25     TestMutex() = default;
26     ~TestMutex() { assert(!locked); }
27
28     void lock() { assert(!locked); locked = true; }
29     bool try_lock() { if (locked) return false; locked = true; return true; }
30     void unlock() { assert(locked); locked = false; }
31
32     TestMutex(TestMutex const&) = delete;
33     TestMutex& operator=(TestMutex const&) = delete;
34 };
35
36 #if !defined(TEST_HAS_NO_EXCEPTIONS)
37 struct TestMutexThrows {
38     bool locked = false;
39     bool throws_on_lock = false;
40
41     TestMutexThrows() = default;
42     ~TestMutexThrows() { assert(!locked); }
43
44     void lock() {
45         assert(!locked);
46         if (throws_on_lock) {
47             throw 42;
48         }
49         locked = true;
50     }
51
52     bool try_lock() {
53         if (locked) return false;
54         lock();
55         return true;
56     }
57
58     void unlock() { assert(locked); locked = false; }
59
60     TestMutexThrows(TestMutexThrows const&) = delete;
61     TestMutexThrows& operator=(TestMutexThrows const&) = delete;
62 };
63 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
64
65 int main()
66 {
67     {
68         using LG = std::scoped_lock<>;
69         LG lg;
70     }
71     {
72         using LG = std::scoped_lock<TestMutex>;
73         TestMutex m1;
74         {
75             LG lg(m1);
76             assert(m1.locked);
77         }
78         assert(!m1.locked);
79     }
80     {
81         using LG = std::scoped_lock<TestMutex, TestMutex>;
82         TestMutex m1, m2;
83         {
84             LG lg(m1, m2);
85             assert(m1.locked && m2.locked);
86         }
87         assert(!m1.locked && !m2.locked);
88     }
89     {
90         using LG = std::scoped_lock<TestMutex, TestMutex, TestMutex>;
91         TestMutex m1, m2, m3;
92         {
93             LG lg(m1, m2, m3);
94             assert(m1.locked && m2.locked && m3.locked);
95         }
96         assert(!m1.locked && !m2.locked && !m3.locked);
97     }
98 #if !defined(TEST_HAS_NO_EXCEPTIONS)
99     {
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);
109     }
110     {
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);
120     }
121     {
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);
131     }
132 #endif
133
134 #ifdef __cpp_deduction_guides
135     {
136     TestMutex m1, m2, m3;
137         {
138         std::scoped_lock sl{};
139         static_assert((std::is_same<decltype(sl), std::scoped_lock<>>::value), "" );
140         }
141         {
142         std::scoped_lock sl{m1};
143         static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1)>>::value), "" );
144         }
145         {
146         std::scoped_lock sl{m1, m2};
147         static_assert((std::is_same<decltype(sl), std::scoped_lock<decltype(m1), decltype(m2)>>::value), "" );
148         }
149         {
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), "" );
152         }
153     } 
154 #endif
155 }