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
8
#include <boost/test/unit_test.hpp>
9
#include <boost/mpl/vector.hpp>
10
#include <boost/thread/mutex.hpp>
11
#include <boost/thread/lock_types.hpp>
12
#include <boost/thread/shared_mutex.hpp>
13
#include <boost/thread/thread_only.hpp>
14
#include <boost/thread/recursive_mutex.hpp>
15
#include <boost/thread/condition_variable.hpp>
17
template<typename Mutex,typename Lock>
18
struct test_initially_locked
20
void operator()() const
26
BOOST_CHECK(lock.owns_lock());
30
template<typename Mutex,typename Lock>
31
struct test_initially_unlocked_if_other_thread_has_lock
34
boost::mutex done_mutex;
37
boost::condition_variable done_cond;
39
test_initially_unlocked_if_other_thread_has_lock():
40
done(false),locked(false)
47
boost::lock_guard<boost::mutex> lk(done_mutex);
48
locked=lock.owns_lock();
50
done_cond.notify_one();
63
typedef test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock> this_type;
65
boost::thread t(&this_type::locking_thread,this);
70
boost::unique_lock<boost::mutex> lk(done_mutex);
71
BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
72
boost::bind(&this_type::is_done,this)));
88
template<typename Mutex,typename Lock>
89
struct test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock
92
boost::mutex done_mutex;
95
boost::condition_variable done_cond;
97
test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock():
98
done(false),locked(false)
101
void locking_thread()
103
Lock lock(m,boost::try_to_lock);
105
boost::lock_guard<boost::mutex> lk(done_mutex);
106
locked=lock.owns_lock();
108
done_cond.notify_one();
119
boost::unique_lock<Mutex> lock(m);
121
typedef test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock> this_type;
123
boost::thread t(&this_type::locking_thread,this);
128
boost::unique_lock<boost::mutex> lk(done_mutex);
129
BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
130
boost::bind(&this_type::is_done,this)));
131
BOOST_CHECK(!locked);
146
template<typename Mutex,typename Lock>
147
struct test_initially_locked_if_other_thread_has_shared_lock
150
boost::mutex done_mutex;
153
boost::condition_variable done_cond;
155
test_initially_locked_if_other_thread_has_shared_lock():
156
done(false),locked(false)
159
void locking_thread()
163
boost::lock_guard<boost::mutex> lk(done_mutex);
164
locked=lock.owns_lock();
166
done_cond.notify_one();
177
boost::shared_lock<Mutex> lock(m);
179
typedef test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock> this_type;
181
boost::thread t(&this_type::locking_thread,this);
186
boost::unique_lock<boost::mutex> lk(done_mutex);
187
BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
188
boost::bind(&this_type::is_done,this)));
204
template<typename Mutex,typename Lock>
205
struct test_initially_unlocked_with_defer_lock_parameter
207
void operator()() const
210
Lock lock(m,boost::defer_lock);
213
BOOST_CHECK(!lock.owns_lock());
217
template<typename Mutex,typename Lock>
218
struct test_initially_locked_with_adopt_lock_parameter
220
void operator()() const
224
Lock lock(m,boost::adopt_lock);
227
BOOST_CHECK(lock.owns_lock());
230
template<typename Mutex,typename Lock>
231
struct test_initially_lock_shared_with_adopt_lock_parameter
233
void operator()() const
237
Lock lock(m,boost::adopt_lock);
240
BOOST_CHECK(lock.owns_lock());
245
template<typename Mutex,typename Lock>
246
struct test_unlocked_after_unlock_called
248
void operator()() const
254
BOOST_CHECK(!lock.owns_lock());
258
template<typename Mutex,typename Lock>
259
struct test_locked_after_lock_called
261
void operator()() const
264
Lock lock(m,boost::defer_lock);
267
BOOST_CHECK(lock.owns_lock());
271
template<typename Mutex,typename Lock>
272
struct test_locked_after_try_lock_called
274
void operator()() const
277
Lock lock(m,boost::defer_lock);
280
BOOST_CHECK(lock.owns_lock());
284
template<typename Mutex,typename Lock>
285
struct test_unlocked_after_try_lock_if_other_thread_has_lock
288
boost::mutex done_mutex;
291
boost::condition_variable done_cond;
293
test_unlocked_after_try_lock_if_other_thread_has_lock():
294
done(false),locked(false)
297
void locking_thread()
299
Lock lock(m,boost::defer_lock);
301
boost::lock_guard<boost::mutex> lk(done_mutex);
302
locked=lock.owns_lock();
304
done_cond.notify_one();
317
typedef test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock> this_type;
319
boost::thread t(&this_type::locking_thread,this);
324
boost::unique_lock<boost::mutex> lk(done_mutex);
325
BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
326
boost::bind(&this_type::is_done,this)));
327
BOOST_CHECK(!locked);
342
template<typename Mutex,typename Lock>
343
struct test_throws_if_lock_called_when_already_locked
345
void operator()() const
350
BOOST_CHECK_THROW( lock.lock(), boost::lock_error );
354
template<typename Mutex,typename Lock>
355
struct test_throws_if_try_lock_called_when_already_locked
357
void operator()() const
362
BOOST_CHECK_THROW( lock.try_lock(), boost::lock_error );
366
template<typename Mutex,typename Lock>
367
struct test_throws_if_unlock_called_when_already_unlocked
369
void operator()() const
375
BOOST_CHECK_THROW( lock.unlock(), boost::lock_error );
378
template<typename Lock>
379
struct test_default_constructed_has_no_mutex_and_unlocked
381
void operator()() const
384
BOOST_CHECK(!l.mutex());
385
BOOST_CHECK(!l.owns_lock());
390
template<typename Mutex,typename Lock>
391
struct test_locks_can_be_swapped
393
void operator()() const
402
BOOST_CHECK_EQUAL(l1.mutex(),&m1);
403
BOOST_CHECK_EQUAL(l2.mutex(),&m2);
407
BOOST_CHECK_EQUAL(l1.mutex(),&m2);
408
BOOST_CHECK_EQUAL(l2.mutex(),&m1);
412
BOOST_CHECK_EQUAL(l1.mutex(),&m1);
413
BOOST_CHECK_EQUAL(l2.mutex(),&m2);
418
BOOST_CHECK_EQUAL(l1.mutex(),&m3);
424
template<typename Mutex,typename Lock>
425
void test_lock_is_scoped_lock_concept_for_mutex()
427
test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
428
test_initially_locked<Mutex,Lock>()();
429
test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
430
test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()();
431
test_unlocked_after_unlock_called<Mutex,Lock>()();
432
test_locked_after_lock_called<Mutex,Lock>()();
433
test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
434
test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
435
test_locks_can_be_swapped<Mutex,Lock>()();
436
test_locked_after_try_lock_called<Mutex,Lock>()();
437
test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
438
test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();
442
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex)
444
typedef typename Mutex::scoped_lock Lock;
446
test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
449
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_unique_lock_is_scoped_lock,Mutex)
451
typedef boost::unique_lock<Mutex> Lock;
453
test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();
456
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex)
458
typedef typename Mutex::scoped_try_lock Lock;
460
test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
461
test_initially_locked<Mutex,Lock>()();
462
test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock>()();
463
test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
464
test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()();
465
test_unlocked_after_unlock_called<Mutex,Lock>()();
466
test_locked_after_lock_called<Mutex,Lock>()();
467
test_locked_after_try_lock_called<Mutex,Lock>()();
468
test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();
469
test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
470
test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
471
test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
472
test_locks_can_be_swapped<Mutex,Lock>()();
475
struct dummy_shared_mutex
479
bool shared_unlocked;
480
bool shared_timed_locked_relative;
481
bool shared_timed_locked_absolute;
482
bool timed_locked_relative;
483
bool timed_locked_absolute;
485
dummy_shared_mutex():
486
locked(false),shared_locked(false),shared_unlocked(false),
487
shared_timed_locked_relative(false),
488
shared_timed_locked_absolute(false),
489
timed_locked_relative(false),
490
timed_locked_absolute(false)
508
shared_unlocked=true;
511
bool timed_lock_shared(boost::system_time)
513
shared_timed_locked_absolute=true;
516
template<typename Duration>
517
bool timed_lock_shared(Duration)
519
shared_timed_locked_relative=true;
522
bool timed_lock(boost::system_time)
524
timed_locked_absolute=true;
527
template<typename Duration>
528
bool timed_lock(Duration)
530
timed_locked_relative=true;
537
void test_shared_lock()
539
typedef boost::shared_mutex Mutex;
540
typedef boost::shared_lock<Mutex> Lock;
542
test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
543
test_initially_locked<Mutex,Lock>()();
544
test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock>()();
545
test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock>()();
546
test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
547
test_initially_lock_shared_with_adopt_lock_parameter<Mutex,Lock>()();
548
test_unlocked_after_unlock_called<Mutex,Lock>()();
549
test_locked_after_lock_called<Mutex,Lock>()();
550
test_locked_after_try_lock_called<Mutex,Lock>()();
551
test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
552
test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
553
test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
554
test_locks_can_be_swapped<Mutex,Lock>()();
556
dummy_shared_mutex dummy;
557
boost::shared_lock<dummy_shared_mutex> lk(dummy);
558
BOOST_CHECK(dummy.shared_locked);
560
BOOST_CHECK(dummy.shared_unlocked);
561
lk.timed_lock(boost::posix_time::milliseconds(5));
562
BOOST_CHECK(dummy.shared_timed_locked_relative);
563
lk.timed_lock(boost::get_system_time());
564
BOOST_CHECK(dummy.shared_timed_locked_absolute);
567
boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
569
boost::unit_test::test_suite* test =
570
BOOST_TEST_SUITE("Boost.Threads: lock concept test suite");
572
typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex,
573
boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock;
575
test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock));
577
typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex,
578
boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock;
580
test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock));
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,boost::shared_mutex> all_mutex_types;
585
test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types));
586
test->add(BOOST_TEST_CASE(&test_shared_lock));