|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r50565 - sandbox/thread_safe_signals/trunk/libs/signals2/test
From: fmhess_at_[hidden]
Date: 2009-01-13 14:45:02
Author: fmhess
Date: 2009-01-13 14:45:02 EST (Tue, 13 Jan 2009)
New Revision: 50565
URL: http://svn.boost.org/trac/boost/changeset/50565
Log:
Added test program for boost::signals2::mutex, based on
libs/thread/test/test_mutex.cpp.
Added:
sandbox/thread_safe_signals/trunk/libs/signals2/test/mutex_test.cpp (contents, props changed)
Added: sandbox/thread_safe_signals/trunk/libs/signals2/test/mutex_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/test/mutex_test.cpp 2009-01-13 14:45:02 EST (Tue, 13 Jan 2009)
@@ -0,0 +1,280 @@
+// 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
+
+#include <boost/signals2/mutex.hpp>
+#include <boost/test/minimal.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:
+ enum wait_type { use_sleep_only, use_mutex, use_condition };
+
+ execution_monitor(wait_type type, int secs)
+ : done(false), type(type), secs(secs) { }
+ void start()
+ {
+ if (type != use_sleep_only) {
+ boost::mutex::scoped_lock lock(mutex); done = false;
+ } else {
+ done = false;
+ }
+ }
+ void finish()
+ {
+ if (type != use_sleep_only) {
+ boost::mutex::scoped_lock lock(mutex);
+ done = true;
+ if (type == use_condition)
+ cond.notify_one();
+ } else {
+ done = true;
+ }
+ }
+ bool wait()
+ {
+ boost::posix_time::time_duration timeout = boost::posix_time::seconds(secs);
+ if (type != use_condition)
+ boost::this_thread::sleep(timeout);
+ if (type != use_sleep_only) {
+ boost::mutex::scoped_lock lock(mutex);
+ while (type == use_condition && !done) {
+ if (!cond.timed_wait(lock, timeout))
+ break;
+ }
+ return done;
+ }
+ return done;
+ }
+
+private:
+ boost::mutex mutex;
+ boost::condition cond;
+ bool done;
+ wait_type type;
+ int secs;
+};
+
+template <typename F>
+class indirect_adapter
+{
+public:
+ indirect_adapter(F func, execution_monitor& monitor)
+ : func(func), monitor(monitor) { }
+ void operator()() const
+ {
+ try
+ {
+ boost::thread thrd(func);
+ thrd.join();
+ }
+ catch (...)
+ {
+ monitor.finish();
+ throw;
+ }
+ monitor.finish();
+ }
+
+private:
+ F func;
+ execution_monitor& monitor;
+ void operator=(indirect_adapter&);
+};
+
+template <typename F>
+void timed_test(F func, int secs,
+ execution_monitor::wait_type type = execution_monitor::use_sleep_only)
+{
+ execution_monitor monitor(type, 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);
+
+ 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();
+ 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);
+}
+
+int test_main(int, char*[])
+{
+ test_mutex();
+
+ return 0;
+}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk