$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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;
+}