|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r57521 - in sandbox/fiber: boost/fiber libs/fiber/build libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-11-09 13:27:36
Author: olli
Date: 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
New Revision: 57521
URL: http://svn.boost.org/trac/boost/changeset/57521
Log:
- tests for sync. primitives added
Added:
sandbox/fiber/libs/fiber/test/condition_test_common.hpp (contents, props changed)
sandbox/fiber/libs/fiber/test/test_auto_reset_event.cpp (contents, props changed)
sandbox/fiber/libs/fiber/test/test_condition.cpp (contents, props changed)
sandbox/fiber/libs/fiber/test/test_count_down_event.cpp (contents, props changed)
sandbox/fiber/libs/fiber/test/test_generic_locks.cpp (contents, props changed)
sandbox/fiber/libs/fiber/test/test_manual_reset_event.cpp (contents, props changed)
sandbox/fiber/libs/fiber/test/test_unique_lock.cpp (contents, props changed)
Text files modified:
sandbox/fiber/boost/fiber/exceptions.hpp | 5 ++
sandbox/fiber/boost/fiber/scheduler.hpp | 4 ++
sandbox/fiber/libs/fiber/build/Jamfile.v2 | 2 +
sandbox/fiber/libs/fiber/src/fiber.cpp | 12 +++++-
sandbox/fiber/libs/fiber/src/scheduler.cpp | 11 ++++++
sandbox/fiber/libs/fiber/test/Jamfile.v2 | 5 ++
sandbox/fiber/libs/fiber/test/test_mutex.cpp | 68 +++++++++++++++++++++++++++++++++++++--
7 files changed, 100 insertions(+), 7 deletions(-)
Modified: sandbox/fiber/boost/fiber/exceptions.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/exceptions.hpp (original)
+++ sandbox/fiber/boost/fiber/exceptions.hpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -10,6 +10,8 @@
#include <stdexcept>
#include <string>
+#include <boost/fiber/detail/config.hpp>
+
#include <boost/config/abi_prefix.hpp>
namespace boost {
@@ -23,6 +25,9 @@
{}
};
+class fiber_interrupted
+{};
+
class invalid_stacksize : public std::runtime_error
{
public:
Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp (original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -56,9 +56,13 @@
static void exit();
+ static void failed();
+
policy * access_();
public:
+ ~scheduler();
+
template< typename Fn >
void make_fiber( Fn fn)
{
Modified: sandbox/fiber/libs/fiber/build/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/build/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/build/Jamfile.v2 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -36,6 +36,7 @@
alias fiber_sources
: ## win32 sources ##
attributes.cpp
+ auto_reset_event.cpp
condition.cpp
count_down_event.cpp
fiber.cpp
@@ -52,6 +53,7 @@
alias fiber_sources
: ## posix sources ##
attributes.cpp
+ auto_reset_event.cpp
condition.cpp
count_down_event.cpp
fiber.cpp
Modified: sandbox/fiber/libs/fiber/src/fiber.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/fiber.cpp (original)
+++ sandbox/fiber/libs/fiber/src/fiber.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -8,6 +8,7 @@
#include <boost/assert.hpp>
+#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/scheduler.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -43,8 +44,15 @@
{
BOOST_ASSERT( self);
BOOST_ASSERT( self->info_);
- self->info_->run();
- scheduler::exit();
+ try
+ {
+ self->info_->run();
+ scheduler::exit();
+ }
+ catch ( fiber_interrupted const&)
+ { scheduler::failed(); }
+ catch (...)
+ { scheduler::failed(); }
}
}}
Modified: sandbox/fiber/libs/fiber/src/scheduler.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/scheduler.cpp (original)
+++ sandbox/fiber/libs/fiber/src/scheduler.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -44,6 +44,14 @@
impl->exit_active_fiber();
}
+void
+scheduler::failed()
+{
+ policy * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->exit_active_fiber();
+}
+
policy *
scheduler::access_()
{
@@ -55,6 +63,9 @@
return impl_.get();
}
+scheduler::~scheduler()
+{ impl_.reset(); }
+
bool
scheduler::run()
{ return access_()->run(); }
Modified: sandbox/fiber/libs/fiber/test/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/test/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/test/Jamfile.v2 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -29,4 +29,9 @@
[ fiber-test test_rrp ]
[ fiber-test test_utility ]
[ fiber-test test_mutex ]
+ [ fiber-test test_auto_reset_event ]
+ [ fiber-test test_manual_reset_event ]
+ [ fiber-test test_count_down_event ]
+ [ fiber-test test_unique_lock ]
+ [ fiber-test test_condition ]
;
Added: sandbox/fiber/libs/fiber/test/condition_test_common.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/condition_test_common.hpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -0,0 +1,97 @@
+#ifndef TASK_CONDITION_TEST_COMMON_HPP
+#define TASK_CONDITION_TEST_COMMON_HPP
+// Copyright (C) 2007 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/utility.hpp>
+#include <boost/thread/thread_time.hpp>
+
+#include <boost/fiber.hpp>
+
+unsigned const timeout_seconds=5;
+
+struct wait_for_flag : private boost::noncopyable
+{
+ boost::fiber::mutex mutex;
+ boost::fiber::condition cond_var;
+ bool flag;
+ unsigned woken;
+
+ wait_for_flag():
+ flag(false),woken(0)
+ {}
+
+ struct check_flag
+ {
+ bool const& flag;
+
+ check_flag(bool const& flag_):
+ flag(flag_)
+ {}
+
+ bool operator()() const
+ {
+ return flag;
+ }
+ private:
+ void operator=(check_flag&);
+ };
+
+
+ void wait_without_predicate()
+ {
+ boost::fiber::mutex::scoped_lock lock(mutex);
+ while(!flag)
+ {
+ cond_var.wait(lock);
+ }
+ ++woken;
+ }
+
+ void wait_with_predicate()
+ {
+ boost::fiber::mutex::scoped_lock lock(mutex);
+ cond_var.wait(lock,check_flag(flag));
+ if(flag)
+ {
+ ++woken;
+ }
+ }
+
+ void timed_wait_without_predicate()
+ {
+ boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds);
+
+ boost::fiber::mutex::scoped_lock lock(mutex);
+ while(!flag)
+ {
+ if(!cond_var.timed_wait(lock,timeout))
+ {
+ return;
+ }
+ }
+ ++woken;
+ }
+
+ void timed_wait_with_predicate()
+ {
+ boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds);
+ boost::fiber::mutex::scoped_lock lock(mutex);
+ if(cond_var.timed_wait(lock,timeout,check_flag(flag)) && flag)
+ {
+ ++woken;
+ }
+ }
+ void relative_timed_wait_with_predicate()
+ {
+ boost::fiber::mutex::scoped_lock lock(mutex);
+ if(cond_var.timed_wait(lock,boost::posix_time::seconds(timeout_seconds),check_flag(flag)) && flag)
+ {
+ ++woken;
+ }
+ }
+};
+
+#endif
Added: sandbox/fiber/libs/fiber/test/test_auto_reset_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_auto_reset_event.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -0,0 +1,124 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+int value = 0;
+
+void wait_fn( boost::fiber::auto_reset_event & ev)
+{
+ ev.wait();
+ ++value;
+}
+
+// check wait
+void test_case_1()
+{
+ value = 0;
+ boost::fiber::auto_reset_event ev;
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ ev.set();
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ ev.set();
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+}
+
+void test_case_2()
+{
+ value = 0;
+ boost::fiber::auto_reset_event ev( true);
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ ev.set();
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+}
+
+void test_case_3()
+{
+ boost::fiber::auto_reset_event ev;
+
+ BOOST_CHECK_EQUAL( false, ev.try_wait() );
+
+ ev.set();
+
+ BOOST_CHECK_EQUAL( true, ev.try_wait() );
+ BOOST_CHECK_EQUAL( false, ev.try_wait() );
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: auto-reset-event test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+ test->add( BOOST_TEST_CASE( & test_case_2) );
+ test->add( BOOST_TEST_CASE( & test_case_3) );
+
+ return test;
+}
Added: sandbox/fiber/libs/fiber/test/test_condition.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_condition.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -0,0 +1,229 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+int value = 0;
+
+void notify_one_fn( boost::fiber::condition & cond)
+{
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::fiber::condition & cond)
+{
+ cond.notify_all();
+}
+
+void wait_fn(
+ boost::fiber::mutex & mtx,
+ boost::fiber::condition & cond)
+{
+ boost::fiber::mutex::scoped_lock lk( mtx);
+ cond.wait( lk);
+ ++value;
+}
+
+void test_case_1()
+{
+ value = 0;
+ boost::fiber::mutex mtx;
+ boost::fiber::condition cond;
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( mtx),
+ boost::ref( cond) );
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ sched.make_fiber(
+ notify_one_fn,
+ boost::ref( cond) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+}
+
+void test_case_2()
+{
+ value = 0;
+ boost::fiber::mutex mtx;
+ boost::fiber::condition cond;
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( mtx),
+ boost::ref( cond) );
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( mtx),
+ boost::ref( cond) );
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ sched.make_fiber(
+ notify_one_fn,
+ boost::ref( cond) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+}
+
+void test_case_3()
+{
+ value = 0;
+ boost::fiber::mutex mtx;
+ boost::fiber::condition cond;
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( mtx),
+ boost::ref( cond) );
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( mtx),
+ boost::ref( cond) );
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ sched.make_fiber(
+ notify_all_fn,
+ boost::ref( cond) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( mtx),
+ boost::ref( cond) );
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+
+ sched.make_fiber(
+ notify_all_fn,
+ boost::ref( cond) );
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 3, value);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: condition test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+ test->add( BOOST_TEST_CASE( & test_case_2) );
+ test->add( BOOST_TEST_CASE( & test_case_3) );
+
+ return test;
+}
Added: sandbox/fiber/libs/fiber/test/test_count_down_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_count_down_event.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -0,0 +1,91 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+int value = 0;
+
+void wait_fn( boost::fiber::count_down_event & ev)
+{
+ ev.wait();
+ ++value;
+}
+
+void test_case_1()
+{
+ boost::uint32_t n = 3;
+ boost::fiber::count_down_event ev( n);
+
+ BOOST_CHECK_EQUAL( ev.initial(), n);
+ BOOST_CHECK_EQUAL( ev.current(), n);
+
+ ev.set();
+ BOOST_CHECK_EQUAL( ev.initial(), n);
+ BOOST_CHECK_EQUAL( ev.current(), static_cast< boost::uint32_t >( 2) );
+
+ ev.set();
+ BOOST_CHECK_EQUAL( ev.initial(), n);
+ BOOST_CHECK_EQUAL( ev.current(), static_cast< boost::uint32_t >( 1) );
+
+ ev.set();
+ BOOST_CHECK_EQUAL( ev.initial(), n);
+ BOOST_CHECK_EQUAL( ev.current(), static_cast< boost::uint32_t >( 0) );
+
+ ev.set();
+ BOOST_CHECK_EQUAL( ev.initial(), n);
+ BOOST_CHECK_EQUAL( ev.current(), static_cast< boost::uint32_t >( 0) );
+}
+
+void test_case_2()
+{
+ value = 0;
+ boost::uint32_t n = 3;
+ boost::fiber::count_down_event ev( n);
+ boost::fiber::scheduler sched;
+
+ BOOST_CHECK_EQUAL( ev.initial(), n);
+ BOOST_CHECK_EQUAL( ev.current(), n);
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ for ( boost::uint32_t i = 0; i < n - 1; ++i)
+ {
+ ev.set();
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( value != 1);
+ }
+ ev.set();
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( ev.initial(), n);
+ BOOST_CHECK_EQUAL( ev.current(), static_cast< boost::uint32_t >( 0) );
+ BOOST_CHECK_EQUAL( 1, value);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Task: spin-count-down-event test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+ test->add( BOOST_TEST_CASE( & test_case_2) );
+
+ return test;
+}
Added: sandbox/fiber/libs/fiber/test/test_generic_locks.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_generic_locks.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -0,0 +1,524 @@
+// (C) Copyright 2008 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/thread.hpp>
+#include <boost/fiber.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+namespace tsk = boost::task;
+
+void test_lock_two_uncontended()
+{
+ boost::fiber::mutex m1,m2;
+
+ boost::fiber::mutex::scoped_lock l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock);
+
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+
+ boost::lock(l1,l2);
+
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+}
+
+struct wait_data
+{
+ boost::fiber::mutex m;
+ bool flag;
+ boost::fiber::condition cond;
+
+ wait_data():
+ flag(false)
+ {}
+
+ void wait()
+ {
+ boost::fiber::mutex::scoped_lock l(m);
+ while(!flag)
+ {
+ cond.wait(l);
+ }
+ }
+
+ template<typename Duration>
+ bool timed_wait(Duration d)
+ {
+ boost::system_time const target=boost::get_system_time()+d;
+
+ boost::fiber::mutex::scoped_lock l(m);
+ while(!flag)
+ {
+ if(!cond.timed_wait(l,target))
+ {
+ return flag;
+ }
+ }
+ return true;
+ }
+
+ void signal()
+ {
+ boost::fiber::mutex::scoped_lock l(m);
+ flag=true;
+ cond.notify_all();
+ }
+};
+
+
+void lock_mutexes_slowly(boost::fiber::mutex* m1,boost::fiber::mutex* m2,wait_data* locked,wait_data* quit)
+{
+ boost::lock_guard<boost::fiber::mutex> l1(*m1);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<boost::fiber::mutex> l2(*m2);
+ locked->signal();
+ quit->wait();
+}
+
+void lock_pair(boost::fiber::mutex* m1,boost::fiber::mutex* m2)
+{
+ boost::lock(*m1,*m2);
+ boost::fiber::mutex::scoped_lock l1(*m1,boost::adopt_lock),
+ l2(*m2,boost::adopt_lock);
+}
+
+void test_lock_two_other_thread_locks_in_order()
+{
+ boost::fiber::mutex m1,m2;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_pair,&m1,&m2);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1)));
+
+ t.join();
+}
+
+void test_lock_two_other_thread_locks_in_opposite_order()
+{
+ boost::fiber::mutex m1,m2;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_pair,&m2,&m1);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1)));
+
+ t.join();
+}
+
+void test_lock_five_uncontended()
+{
+ boost::fiber::mutex m1,m2,m3,m4,m5;
+
+ boost::fiber::mutex::scoped_lock l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock),
+ l3(m3,boost::defer_lock),
+ l4(m4,boost::defer_lock),
+ l5(m5,boost::defer_lock);
+
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ BOOST_CHECK(!l4.owns_lock());
+ BOOST_CHECK(!l5.owns_lock());
+
+ boost::lock(l1,l2,l3,l4,l5);
+
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ BOOST_CHECK(l4.owns_lock());
+ BOOST_CHECK(l5.owns_lock());
+}
+
+void lock_five_mutexes_slowly(boost::fiber::mutex* m1,boost::fiber::mutex* m2,boost::fiber::mutex* m3,boost::fiber::mutex* m4,boost::fiber::mutex* m5,
+ wait_data* locked,wait_data* quit)
+{
+ boost::lock_guard<boost::fiber::mutex> l1(*m1);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<boost::fiber::mutex> l2(*m2);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<boost::fiber::mutex> l3(*m3);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<boost::fiber::mutex> l4(*m4);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(500));
+ boost::lock_guard<boost::fiber::mutex> l5(*m5);
+ locked->signal();
+ quit->wait();
+}
+
+void lock_five(boost::fiber::mutex* m1,boost::fiber::mutex* m2,boost::fiber::mutex* m3,boost::fiber::mutex* m4,boost::fiber::mutex* m5)
+{
+ boost::lock(*m1,*m2,*m3,*m4,*m5);
+ m1->unlock();
+ m2->unlock();
+ m3->unlock();
+ m4->unlock();
+ m5->unlock();
+}
+
+void test_lock_five_other_thread_locks_in_order()
+{
+ boost::fiber::mutex m1,m2,m3,m4,m5;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_five,&m1,&m2,&m3,&m4,&m5);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));
+
+ t.join();
+}
+
+void test_lock_five_other_thread_locks_in_different_order()
+{
+ boost::fiber::mutex m1,m2,m3,m4,m5;
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_five,&m5,&m1,&m4,&m2,&m3);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));
+
+ t.join();
+}
+
+void lock_n(boost::fiber::mutex* mutexes,unsigned count)
+{
+ boost::lock(mutexes,mutexes+count);
+ for(unsigned i=0;i<count;++i)
+ {
+ mutexes[i].unlock();
+ }
+}
+
+
+void test_lock_ten_other_thread_locks_in_different_order()
+{
+ unsigned const num_mutexes=10;
+
+ boost::fiber::mutex mutexes[num_mutexes];
+ wait_data locked;
+ wait_data release;
+
+ boost::thread t(lock_five_mutexes_slowly,&mutexes[6],&mutexes[3],&mutexes[8],&mutexes[0],&mutexes[2],&locked,&release);
+ boost::this_fiber::sleep(boost::posix_time::milliseconds(10));
+
+ boost::thread t2(lock_n,mutexes,num_mutexes);
+ BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));
+
+ release.signal();
+
+ BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));
+
+ t.join();
+}
+
+struct dummy_mutex
+{
+ bool is_locked;
+
+ dummy_mutex():
+ is_locked(false)
+ {}
+
+ void lock()
+ {
+ is_locked=true;
+ }
+
+ bool try_lock()
+ {
+ if(is_locked)
+ {
+ return false;
+ }
+ is_locked=true;
+ return true;
+ }
+
+ void unlock()
+ {
+ is_locked=false;
+ }
+};
+
+namespace boost
+{
+ template<>
+ struct is_mutex_type<dummy_mutex>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+}
+
+
+
+void test_lock_five_in_range()
+{
+ unsigned const num_mutexes=5;
+ dummy_mutex mutexes[num_mutexes];
+
+ boost::lock(mutexes,mutexes+num_mutexes);
+
+ for(unsigned i=0;i<num_mutexes;++i)
+ {
+ BOOST_CHECK(mutexes[i].is_locked);
+ }
+}
+
+void test_lock_ten_in_range()
+{
+ unsigned const num_mutexes=10;
+ dummy_mutex mutexes[num_mutexes];
+
+ boost::lock(mutexes,mutexes+num_mutexes);
+
+ for(unsigned i=0;i<num_mutexes;++i)
+ {
+ BOOST_CHECK(mutexes[i].is_locked);
+ }
+}
+
+void test_try_lock_two_uncontended()
+{
+ dummy_mutex m1,m2;
+
+ int const res=boost::try_lock(m1,m2);
+
+ BOOST_CHECK(res==-1);
+ BOOST_CHECK(m1.is_locked);
+ BOOST_CHECK(m2.is_locked);
+}
+void test_try_lock_two_first_locked()
+{
+ dummy_mutex m1,m2;
+ m1.lock();
+
+ boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2);
+
+ BOOST_CHECK(res==0);
+ BOOST_CHECK(m1.is_locked);
+ BOOST_CHECK(!m2.is_locked);
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+}
+void test_try_lock_two_second_locked()
+{
+ dummy_mutex m1,m2;
+ m2.lock();
+
+ boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock),
+ l2(m2,boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2);
+
+ BOOST_CHECK(res==1);
+ BOOST_CHECK(!m1.is_locked);
+ BOOST_CHECK(m2.is_locked);
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+}
+
+void test_try_lock_three()
+{
+ int const num_mutexes=3;
+
+ for(int i=-1;i<num_mutexes;++i)
+ {
+ dummy_mutex mutexes[num_mutexes];
+
+ if(i>=0)
+ {
+ mutexes[i].lock();
+ }
+ boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),
+ l2(mutexes[1],boost::defer_lock),
+ l3(mutexes[2],boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2,l3);
+
+ BOOST_CHECK(res==i);
+ for(int j=0;j<num_mutexes;++j)
+ {
+ if((i==j) || (i==-1))
+ {
+ BOOST_CHECK(mutexes[j].is_locked);
+ }
+ else
+ {
+ BOOST_CHECK(!mutexes[j].is_locked);
+ }
+ }
+ if(i==-1)
+ {
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ }
+ else
+ {
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ }
+ }
+}
+
+void test_try_lock_four()
+{
+ int const num_mutexes=4;
+
+ for(int i=-1;i<num_mutexes;++i)
+ {
+ dummy_mutex mutexes[num_mutexes];
+
+ if(i>=0)
+ {
+ mutexes[i].lock();
+ }
+ boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),
+ l2(mutexes[1],boost::defer_lock),
+ l3(mutexes[2],boost::defer_lock),
+ l4(mutexes[3],boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2,l3,l4);
+
+ BOOST_CHECK(res==i);
+ for(int j=0;j<num_mutexes;++j)
+ {
+ if((i==j) || (i==-1))
+ {
+ BOOST_CHECK(mutexes[j].is_locked);
+ }
+ else
+ {
+ BOOST_CHECK(!mutexes[j].is_locked);
+ }
+ }
+ if(i==-1)
+ {
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ BOOST_CHECK(l4.owns_lock());
+ }
+ else
+ {
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ BOOST_CHECK(!l4.owns_lock());
+ }
+ }
+}
+
+void test_try_lock_five()
+{
+ int const num_mutexes=5;
+
+ for(int i=-1;i<num_mutexes;++i)
+ {
+ dummy_mutex mutexes[num_mutexes];
+
+ if(i>=0)
+ {
+ mutexes[i].lock();
+ }
+ boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),
+ l2(mutexes[1],boost::defer_lock),
+ l3(mutexes[2],boost::defer_lock),
+ l4(mutexes[3],boost::defer_lock),
+ l5(mutexes[4],boost::defer_lock);
+
+ int const res=boost::try_lock(l1,l2,l3,l4,l5);
+
+ BOOST_CHECK(res==i);
+ for(int j=0;j<num_mutexes;++j)
+ {
+ if((i==j) || (i==-1))
+ {
+ BOOST_CHECK(mutexes[j].is_locked);
+ }
+ else
+ {
+ BOOST_CHECK(!mutexes[j].is_locked);
+ }
+ }
+ if(i==-1)
+ {
+ BOOST_CHECK(l1.owns_lock());
+ BOOST_CHECK(l2.owns_lock());
+ BOOST_CHECK(l3.owns_lock());
+ BOOST_CHECK(l4.owns_lock());
+ BOOST_CHECK(l5.owns_lock());
+ }
+ else
+ {
+ BOOST_CHECK(!l1.owns_lock());
+ BOOST_CHECK(!l2.owns_lock());
+ BOOST_CHECK(!l3.owns_lock());
+ BOOST_CHECK(!l4.owns_lock());
+ BOOST_CHECK(!l5.owns_lock());
+ }
+ }
+}
+
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: generic locks test suite");
+
+ test->add(BOOST_TEST_CASE(&test_lock_two_uncontended));
+ test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_order));
+ test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_opposite_order));
+ test->add(BOOST_TEST_CASE(&test_lock_five_uncontended));
+ test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
+ test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
+ test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
+ test->add(BOOST_TEST_CASE(&test_lock_ten_in_range));
+ test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
+ test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
+ test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));
+ test->add(BOOST_TEST_CASE(&test_try_lock_two_second_locked));
+ test->add(BOOST_TEST_CASE(&test_try_lock_three));
+ test->add(BOOST_TEST_CASE(&test_try_lock_four));
+ test->add(BOOST_TEST_CASE(&test_try_lock_five));
+
+ return test;
+}
Added: sandbox/fiber/libs/fiber/test/test_manual_reset_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_manual_reset_event.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -0,0 +1,158 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+int value = 0;
+
+void wait_fn( boost::fiber::manual_reset_event & ev)
+{
+ ev.wait();
+ ++value;
+}
+
+void test_case_1()
+{
+ value = 0;
+ boost::fiber::manual_reset_event ev;
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ ev.set();
+
+ while ( sched.run() );
+
+ BOOST_CHECK( ! sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+}
+
+void test_case_2()
+{
+ value = 0;
+ boost::fiber::manual_reset_event ev;
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ ev.set();
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ ev.reset();
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value);
+
+ ev.set();
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( ! sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+}
+
+void test_case_3()
+{
+ value = 0;
+ boost::fiber::manual_reset_event ev( true);
+ boost::fiber::scheduler sched;
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ sched.make_fiber(
+ wait_fn,
+ boost::ref( ev) );
+
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 0, value);
+
+ while ( sched.run() );
+
+ BOOST_CHECK( ! sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 2, value);
+}
+
+void test_case_4()
+{
+ boost::fiber::manual_reset_event ev;
+
+ BOOST_CHECK_EQUAL( false, ev.try_wait() );
+
+ ev.set();
+
+ BOOST_CHECK_EQUAL( true, ev.try_wait() );
+ BOOST_CHECK_EQUAL( true, ev.try_wait() );
+
+ ev.reset();
+
+ BOOST_CHECK_EQUAL( false, ev.try_wait() );
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: manual-reset-event test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+ test->add( BOOST_TEST_CASE( & test_case_2) );
+ test->add( BOOST_TEST_CASE( & test_case_3) );
+ test->add( BOOST_TEST_CASE( & test_case_4) );
+
+ return test;
+}
Modified: sandbox/fiber/libs/fiber/test/test_mutex.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_mutex.cpp (original)
+++ sandbox/fiber/libs/fiber/test/test_mutex.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -17,13 +17,10 @@
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/test/unit_test.hpp>
-#include <boost/thread.hpp>
#include <boost/utility.hpp>
#include <boost/fiber.hpp>
-#include <libs/task/test/util.ipp>
-
template< typename M >
struct test_lock
{
@@ -65,19 +62,80 @@
test_lock< boost::fiber::mutex >()();
}
-void test_mutex()
+void test_case1()
{
boost::fiber::scheduler sched;
sched.make_fiber( & do_test_mutex);
sched.run();
}
+int value1 = 0;
+int value2 = 0;
+
+void test_fn1( boost::fiber::mutex & mtx)
+{
+ boost::fiber::mutex::scoped_lock lk( mtx);
+ ++value1;
+ for ( int i = 0; i < 3; ++i)
+ boost::this_fiber::yield();
+}
+
+void test_fn2( boost::fiber::mutex & mtx)
+{
+ boost::fiber::mutex::scoped_lock lk( mtx);
+ ++value2;
+}
+
+void test_case2()
+{
+ boost::fiber::mutex mtx;
+ boost::fiber::scheduler sched;
+ sched.make_fiber( & test_fn1, boost::ref( mtx) );
+ sched.make_fiber( & test_fn2, boost::ref( mtx) );
+
+ BOOST_CHECK_EQUAL( 0, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ BOOST_CHECK( sched.run() );
+ BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 1, value2);
+}
+
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
{
boost::unit_test_framework::test_suite * test =
BOOST_TEST_SUITE("Boost.Fiber: mutex test suite");
- test->add(BOOST_TEST_CASE(&test_mutex));
+ test->add(BOOST_TEST_CASE(&test_case1));
+ test->add(BOOST_TEST_CASE(&test_case2));
return test;
}
Added: sandbox/fiber/libs/fiber/test/test_unique_lock.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_unique_lock.cpp 2009-11-09 13:27:32 EST (Mon, 09 Nov 2009)
@@ -0,0 +1,200 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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)
+//
+// This test is based on the tests of Boost.Thread
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+struct dummy_mutex
+{
+ bool is_locked;
+
+ dummy_mutex() :
+ is_locked( false)
+ {}
+
+ void lock()
+ { is_locked = true; }
+
+ bool try_lock()
+ {
+ if ( is_locked)
+ return false;
+ is_locked = true;
+ return true;
+ }
+
+ void unlock()
+ { is_locked = false; }
+};
+
+void test_lock()
+{
+ boost::fiber::mutex mtx;
+ boost::fiber::unique_lock< boost::fiber::mutex > lk( mtx);
+
+ BOOST_CHECK( lk);
+ BOOST_CHECK( lk.owns_lock() );
+
+ lk.unlock();
+
+ BOOST_CHECK( ! lk);
+ BOOST_CHECK( ! lk.owns_lock() );
+}
+
+void test_defer_lock()
+{
+ boost::fiber::mutex mtx;
+ boost::fiber::unique_lock< boost::fiber::mutex > lk( mtx, boost::defer_lock);
+
+ BOOST_CHECK( ! lk);
+ BOOST_CHECK( ! lk.owns_lock() );
+
+ lk.lock();
+
+ BOOST_CHECK( lk);
+ BOOST_CHECK( lk.owns_lock() );
+}
+
+void test_adopt_lock()
+{
+ boost::fiber::mutex mtx;
+ mtx.lock();
+ boost::fiber::unique_lock< boost::fiber::mutex > lk( mtx, boost::adopt_lock);
+
+ BOOST_CHECK( lk);
+ BOOST_CHECK( lk.owns_lock() );
+}
+
+void test_try_lock()
+{
+ boost::fiber::mutex mtx;
+ boost::fiber::unique_lock< boost::fiber::mutex > lk( mtx, boost::defer_lock);
+
+ BOOST_CHECK( ! lk);
+ BOOST_CHECK( ! lk.owns_lock() );
+
+ lk.try_lock();
+
+ BOOST_CHECK( lk);
+ BOOST_CHECK( lk.owns_lock() );
+}
+
+void test_lock_twice()
+{
+ boost::fiber::mutex mtx;
+ boost::fiber::unique_lock< boost::fiber::mutex > lk( mtx);
+
+ BOOST_CHECK_THROW( lk.lock(), boost::fiber::lock_error);
+}
+
+void test_try_lock_twice()
+{
+ boost::fiber::mutex mtx;
+ boost::fiber::unique_lock< boost::fiber::mutex > lk( mtx);
+
+ BOOST_CHECK_THROW( lk.try_lock(), boost::fiber::lock_error);
+}
+
+void test_unlock_twice()
+{
+ boost::fiber::mutex mtx;
+ boost::fiber::unique_lock< boost::fiber::mutex > lk( mtx);
+ lk.unlock();
+
+ BOOST_CHECK_THROW( lk.unlock(), boost::fiber::lock_error);
+}
+
+void test_default_ctor()
+{
+ boost::fiber::unique_lock< boost::fiber::mutex > lk;
+
+ BOOST_CHECK( ! lk);
+ BOOST_CHECK( ! lk.owns_lock() );
+}
+
+void test_lock_concept()
+{
+ boost::fiber::mutex mtx1, mtx2, mtx3;
+
+ boost::fiber::mutex::scoped_lock lk1( mtx1, boost::defer_lock),
+ lk2( mtx2, boost::defer_lock),
+ lk3( mtx3, boost::defer_lock);
+
+ BOOST_CHECK( ! lk1.owns_lock() );
+ BOOST_CHECK( ! lk2.owns_lock() );
+ BOOST_CHECK( ! lk3.owns_lock() );
+
+ boost::lock( lk1, lk2, lk3);
+
+ BOOST_CHECK( lk1.owns_lock() );
+ BOOST_CHECK( lk2.owns_lock() );
+ BOOST_CHECK( lk3.owns_lock() );
+}
+
+void test_try_lock_concept()
+{
+ dummy_mutex mtx1, mtx2;
+ mtx2.lock();
+
+ boost::fiber::unique_lock< dummy_mutex > lk1( mtx1, boost::defer_lock),
+ lk2( mtx2, boost::defer_lock);
+
+ int res = boost::try_lock( lk1, lk2);
+
+ BOOST_CHECK( res == 1);
+ BOOST_CHECK( ! mtx1.is_locked);
+ BOOST_CHECK( mtx2.is_locked);
+ BOOST_CHECK( ! lk1.owns_lock() );
+ BOOST_CHECK( ! lk2.owns_lock() );
+}
+
+void test_swap()
+{
+ boost::fiber::mutex mtx1, mtx2;
+
+ boost::fiber::unique_lock< boost::fiber::mutex > lk1( mtx1), lk2( mtx2);
+
+ BOOST_CHECK_EQUAL( lk1.mutex(), & mtx1);
+ BOOST_CHECK_EQUAL( lk2.mutex(), & mtx2);
+
+ lk1.swap( lk2);
+
+ BOOST_CHECK_EQUAL( lk1.mutex(), & mtx2);
+ BOOST_CHECK_EQUAL( lk2.mutex(), & mtx1);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test_framework::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: lock test suite");
+
+ test->add( BOOST_TEST_CASE( & test_lock) );
+ test->add( BOOST_TEST_CASE( & test_defer_lock) );
+ test->add( BOOST_TEST_CASE( & test_adopt_lock) );
+ test->add( BOOST_TEST_CASE( & test_try_lock) );
+ test->add( BOOST_TEST_CASE( & test_lock_twice) );
+ test->add( BOOST_TEST_CASE( & test_try_lock_twice) );
+ test->add( BOOST_TEST_CASE( & test_unlock_twice) );
+ test->add( BOOST_TEST_CASE( & test_default_ctor) );
+ test->add( BOOST_TEST_CASE( & test_lock_concept) );
+ test->add( BOOST_TEST_CASE( & test_try_lock_concept) );
+ test->add( BOOST_TEST_CASE( & test_swap) );
+
+ return test;
+}
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