// (C) Copyright 2006-7 Anthony Williams // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include template struct test_initially_locked { void operator()() const { Mutex m; Lock lock(m); BOOST_CHECK(lock); BOOST_CHECK(lock.owns_lock()); } }; template struct test_initially_unlocked_if_other_thread_has_lock { Mutex m; boost::mutex done_mutex; bool done; bool locked; boost::condition_variable done_cond; test_initially_unlocked_if_other_thread_has_lock(): done(false),locked(false) {} void locking_thread() { Lock lock(m); boost::lock_guard lk(done_mutex); locked=lock.owns_lock(); done=true; done_cond.notify_one(); } bool is_done() const { return done; } void operator()() { Lock lock(m); typedef test_initially_unlocked_if_other_thread_has_lock this_type; boost::thread t(&this_type::locking_thread,this); try { { boost::mutex::scoped_lock lk(done_mutex); BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), boost::bind(&this_type::is_done,this))); BOOST_CHECK(!locked); } lock.unlock(); t.join(); } catch(...) { lock.unlock(); t.join(); throw; } } }; template struct test_initially_unlocked_with_defer_lock_parameter { void operator()() const { Mutex m; Lock lock(m,boost::defer_lock); BOOST_CHECK(!lock); BOOST_CHECK(!lock.owns_lock()); } }; template struct test_initially_locked_with_adopt_lock_parameter { void operator()() const { Mutex m; m.lock(); Lock lock(m,boost::adopt_lock); BOOST_CHECK(lock); BOOST_CHECK(lock.owns_lock()); } }; template struct test_unlocked_after_unlock_called { void operator()() const { Mutex m; Lock lock(m); lock.unlock(); BOOST_CHECK(!lock); BOOST_CHECK(!lock.owns_lock()); } }; template struct test_locked_after_lock_called { void operator()() const { Mutex m; Lock lock(m,boost::defer_lock); lock.lock(); BOOST_CHECK(lock); BOOST_CHECK(lock.owns_lock()); } }; template struct test_locked_after_try_lock_called { void operator()() const { Mutex m; Lock lock(m,boost::defer_lock); lock.try_lock(); BOOST_CHECK(lock); BOOST_CHECK(lock.owns_lock()); } }; template struct test_throws_if_lock_called_when_already_locked { void operator()() const { Mutex m; Lock lock(m); BOOST_CHECK_THROW( lock.lock(), boost::lock_error ); } }; template struct test_throws_if_try_lock_called_when_already_locked { void operator()() const { Mutex m; Lock lock(m); BOOST_CHECK_THROW( lock.try_lock(), boost::lock_error ); } }; template struct test_throws_if_unlock_called_when_already_unlocked { void operator()() const { Mutex m; Lock lock(m); lock.unlock(); BOOST_CHECK_THROW( lock.unlock(), boost::lock_error ); } }; template struct test_default_constructed_has_no_mutex_and_unlocked { void operator()() const { Lock l; BOOST_CHECK(!l.mutex()); BOOST_CHECK(!l.owns_lock()); }; }; BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex) { typedef typename Mutex::scoped_lock Lock; test_default_constructed_has_no_mutex_and_unlocked()(); test_initially_locked()(); test_initially_unlocked_with_defer_lock_parameter()(); test_initially_locked_with_adopt_lock_parameter()(); test_unlocked_after_unlock_called()(); test_locked_after_lock_called()(); test_throws_if_lock_called_when_already_locked()(); test_throws_if_unlock_called_when_already_unlocked()(); } BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex) { typedef typename Mutex::scoped_try_lock Lock; test_default_constructed_has_no_mutex_and_unlocked()(); test_initially_locked()(); test_initially_unlocked_if_other_thread_has_lock()(); test_initially_unlocked_with_defer_lock_parameter()(); test_initially_locked_with_adopt_lock_parameter()(); test_unlocked_after_unlock_called()(); test_locked_after_lock_called()(); test_locked_after_try_lock_called()(); test_throws_if_lock_called_when_already_locked()(); test_throws_if_try_lock_called_when_already_locked()(); test_throws_if_unlock_called_when_already_unlocked()(); } boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) { boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: lock concept test suite"); typedef boost::mpl::vector mutex_types; test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types)); typedef boost::mpl::vector try_mutex_types; test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,try_mutex_types)); return test; }