1 #pragma once
2 
3 #include "../relacy/relacy_std.hpp"
4 
5 
6 
7 struct test_mutex : rl::test_suite<test_mutex, 3>
8 {
9     rl::mutex mtx;
10     rl::var<int> data;
11 
beforetest_mutex12     void before()
13     {
14         data($) = 0;
15     }
16 
aftertest_mutex17     void after()
18     {
19         RL_ASSERT(data($) == 3);
20     }
21 
threadtest_mutex22     void thread(unsigned /*index*/)
23     {
24         mtx.lock($);
25         data($) += 1;
26         mtx.unlock($);
27     }
28 };
29 
30 
31 
32 
33 struct test_deadlock : rl::test_suite<test_deadlock, 2, rl::test_result_deadlock>
34 {
35     rl::mutex mtx1;
36     rl::mutex mtx2;
37 
threadtest_deadlock38     void thread(unsigned index)
39     {
40         if (0 == index)
41         {
42             mtx1.lock($);
43             mtx2.lock($);
44             mtx1.unlock($);
45             mtx2.unlock($);
46         }
47         else
48         {
49             mtx2.lock($);
50             mtx1.lock($);
51             mtx1.unlock($);
52             mtx2.unlock($);
53         }
54     }
55 };
56 
57 
58 
59 struct test_deadlock2 : rl::test_suite<test_deadlock2, 2, rl::test_result_deadlock>
60 {
61     std::mutex m;
62     std::atomic<int> f;
63 
beforetest_deadlock264     void before()
65     {
66         f($) = 0;
67     }
68 
threadtest_deadlock269     void thread(unsigned index)
70     {
71         if (index)
72         {
73             m.lock($);
74             f($) = 1;
75             for (int i = 0; i != 100; ++i)
76                 rl::yield(1, $);
77         }
78         else
79         {
80             while (0 == f($))
81                 rl::yield(1, $);
82             m.lock($);
83         }
84     }
85 };
86 
87 
88 
89 struct test_mutex_destuction : rl::test_suite<test_mutex_destuction, 1, rl::test_result_destroying_owned_mutex>
90 {
threadtest_mutex_destuction91     void thread(unsigned)
92     {
93         std::mutex* m = new std::mutex;
94         m->lock($);
95         delete m;
96     }
97 };
98 
99 
100 struct test_mutex_destuction2 : rl::test_suite<test_mutex_destuction2, 2, rl::test_result_destroying_owned_mutex>
101 {
102     std::mutex* m;
103     std::atomic<int> f;
104 
beforetest_mutex_destuction2105     void before()
106     {
107         m = new std::mutex;
108         f($) = 0;
109     }
110 
threadtest_mutex_destuction2111     void thread(unsigned index)
112     {
113         if (0 == index)
114         {
115             m->lock($);
116             f($) = 1;
117             while (1 == f($))
118                 rl::yield(1, $);
119             m->unlock($);
120         }
121         else
122         {
123             while (0 == f($))
124                 rl::yield(1, $);
125             delete m;
126             f($) = 2;
127         }
128     }
129 };
130 
131 
132 struct test_mutex_recursion : rl::test_suite<test_mutex_recursion, 2>
133 {
134     std::recursive_mutex mtx;
135     rl::var<int> data;
136 
beforetest_mutex_recursion137     void before()
138     {
139         data($) = 0;
140     }
141 
aftertest_mutex_recursion142     void after()
143     {
144         RL_ASSERT(data($) == 2);
145     }
146 
threadtest_mutex_recursion147     void thread(unsigned /*index*/)
148     {
149         mtx.lock($);
150         mtx.lock($);
151         data($) += 1;
152         mtx.unlock($);
153         mtx.unlock($);
154     }
155 };
156 
157 
158 
159 struct test_mutex_try_lock : rl::test_suite<test_mutex_try_lock, 2>
160 {
161     std::recursive_mutex mtx;
162     rl::var<int> data;
163 
beforetest_mutex_try_lock164     void before()
165     {
166         data($) = 0;
167     }
168 
aftertest_mutex_try_lock169     void after()
170     {
171         RL_ASSERT(data($) == 2);
172     }
173 
threadtest_mutex_try_lock174     void thread(unsigned /*index*/)
175     {
176         while (false == mtx.try_lock($))
177             rl::yield(1, $);
178         RL_ASSERT(mtx.try_lock($));
179         data($) += 1;
180         mtx.unlock($);
181         mtx.unlock($);
182     }
183 };
184 
185 
186 
187 struct test_mutex_recursion_error : rl::test_suite<test_mutex_recursion_error, 1, rl::test_result_recursion_on_nonrecursive_mutex>
188 {
threadtest_mutex_recursion_error189     void thread(unsigned)
190     {
191         std::mutex m;
192         m.lock($);
193         m.lock($);
194     }
195 };
196 
197 
198 
199 struct test_mutex_unlock_error : rl::test_suite<test_mutex_unlock_error, 1, rl::test_result_unlocking_mutex_wo_ownership>
200 {
threadtest_mutex_unlock_error201     void thread(unsigned)
202     {
203         std::mutex m;
204         m.lock($);
205         m.unlock($);
206         m.unlock($);
207     }
208 };
209 
210 
211 struct test_mutex_leak : rl::test_suite<test_mutex_leak, 1, rl::test_result_resource_leak>
212 {
threadtest_mutex_leak213     void thread(unsigned)
214     {
215         char* p = new char [sizeof(std::mutex)];
216         new (p) std::mutex();
217         delete [] p;
218     }
219 };
220 
221 
222