test_lock_concept.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 572 行
CPP
572 行
// (C) Copyright 2006-8 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 <boost/test/unit_test.hpp>#include <boost/test/test_case_template.hpp>#include <boost/mpl/vector.hpp>#include <boost/thread/mutex.hpp>#include <boost/thread/shared_mutex.hpp>#include <boost/thread/thread.hpp>#include <boost/thread/recursive_mutex.hpp>#include <boost/thread/condition_variable.hpp>template<typename Mutex,typename Lock>struct test_initially_locked{ void operator()() const { Mutex m; Lock lock(m); BOOST_CHECK(lock); BOOST_CHECK(lock.owns_lock()); }};template<typename Mutex,typename Lock>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<boost::mutex> 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<Mutex,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<typename Mutex,typename Lock>struct test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock{ Mutex m; boost::mutex done_mutex; bool done; bool locked; boost::condition_variable done_cond; test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock(): done(false),locked(false) {} void locking_thread() { Lock lock(m,boost::try_to_lock); boost::lock_guard<boost::mutex> lk(done_mutex); locked=lock.owns_lock(); done=true; done_cond.notify_one(); } bool is_done() const { return done; } void operator()() { boost::unique_lock<Mutex> lock(m); typedef test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,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<typename Mutex,typename Lock>struct test_initially_locked_if_other_thread_has_shared_lock{ Mutex m; boost::mutex done_mutex; bool done; bool locked; boost::condition_variable done_cond; test_initially_locked_if_other_thread_has_shared_lock(): done(false),locked(false) {} void locking_thread() { Lock lock(m); boost::lock_guard<boost::mutex> lk(done_mutex); locked=lock.owns_lock(); done=true; done_cond.notify_one(); } bool is_done() const { return done; } void operator()() { boost::shared_lock<Mutex> lock(m); typedef test_initially_locked_if_other_thread_has_shared_lock<Mutex,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<typename Mutex,typename Lock>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<typename Mutex,typename Lock>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<typename Mutex,typename Lock>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<typename Mutex,typename Lock>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<typename Mutex,typename Lock>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<typename Mutex,typename Lock>struct test_unlocked_after_try_lock_if_other_thread_has_lock{ Mutex m; boost::mutex done_mutex; bool done; bool locked; boost::condition_variable done_cond; test_unlocked_after_try_lock_if_other_thread_has_lock(): done(false),locked(false) {} void locking_thread() { Lock lock(m,boost::defer_lock); boost::lock_guard<boost::mutex> 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_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,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<typename Mutex,typename Lock>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<typename Mutex,typename Lock>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<typename Mutex,typename Lock>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<typename Lock>struct test_default_constructed_has_no_mutex_and_unlocked{ void operator()() const { Lock l; BOOST_CHECK(!l.mutex()); BOOST_CHECK(!l.owns_lock()); };};template<typename Mutex,typename Lock>struct test_locks_can_be_swapped{ void operator()() const { Mutex m1; Mutex m2; Mutex m3; Lock l1(m1); Lock l2(m2); BOOST_CHECK_EQUAL(l1.mutex(),&m1); BOOST_CHECK_EQUAL(l2.mutex(),&m2); l1.swap(l2); BOOST_CHECK_EQUAL(l1.mutex(),&m2); BOOST_CHECK_EQUAL(l2.mutex(),&m1); swap(l1,l2); BOOST_CHECK_EQUAL(l1.mutex(),&m1); BOOST_CHECK_EQUAL(l2.mutex(),&m2); l1.swap(Lock(m3)); BOOST_CHECK_EQUAL(l1.mutex(),&m3); }};template<typename Mutex,typename Lock>void test_lock_is_scoped_lock_concept_for_mutex(){ test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); test_initially_locked<Mutex,Lock>()(); test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()(); test_unlocked_after_unlock_called<Mutex,Lock>()(); test_locked_after_lock_called<Mutex,Lock>()(); test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); test_locks_can_be_swapped<Mutex,Lock>()(); test_locked_after_try_lock_called<Mutex,Lock>()(); test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()();}BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex){ typedef typename Mutex::scoped_lock Lock; test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();}BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_unique_lock_is_scoped_lock,Mutex){ typedef boost::unique_lock<Mutex> Lock; test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>();}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<Lock>()(); test_initially_locked<Mutex,Lock>()(); test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock>()(); test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()(); test_unlocked_after_unlock_called<Mutex,Lock>()(); test_locked_after_lock_called<Mutex,Lock>()(); test_locked_after_try_lock_called<Mutex,Lock>()(); test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()(); test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); test_locks_can_be_swapped<Mutex,Lock>()();}struct dummy_shared_mutex{ bool locked; bool shared_locked; bool shared_unlocked; bool shared_timed_locked_relative; bool shared_timed_locked_absolute; bool timed_locked_relative; bool timed_locked_absolute; dummy_shared_mutex(): locked(false),shared_locked(false),shared_unlocked(false), shared_timed_locked_relative(false), shared_timed_locked_absolute(false), timed_locked_relative(false), timed_locked_absolute(false) {} void lock() { locked=true; } void lock_shared() { shared_locked=true; } void unlock() {} void unlock_shared() { shared_unlocked=true; } bool timed_lock_shared(boost::system_time) { shared_timed_locked_absolute=true; return false; } template<typename Duration> bool timed_lock_shared(Duration) { shared_timed_locked_relative=true; return false; } bool timed_lock(boost::system_time) { timed_locked_absolute=true; return false; } template<typename Duration> bool timed_lock(Duration) { timed_locked_relative=true; return false; } };void test_shared_lock(){ typedef boost::shared_mutex Mutex; typedef boost::shared_lock<Mutex> Lock; test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); test_initially_locked<Mutex,Lock>()(); test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock>()(); test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock>()(); test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()(); test_unlocked_after_unlock_called<Mutex,Lock>()(); test_locked_after_lock_called<Mutex,Lock>()(); test_locked_after_try_lock_called<Mutex,Lock>()(); test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); test_locks_can_be_swapped<Mutex,Lock>()(); dummy_shared_mutex dummy; boost::shared_lock<dummy_shared_mutex> lk(dummy); BOOST_CHECK(dummy.shared_locked); lk.unlock(); BOOST_CHECK(dummy.shared_unlocked); lk.timed_lock(boost::posix_time::milliseconds(5)); BOOST_CHECK(dummy.shared_timed_locked_relative); lk.timed_lock(boost::get_system_time()); BOOST_CHECK(dummy.shared_timed_locked_absolute);}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<boost::mutex,boost::try_mutex,boost::timed_mutex, boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock; test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock)); typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex, boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock; test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock)); typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex, boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types; test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types)); test->add(BOOST_TEST_CASE(&test_shared_lock)); return test;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?