diff options
Diffstat (limited to 'src/boost/libs/signals2/test/mutex_test.cpp')
-rw-r--r-- | src/boost/libs/signals2/test/mutex_test.cpp | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/boost/libs/signals2/test/mutex_test.cpp b/src/boost/libs/signals2/test/mutex_test.cpp new file mode 100644 index 00000000..a1d2c5e2 --- /dev/null +++ b/src/boost/libs/signals2/test/mutex_test.cpp @@ -0,0 +1,289 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Copyright Frank Mori Hess 2009 +// +// Use, modification and +// distribution is subject to 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) + +// This is a simplified/modified version of libs/thread/test/test_mutex.cpp +// added to test boost::signals2::mutex. +// For more information, see http://www.boost.org + +// note boost/test/minimal.hpp can cause windows.h to get included, which +// can screw up our checks of _WIN32_WINNT if it is included +// after boost/signals2/mutex.hpp. Frank Hess 2009-03-07. +#include <boost/test/minimal.hpp> + +#include <boost/bind.hpp> +#include <boost/signals2/dummy_mutex.hpp> +#include <boost/signals2/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/thread_time.hpp> +#include <boost/thread/condition.hpp> + +class execution_monitor +{ +public: + execution_monitor(int secs) + : done(false), m_secs(secs) { } + void start() + { + boost::mutex::scoped_lock lock(mutex); + done = false; + } + void finish() + { + boost::mutex::scoped_lock lock(mutex); + done = true; + cond.notify_one(); + } + bool wait() + { + boost::posix_time::time_duration timeout = boost::posix_time::seconds(m_secs); + boost::mutex::scoped_lock lock(mutex); + while (!done) { + if (!cond.timed_wait(lock, timeout)) + break; + } + return done; + } + +private: + boost::mutex mutex; + boost::condition cond; + bool done; + int m_secs; +}; + +template <typename F> +class indirect_adapter +{ +public: + indirect_adapter(F func, execution_monitor& monitor) + : m_func(func), m_monitor(monitor) { } + void operator()() const + { + try + { + boost::thread thrd(m_func); + thrd.join(); + } + catch (...) + { + m_monitor.finish(); + throw; + } + m_monitor.finish(); + } + +private: + F m_func; + execution_monitor& m_monitor; + void operator=(indirect_adapter&); +}; + +template <typename F> +void timed_test(F func, int secs) +{ + execution_monitor monitor(secs); + indirect_adapter<F> ifunc(func, monitor); + monitor.start(); + boost::thread thrd(ifunc); + BOOST_REQUIRE(monitor.wait()); // Timed test didn't complete in time, possible deadlock +} + +template <typename M> +struct test_lock +{ + typedef M mutex_type; + typedef typename boost::unique_lock<M> lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + + // Construct a fast time out. + boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, timeout)); + BOOST_CHECK(lock ? true : false); + + // Test the lock and unlock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + } +}; + +template <typename M> +struct test_trylock +{ + typedef M mutex_type; + typedef typename boost::unique_lock<M> lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + lock_type lock(mutex, boost::try_to_lock); + BOOST_CHECK(lock ? true : false); + } + { + lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + lock_type lock(mutex, boost::try_to_lock); + BOOST_CHECK(lock ? true : false); + + // Construct a fast time out. + boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, timeout)); + BOOST_CHECK(lock ? true : false); + + // Test the lock, unlock and trylock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + BOOST_CHECK(lock.try_lock()); + BOOST_CHECK(lock ? true : false); + } +}; + +template<typename Mutex> +struct test_lock_exclusion +{ + typedef boost::unique_lock<Mutex> Lock; + + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_lock_exclusion(): + 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; + } + + typedef test_lock_exclusion<Mutex> this_type; + + void do_test(void (this_type::*test_func)()) + { + Lock lock(m); + + { + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=false; + } + + done=false; + + boost::thread t(test_func,this); + + try + { + { + boost::mutex::scoped_lock lk(done_mutex); + BOOST_CHECK(!done_cond.timed_wait(lk, boost::posix_time::seconds(1), + boost::bind(&this_type::is_done,this))); + } + lock.unlock(); + { + boost::mutex::scoped_lock lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk, boost::posix_time::seconds(1), + boost::bind(&this_type::is_done,this))); + } + t.join(); + BOOST_CHECK(locked); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } + + + void operator()() + { + do_test(&this_type::locking_thread); + } +}; + + +void do_test_mutex() +{ + test_lock<boost::signals2::mutex>()(); +// try_lock not supported on old versions of windows +#if !defined(BOOST_HAS_WINTHREADS) || (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)) + test_trylock<boost::signals2::mutex>()(); +#endif + test_lock_exclusion<boost::signals2::mutex>()(); +} + +void test_mutex() +{ + timed_test(&do_test_mutex, 3); +} + +void do_test_dummy_mutex() +{ + test_lock<boost::signals2::dummy_mutex>()(); + test_trylock<boost::signals2::dummy_mutex>()(); +} + +void test_dummy_mutex() +{ + timed_test(&do_test_dummy_mutex, 2); +} + +int test_main(int, char*[]) +{ + test_mutex(); + test_dummy_mutex(); + + return 0; +} |