1// Copyright (C) 2001-2003
2// William E. Kempf
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7#define BOOST_THREAD_VERSION 2
8#define BOOST_TEST_MODULE Boost.Threads: mutex test suite
9
10#include <boost/thread/detail/config.hpp>
11
12#include <boost/thread/mutex.hpp>
13#include <boost/thread/lock_types.hpp>
14#include <boost/thread/thread_only.hpp>
15#include <boost/thread/recursive_mutex.hpp>
16#include <boost/thread/thread_time.hpp>
17#include <boost/thread/condition.hpp>
18
19#define BOOST_TEST_MODULE Boost.Threads: mutex test suite
20
21#include <boost/test/unit_test.hpp>
22
23#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only
24#include "./util.inl"
25
26template <typename M>
27struct test_lock
28{
29 typedef M mutex_type;
30 typedef typename M::scoped_lock lock_type;
31
32 void operator()()
33 {
34 mutex_type mutex;
35 boost::condition condition;
36
37 // Test the lock's constructors.
38 {
39 lock_type lock(mutex, boost::defer_lock);
40 BOOST_CHECK(!lock);
41 }
42 lock_type lock(mutex);
43 BOOST_CHECK(lock ? true : false);
44
45 // Construct and initialize an xtime for a fast time out.
46 boost::xtime xt = delay(secs: 0, msecs: 100);
47
48 // Test the lock and the mutex with condition variables.
49 // No one is going to notify this condition variable. We expect to
50 // time out.
51 BOOST_CHECK(!condition.timed_wait(lock, xt));
52 BOOST_CHECK(lock ? true : false);
53
54 // Test the lock and unlock methods.
55 lock.unlock();
56 BOOST_CHECK(!lock);
57 lock.lock();
58 BOOST_CHECK(lock ? true : false);
59 }
60};
61
62template <typename M>
63struct test_trylock
64{
65 typedef M mutex_type;
66 typedef typename M::scoped_try_lock try_lock_type;
67
68 void operator()()
69 {
70 mutex_type mutex;
71 boost::condition condition;
72
73 // Test the lock's constructors.
74 {
75 try_lock_type lock(mutex);
76 BOOST_CHECK(lock ? true : false);
77 }
78 {
79 try_lock_type lock(mutex, boost::defer_lock);
80 BOOST_CHECK(!lock);
81 }
82 try_lock_type lock(mutex);
83 BOOST_CHECK(lock ? true : false);
84
85 // Construct and initialize an xtime for a fast time out.
86 boost::xtime xt = delay(secs: 0, msecs: 100);
87
88 // Test the lock and the mutex with condition variables.
89 // No one is going to notify this condition variable. We expect to
90 // time out.
91 BOOST_CHECK(!condition.timed_wait(lock, xt));
92 BOOST_CHECK(lock ? true : false);
93
94 // Test the lock, unlock and trylock methods.
95 lock.unlock();
96 BOOST_CHECK(!lock);
97 lock.lock();
98 BOOST_CHECK(lock ? true : false);
99 lock.unlock();
100 BOOST_CHECK(!lock);
101 BOOST_CHECK(lock.try_lock());
102 BOOST_CHECK(lock ? true : false);
103 }
104};
105
106template<typename Mutex>
107struct test_lock_times_out_if_other_thread_has_lock
108{
109 typedef boost::unique_lock<Mutex> Lock;
110
111 Mutex m;
112 boost::mutex done_mutex;
113 bool done;
114 bool locked;
115 boost::condition_variable done_cond;
116
117 test_lock_times_out_if_other_thread_has_lock():
118 done(false),locked(false)
119 {}
120
121 void locking_thread()
122 {
123 Lock lock(m,boost::defer_lock);
124 lock.timed_lock(boost::posix_time::milliseconds(50));
125
126 boost::lock_guard<boost::mutex> lk(done_mutex);
127 locked=lock.owns_lock();
128 done=true;
129 done_cond.notify_one();
130 }
131
132 void locking_thread_through_constructor()
133 {
134 Lock lock(m,boost::posix_time::milliseconds(50));
135
136 boost::lock_guard<boost::mutex> lk(done_mutex);
137 locked=lock.owns_lock();
138 done=true;
139 done_cond.notify_one();
140 }
141
142 bool is_done() const
143 {
144 return done;
145 }
146
147 typedef test_lock_times_out_if_other_thread_has_lock<Mutex> this_type;
148
149 void do_test(void (this_type::*test_func)())
150 {
151 Lock lock(m);
152
153 locked=false;
154 done=false;
155
156 boost::thread t(test_func,this);
157
158 try
159 {
160 {
161 boost::unique_lock<boost::mutex> lk(done_mutex);
162 BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
163 boost::bind(&this_type::is_done,this)));
164 BOOST_CHECK(!locked);
165 }
166
167 lock.unlock();
168 t.join();
169 }
170 catch(...)
171 {
172 lock.unlock();
173 t.join();
174 throw;
175 }
176 }
177
178
179 void operator()()
180 {
181 do_test(test_func: &this_type::locking_thread);
182 do_test(test_func: &this_type::locking_thread_through_constructor);
183 }
184};
185
186template <typename M>
187struct test_timedlock
188{
189 typedef M mutex_type;
190 typedef typename M::scoped_timed_lock timed_lock_type;
191
192 static bool fake_predicate()
193 {
194 return false;
195 }
196
197 void operator()()
198 {
199 test_lock_times_out_if_other_thread_has_lock<mutex_type>()();
200
201 mutex_type mutex;
202 boost::condition condition;
203
204 // Test the lock's constructors.
205 {
206 // Construct and initialize an xtime for a fast time out.
207 boost::system_time xt = boost::get_system_time()+boost::posix_time::milliseconds(100);
208
209 timed_lock_type lock(mutex, xt);
210 BOOST_CHECK(lock ? true : false);
211 }
212 {
213 timed_lock_type lock(mutex, boost::defer_lock);
214 BOOST_CHECK(!lock);
215 }
216 timed_lock_type lock(mutex);
217 BOOST_CHECK(lock ? true : false);
218
219 // Construct and initialize an xtime for a fast time out.
220 boost::system_time timeout = boost::get_system_time()+boost::posix_time::milliseconds(100);
221
222 // Test the lock and the mutex with condition variables.
223 // No one is going to notify this condition variable. We expect to
224 // time out.
225 BOOST_CHECK(!condition.timed_wait(lock, timeout, fake_predicate));
226 BOOST_CHECK(lock ? true : false);
227
228 boost::system_time now=boost::get_system_time();
229 boost::posix_time::milliseconds const timeout_resolution(20);
230 BOOST_CHECK((timeout-timeout_resolution)<now);
231
232 // Test the lock, unlock and timedlock methods.
233 lock.unlock();
234 BOOST_CHECK(!lock);
235 lock.lock();
236 BOOST_CHECK(lock ? true : false);
237 lock.unlock();
238 BOOST_CHECK(!lock);
239 boost::system_time target = boost::get_system_time()+boost::posix_time::milliseconds(100);
240 BOOST_CHECK(lock.timed_lock(target));
241 BOOST_CHECK(lock ? true : false);
242 lock.unlock();
243 BOOST_CHECK(!lock);
244
245 BOOST_CHECK(mutex.timed_lock(boost::posix_time::milliseconds(100)));
246 mutex.unlock();
247
248 BOOST_CHECK(lock.timed_lock(boost::posix_time::milliseconds(100)));
249 BOOST_CHECK(lock ? true : false);
250 lock.unlock();
251 BOOST_CHECK(!lock);
252
253 }
254};
255
256template <typename M>
257struct test_recursive_lock
258{
259 typedef M mutex_type;
260 typedef typename M::scoped_lock lock_type;
261
262 void operator()()
263 {
264 mutex_type mx;
265 lock_type lock1(mx);
266 lock_type lock2(mx);
267 }
268};
269
270
271void do_test_mutex()
272{
273 test_lock<boost::mutex>()();
274}
275
276BOOST_AUTO_TEST_CASE(test_mutex)
277{
278 timed_test(func: &do_test_mutex, secs: 3);
279}
280
281void do_test_try_mutex()
282{
283 test_lock<boost::try_mutex>()();
284 test_trylock<boost::try_mutex>()();
285}
286
287BOOST_AUTO_TEST_CASE(test_try_mutex)
288{
289 timed_test(func: &do_test_try_mutex, secs: 3);
290}
291
292void do_test_timed_mutex()
293{
294 test_lock<boost::timed_mutex>()();
295 test_trylock<boost::timed_mutex>()();
296 test_timedlock<boost::timed_mutex>()();
297}
298
299BOOST_AUTO_TEST_CASE(test_timed_mutex)
300{
301 timed_test(func: &do_test_timed_mutex, secs: 3);
302}
303
304void do_test_recursive_mutex()
305{
306 test_lock<boost::recursive_mutex>()();
307 test_recursive_lock<boost::recursive_mutex>()();
308}
309
310BOOST_AUTO_TEST_CASE(test_recursive_mutex)
311{
312 timed_test(func: &do_test_recursive_mutex, secs: 3);
313}
314
315void do_test_recursive_try_mutex()
316{
317 test_lock<boost::recursive_try_mutex>()();
318 test_trylock<boost::recursive_try_mutex>()();
319 test_recursive_lock<boost::recursive_try_mutex>()();
320}
321
322BOOST_AUTO_TEST_CASE(test_recursive_try_mutex)
323{
324 timed_test(func: &do_test_recursive_try_mutex, secs: 3);
325}
326
327void do_test_recursive_timed_mutex()
328{
329 test_lock<boost::recursive_timed_mutex>()();
330 test_trylock<boost::recursive_timed_mutex>()();
331 test_timedlock<boost::recursive_timed_mutex>()();
332 test_recursive_lock<boost::recursive_timed_mutex>()();
333}
334
335BOOST_AUTO_TEST_CASE(test_recursive_timed_mutex)
336{
337 timed_test(func: &do_test_recursive_timed_mutex, secs: 3);
338}
339
340
341
342

source code of boost/libs/thread/test/test_mutex.cpp