• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
26 template <typename M>
27 struct test_lock
28 {
29     typedef M mutex_type;
30     typedef typename M::scoped_lock lock_type;
31 
operator ()test_lock32     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(0, 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 
62 template <typename M>
63 struct test_trylock
64 {
65     typedef M mutex_type;
66     typedef typename M::scoped_try_lock try_lock_type;
67 
operator ()test_trylock68     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(0, 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 
106 template<typename Mutex>
107 struct 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 
test_lock_times_out_if_other_thread_has_locktest_lock_times_out_if_other_thread_has_lock117     test_lock_times_out_if_other_thread_has_lock():
118         done(false),locked(false)
119     {}
120 
locking_threadtest_lock_times_out_if_other_thread_has_lock121     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 
locking_thread_through_constructortest_lock_times_out_if_other_thread_has_lock132     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 
is_donetest_lock_times_out_if_other_thread_has_lock142     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 
do_testtest_lock_times_out_if_other_thread_has_lock149     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 
operator ()test_lock_times_out_if_other_thread_has_lock179     void operator()()
180     {
181         do_test(&this_type::locking_thread);
182         do_test(&this_type::locking_thread_through_constructor);
183     }
184 };
185 
186 template <typename M>
187 struct test_timedlock
188 {
189     typedef M mutex_type;
190     typedef typename M::scoped_timed_lock timed_lock_type;
191 
fake_predicatetest_timedlock192     static bool fake_predicate()
193     {
194         return false;
195     }
196 
operator ()test_timedlock197     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 
256 template <typename M>
257 struct test_recursive_lock
258 {
259     typedef M mutex_type;
260     typedef typename M::scoped_lock lock_type;
261 
operator ()test_recursive_lock262     void operator()()
263     {
264         mutex_type mx;
265         lock_type lock1(mx);
266         lock_type lock2(mx);
267     }
268 };
269 
270 
do_test_mutex()271 void do_test_mutex()
272 {
273     test_lock<boost::mutex>()();
274 }
275 
BOOST_AUTO_TEST_CASE(test_mutex)276 BOOST_AUTO_TEST_CASE(test_mutex)
277 {
278     timed_test(&do_test_mutex, 3);
279 }
280 
do_test_try_mutex()281 void do_test_try_mutex()
282 {
283     test_lock<boost::try_mutex>()();
284     test_trylock<boost::try_mutex>()();
285 }
286 
BOOST_AUTO_TEST_CASE(test_try_mutex)287 BOOST_AUTO_TEST_CASE(test_try_mutex)
288 {
289     timed_test(&do_test_try_mutex, 3);
290 }
291 
do_test_timed_mutex()292 void 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 
BOOST_AUTO_TEST_CASE(test_timed_mutex)299 BOOST_AUTO_TEST_CASE(test_timed_mutex)
300 {
301     timed_test(&do_test_timed_mutex, 3);
302 }
303 
do_test_recursive_mutex()304 void do_test_recursive_mutex()
305 {
306     test_lock<boost::recursive_mutex>()();
307     test_recursive_lock<boost::recursive_mutex>()();
308 }
309 
BOOST_AUTO_TEST_CASE(test_recursive_mutex)310 BOOST_AUTO_TEST_CASE(test_recursive_mutex)
311 {
312     timed_test(&do_test_recursive_mutex, 3);
313 }
314 
do_test_recursive_try_mutex()315 void 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 
BOOST_AUTO_TEST_CASE(test_recursive_try_mutex)322 BOOST_AUTO_TEST_CASE(test_recursive_try_mutex)
323 {
324     timed_test(&do_test_recursive_try_mutex, 3);
325 }
326 
do_test_recursive_timed_mutex()327 void 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 
BOOST_AUTO_TEST_CASE(test_recursive_timed_mutex)335 BOOST_AUTO_TEST_CASE(test_recursive_timed_mutex)
336 {
337     timed_test(&do_test_recursive_timed_mutex, 3);
338 }
339 
340 
341 
342