1 // (C) Copyright 2006-8 Anthony Williams
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 #define BOOST_THREAD_VERSION 2
7 #define BOOST_TEST_MODULE Boost.Threads: lock_concept test suite
9 #include <boost/test/unit_test.hpp>
10 #include <boost/test/test_case_template.hpp>
11 #include <boost/mpl/vector.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <boost/thread/lock_types.hpp>
14 #include <boost/thread/shared_mutex.hpp>
15 #include <boost/thread/thread_only.hpp>
16 #include <boost/thread/recursive_mutex.hpp>
17 #include <boost/thread/condition_variable.hpp>
19 template<typename Mutex
,typename Lock
>
20 struct test_initially_locked
22 void operator()() const
28 BOOST_CHECK(lock
.owns_lock());
32 template<typename Mutex
,typename Lock
>
33 struct test_initially_unlocked_if_other_thread_has_lock
36 boost::mutex done_mutex
;
39 boost::condition_variable done_cond
;
41 test_initially_unlocked_if_other_thread_has_lock():
42 done(false),locked(false)
49 boost::lock_guard
<boost::mutex
> lk(done_mutex
);
50 locked
=lock
.owns_lock();
52 done_cond
.notify_one();
65 typedef test_initially_unlocked_if_other_thread_has_lock
<Mutex
,Lock
> this_type
;
67 boost::thread
t(&this_type::locking_thread
,this);
72 boost::unique_lock
<boost::mutex
> lk(done_mutex
);
73 BOOST_CHECK(done_cond
.timed_wait(lk
,boost::posix_time::seconds(2),
74 boost::bind(&this_type::is_done
,this)));
90 template<typename Mutex
,typename Lock
>
91 struct test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock
94 boost::mutex done_mutex
;
97 boost::condition_variable done_cond
;
99 test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock():
100 done(false),locked(false)
103 void locking_thread()
105 Lock
lock(m
,boost::try_to_lock
);
107 boost::lock_guard
<boost::mutex
> lk(done_mutex
);
108 locked
=lock
.owns_lock();
110 done_cond
.notify_one();
121 boost::unique_lock
<Mutex
> lock(m
);
123 typedef test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock
<Mutex
,Lock
> this_type
;
125 boost::thread
t(&this_type::locking_thread
,this);
130 boost::unique_lock
<boost::mutex
> lk(done_mutex
);
131 BOOST_CHECK(done_cond
.timed_wait(lk
,boost::posix_time::seconds(2),
132 boost::bind(&this_type::is_done
,this)));
133 BOOST_CHECK(!locked
);
148 template<typename Mutex
,typename Lock
>
149 struct test_initially_locked_if_other_thread_has_shared_lock
152 boost::mutex done_mutex
;
155 boost::condition_variable done_cond
;
157 test_initially_locked_if_other_thread_has_shared_lock():
158 done(false),locked(false)
161 void locking_thread()
165 boost::lock_guard
<boost::mutex
> lk(done_mutex
);
166 locked
=lock
.owns_lock();
168 done_cond
.notify_one();
179 boost::shared_lock
<Mutex
> lock(m
);
181 typedef test_initially_locked_if_other_thread_has_shared_lock
<Mutex
,Lock
> this_type
;
183 boost::thread
t(&this_type::locking_thread
,this);
188 boost::unique_lock
<boost::mutex
> lk(done_mutex
);
189 BOOST_CHECK(done_cond
.timed_wait(lk
,boost::posix_time::seconds(2),
190 boost::bind(&this_type::is_done
,this)));
206 template<typename Mutex
,typename Lock
>
207 struct test_initially_unlocked_with_defer_lock_parameter
209 void operator()() const
212 Lock
lock(m
,boost::defer_lock
);
215 BOOST_CHECK(!lock
.owns_lock());
219 template<typename Mutex
,typename Lock
>
220 struct test_initially_locked_with_adopt_lock_parameter
222 void operator()() const
226 Lock
lock(m
,boost::adopt_lock
);
229 BOOST_CHECK(lock
.owns_lock());
232 template<typename Mutex
,typename Lock
>
233 struct test_initially_lock_shared_with_adopt_lock_parameter
235 void operator()() const
239 Lock
lock(m
,boost::adopt_lock
);
242 BOOST_CHECK(lock
.owns_lock());
247 template<typename Mutex
,typename Lock
>
248 struct test_unlocked_after_unlock_called
250 void operator()() const
256 BOOST_CHECK(!lock
.owns_lock());
260 template<typename Mutex
,typename Lock
>
261 struct test_locked_after_lock_called
263 void operator()() const
266 Lock
lock(m
,boost::defer_lock
);
269 BOOST_CHECK(lock
.owns_lock());
273 template<typename Mutex
,typename Lock
>
274 struct test_locked_after_try_lock_called
276 void operator()() const
279 Lock
lock(m
,boost::defer_lock
);
282 BOOST_CHECK(lock
.owns_lock());
286 template<typename Mutex
,typename Lock
>
287 struct test_unlocked_after_try_lock_if_other_thread_has_lock
290 boost::mutex done_mutex
;
293 boost::condition_variable done_cond
;
295 test_unlocked_after_try_lock_if_other_thread_has_lock():
296 done(false),locked(false)
299 void locking_thread()
301 Lock
lock(m
,boost::defer_lock
);
303 boost::lock_guard
<boost::mutex
> lk(done_mutex
);
304 locked
=lock
.owns_lock();
306 done_cond
.notify_one();
319 typedef test_unlocked_after_try_lock_if_other_thread_has_lock
<Mutex
,Lock
> this_type
;
321 boost::thread
t(&this_type::locking_thread
,this);
326 boost::unique_lock
<boost::mutex
> lk(done_mutex
);
327 BOOST_CHECK(done_cond
.timed_wait(lk
,boost::posix_time::seconds(2),
328 boost::bind(&this_type::is_done
,this)));
329 BOOST_CHECK(!locked
);
344 template<typename Mutex
,typename Lock
>
345 struct test_throws_if_lock_called_when_already_locked
347 void operator()() const
352 BOOST_CHECK_THROW( lock
.lock(), boost::lock_error
);
356 template<typename Mutex
,typename Lock
>
357 struct test_throws_if_try_lock_called_when_already_locked
359 void operator()() const
364 BOOST_CHECK_THROW( lock
.try_lock(), boost::lock_error
);
368 template<typename Mutex
,typename Lock
>
369 struct test_throws_if_unlock_called_when_already_unlocked
371 void operator()() const
377 BOOST_CHECK_THROW( lock
.unlock(), boost::lock_error
);
380 template<typename Lock
>
381 struct test_default_constructed_has_no_mutex_and_unlocked
383 void operator()() const
386 BOOST_CHECK(!l
.mutex());
387 BOOST_CHECK(!l
.owns_lock());
392 template<typename Mutex
,typename Lock
>
393 struct test_locks_can_be_swapped
395 void operator()() const
404 BOOST_CHECK_EQUAL(l1
.mutex(),&m1
);
405 BOOST_CHECK_EQUAL(l2
.mutex(),&m2
);
409 BOOST_CHECK_EQUAL(l1
.mutex(),&m2
);
410 BOOST_CHECK_EQUAL(l2
.mutex(),&m1
);
414 BOOST_CHECK_EQUAL(l1
.mutex(),&m1
);
415 BOOST_CHECK_EQUAL(l2
.mutex(),&m2
);
420 BOOST_CHECK_EQUAL(l1
.mutex(),&m3
);
426 template<typename Mutex
,typename Lock
>
427 void test_lock_is_scoped_lock_concept_for_mutex()
429 test_default_constructed_has_no_mutex_and_unlocked
<Lock
>()();
430 test_initially_locked
<Mutex
,Lock
>()();
431 test_initially_unlocked_with_defer_lock_parameter
<Mutex
,Lock
>()();
432 test_initially_locked_with_adopt_lock_parameter
<Mutex
,Lock
>()();
433 test_unlocked_after_unlock_called
<Mutex
,Lock
>()();
434 test_locked_after_lock_called
<Mutex
,Lock
>()();
435 test_throws_if_lock_called_when_already_locked
<Mutex
,Lock
>()();
436 test_throws_if_unlock_called_when_already_unlocked
<Mutex
,Lock
>()();
437 test_locks_can_be_swapped
<Mutex
,Lock
>()();
438 test_locked_after_try_lock_called
<Mutex
,Lock
>()();
439 test_throws_if_try_lock_called_when_already_locked
<Mutex
,Lock
>()();
440 test_unlocked_after_try_lock_if_other_thread_has_lock
<Mutex
,Lock
>()();
443 typedef boost::mpl::vector
<boost::mutex
,boost::timed_mutex
,
444 boost::recursive_mutex
,boost::recursive_timed_mutex
> mutex_types_with_scoped_lock
;
446 BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_lock_concept
,Mutex
,mutex_types_with_scoped_lock
)
448 typedef typename
Mutex::scoped_lock Lock
;
450 test_lock_is_scoped_lock_concept_for_mutex
<Mutex
,Lock
>();
453 typedef boost::mpl::vector
<boost::mutex
,boost::timed_mutex
,
454 boost::recursive_mutex
,boost::recursive_timed_mutex
,boost::shared_mutex
> all_mutex_types
;
456 BOOST_AUTO_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock
,Mutex
,all_mutex_types
)
458 typedef boost::unique_lock
<Mutex
> Lock
;
460 test_lock_is_scoped_lock_concept_for_mutex
<Mutex
,Lock
>();
463 typedef boost::mpl::vector
<boost::try_mutex
,boost::timed_mutex
,
464 boost::recursive_try_mutex
,boost::recursive_timed_mutex
> mutex_types_with_scoped_try_lock
;
466 BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept
,Mutex
,mutex_types_with_scoped_try_lock
)
468 typedef typename
Mutex::scoped_try_lock Lock
;
470 test_default_constructed_has_no_mutex_and_unlocked
<Lock
>()();
471 test_initially_locked
<Mutex
,Lock
>()();
472 test_initially_unlocked_if_other_thread_has_lock
<Mutex
,Lock
>()();
473 test_initially_unlocked_with_defer_lock_parameter
<Mutex
,Lock
>()();
474 test_initially_locked_with_adopt_lock_parameter
<Mutex
,Lock
>()();
475 test_unlocked_after_unlock_called
<Mutex
,Lock
>()();
476 test_locked_after_lock_called
<Mutex
,Lock
>()();
477 test_locked_after_try_lock_called
<Mutex
,Lock
>()();
478 test_unlocked_after_try_lock_if_other_thread_has_lock
<Mutex
,Lock
>()();
479 test_throws_if_lock_called_when_already_locked
<Mutex
,Lock
>()();
480 test_throws_if_try_lock_called_when_already_locked
<Mutex
,Lock
>()();
481 test_throws_if_unlock_called_when_already_unlocked
<Mutex
,Lock
>()();
482 test_locks_can_be_swapped
<Mutex
,Lock
>()();
485 struct dummy_shared_mutex
489 bool shared_unlocked
;
490 bool shared_timed_locked_relative
;
491 bool shared_timed_locked_absolute
;
492 bool timed_locked_relative
;
493 bool timed_locked_absolute
;
495 dummy_shared_mutex():
496 locked(false),shared_locked(false),shared_unlocked(false),
497 shared_timed_locked_relative(false),
498 shared_timed_locked_absolute(false),
499 timed_locked_relative(false),
500 timed_locked_absolute(false)
518 shared_unlocked
=true;
521 bool timed_lock_shared(boost::system_time
)
523 shared_timed_locked_absolute
=true;
526 template<typename Duration
>
527 bool timed_lock_shared(Duration
)
529 shared_timed_locked_relative
=true;
532 bool timed_lock(boost::system_time
)
534 timed_locked_absolute
=true;
537 template<typename Duration
>
538 bool timed_lock(Duration
)
540 timed_locked_relative
=true;
547 BOOST_AUTO_TEST_CASE(test_shared_lock
)
549 typedef boost::shared_mutex Mutex
;
550 typedef boost::shared_lock
<Mutex
> Lock
;
552 test_default_constructed_has_no_mutex_and_unlocked
<Lock
>()();
553 test_initially_locked
<Mutex
,Lock
>()();
554 test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock
<Mutex
,Lock
>()();
555 test_initially_locked_if_other_thread_has_shared_lock
<Mutex
,Lock
>()();
556 test_initially_unlocked_with_defer_lock_parameter
<Mutex
,Lock
>()();
557 test_initially_lock_shared_with_adopt_lock_parameter
<Mutex
,Lock
>()();
558 test_unlocked_after_unlock_called
<Mutex
,Lock
>()();
559 test_locked_after_lock_called
<Mutex
,Lock
>()();
560 test_locked_after_try_lock_called
<Mutex
,Lock
>()();
561 test_throws_if_lock_called_when_already_locked
<Mutex
,Lock
>()();
562 test_throws_if_try_lock_called_when_already_locked
<Mutex
,Lock
>()();
563 test_throws_if_unlock_called_when_already_unlocked
<Mutex
,Lock
>()();
564 test_locks_can_be_swapped
<Mutex
,Lock
>()();
566 dummy_shared_mutex dummy
;
567 boost::shared_lock
<dummy_shared_mutex
> lk(dummy
);
568 BOOST_CHECK(dummy
.shared_locked
);
570 BOOST_CHECK(dummy
.shared_unlocked
);
571 lk
.timed_lock(boost::posix_time::milliseconds(5));
572 BOOST_CHECK(dummy
.shared_timed_locked_relative
);
573 lk
.timed_lock(boost::get_system_time());
574 BOOST_CHECK(dummy
.shared_timed_locked_absolute
);
577 //boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
579 // boost::unit_test::test_suite* test =
580 // BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
582 // typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
583 // boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
585 // test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
587 // typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
588 // boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
590 // test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
592 // typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
593 // boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types;
595 // test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
596 // test->add(BOOST_TEST_CASE(&test_shared_lock));