Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58228 - in sandbox/fiber: boost boost/fiber libs/fiber/build libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-12-07 15:49:42


Author: olli
Date: 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
New Revision: 58228
URL: http://svn.boost.org/trac/boost/changeset/58228

Log:
- introduction of spinning sync. objects (spin_mutex, spin_condition, ...)
- non-spinning sync. objects (mutex, condition,...) take scheduler as argument in ctor
- tests added and adapted

Added:
   sandbox/fiber/boost/fiber/spin_auto_reset_event.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin_condition.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin_count_down_event.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin_manual_reset_event.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin_mutex.hpp (contents, props changed)
   sandbox/fiber/libs/fiber/src/spin_auto_reset_event.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/src/spin_condition.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/src/spin_count_down_event.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/src/spin_manual_reset_event.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/src/spin_mutex.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_lock.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_spin_auto_reset_event.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_spin_condition.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_spin_count_down_event.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_spin_lock.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_spin_manual_reset_event.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_spin_mutex.cpp (contents, props changed)
Text files modified:
   sandbox/fiber/boost/fiber.hpp | 5 +++
   sandbox/fiber/boost/fiber/auto_reset_event.hpp | 13 ++++++++
   sandbox/fiber/boost/fiber/condition.hpp | 13 ++++++++
   sandbox/fiber/boost/fiber/count_down_event.hpp | 11 +++++++
   sandbox/fiber/boost/fiber/manual_reset_event.hpp | 15 ++++++++++
   sandbox/fiber/boost/fiber/mutex.hpp | 10 ++++++
   sandbox/fiber/boost/fiber/round_robin.hpp | 4 +-
   sandbox/fiber/boost/fiber/scheduler.hpp | 44 +++++++++++++++++--------------
   sandbox/fiber/boost/fiber/strategy.hpp | 25 ++++++++---------
   sandbox/fiber/libs/fiber/build/Jamfile.v2 | 10 +++++++
   sandbox/fiber/libs/fiber/src/auto_reset_event.cpp | 15 ++--------
   sandbox/fiber/libs/fiber/src/condition.cpp | 18 ++----------
   sandbox/fiber/libs/fiber/src/count_down_event.cpp | 14 ++--------
   sandbox/fiber/libs/fiber/src/manual_reset_event.cpp | 17 ++----------
   sandbox/fiber/libs/fiber/src/mutex.cpp | 12 ++------
   sandbox/fiber/libs/fiber/src/round_robin.cpp | 4 +-
   sandbox/fiber/libs/fiber/src/strategy.cpp | 46 ---------------------------------
   sandbox/fiber/libs/fiber/test/Jamfile.v2 | 18 ++++++++----
   sandbox/fiber/libs/fiber/test/test_auto_reset_event.cpp | 6 ++--
   sandbox/fiber/libs/fiber/test/test_condition.cpp | 12 ++++----
   sandbox/fiber/libs/fiber/test/test_count_down_event.cpp | 4 +-
   sandbox/fiber/libs/fiber/test/test_manual_reset_event.cpp | 8 ++--
   sandbox/fiber/libs/fiber/test/test_mutex.cpp | 54 +++++++++++----------------------------
   23 files changed, 172 insertions(+), 206 deletions(-)

Modified: sandbox/fiber/boost/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber.hpp (original)
+++ sandbox/fiber/boost/fiber.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -17,6 +17,11 @@
 #include <boost/fiber/manual_reset_event.hpp>
 #include <boost/fiber/mutex.hpp>
 #include <boost/fiber/scheduler.hpp>
+#include <boost/fiber/spin_auto_reset_event.hpp>
+#include <boost/fiber/spin_condition.hpp>
+#include <boost/fiber/spin_count_down_event.hpp>
+#include <boost/fiber/spin_manual_reset_event.hpp>
+#include <boost/fiber/spin_mutex.hpp>
 #include <boost/fiber/unbounded_fifo.hpp>
 #include <boost/fiber/utility.hpp>
 

Modified: sandbox/fiber/boost/fiber/auto_reset_event.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/auto_reset_event.hpp (original)
+++ sandbox/fiber/boost/fiber/auto_reset_event.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -11,6 +11,8 @@
 #include <boost/utility.hpp>
 
 #include <boost/fiber/object/id.hpp>
+#include <boost/fiber/scheduler.hpp>
+#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
@@ -26,9 +28,18 @@
 
         volatile uint32_t state_;
         object::id id_;
+ strategy::ptr_t strategy_;
 
 public:
- explicit auto_reset_event( bool = false);
+ template< typename Strategy >
+ auto_reset_event( scheduler< Strategy > & sched, bool isset = false) :
+ state_(
+ isset ?
+ static_cast< uint32_t >( SET) :
+ static_cast< uint32_t >( RESET) ),
+ id_( * this),
+ strategy_( sched.strategy_)
+ { strategy_->register_object( id_); }
 
         ~auto_reset_event();
 

Modified: sandbox/fiber/boost/fiber/condition.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/condition.hpp (original)
+++ sandbox/fiber/boost/fiber/condition.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -15,6 +15,8 @@
 #include <boost/fiber/object/id.hpp>
 #include <boost/fiber/exceptions.hpp>
 #include <boost/fiber/mutex.hpp>
+#include <boost/fiber/scheduler.hpp>
+#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
@@ -34,11 +36,20 @@
         mutex enter_mtx_;
         mutex check_mtx_;
         object::id id_;
+ strategy::ptr_t strategy_;
 
         void wait_( mutex &);
 
 public:
- condition();
+ template< typename Strategy >
+ condition( scheduler< Strategy > & sched) :
+ cmd_( static_cast< uint32_t >( SLEEPING) ),
+ waiters_( 0),
+ enter_mtx_( sched),
+ check_mtx_( sched),
+ id_( * this),
+ strategy_( sched.strategy_)
+ { strategy_->register_object( id_); }
 
         ~condition();
 

Modified: sandbox/fiber/boost/fiber/count_down_event.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/count_down_event.hpp (original)
+++ sandbox/fiber/boost/fiber/count_down_event.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -12,6 +12,8 @@
 
 #include <boost/fiber/object/id.hpp>
 #include <boost/fiber/mutex.hpp>
+#include <boost/fiber/scheduler.hpp>
+#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
@@ -22,9 +24,16 @@
         uint32_t initial_;
         volatile uint32_t current_;
         object::id id_;
+ strategy::ptr_t strategy_;
 
 public:
- explicit count_down_event( uint32_t);
+ template< typename Strategy >
+ count_down_event( scheduler< Strategy > & sched, uint32_t initial) :
+ initial_( initial),
+ current_( initial_),
+ id_( * this),
+ strategy_( sched.strategy_)
+ { strategy_->register_object( id_); }
 
         ~count_down_event();
 

Modified: sandbox/fiber/boost/fiber/manual_reset_event.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/manual_reset_event.hpp (original)
+++ sandbox/fiber/boost/fiber/manual_reset_event.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -12,6 +12,8 @@
 
 #include <boost/fiber/object/id.hpp>
 #include <boost/fiber/mutex.hpp>
+#include <boost/fiber/scheduler.hpp>
+#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
@@ -29,9 +31,20 @@
         volatile uint32_t waiters_;
         mutex enter_mtx_;
         object::id id_;
+ strategy::ptr_t strategy_;
 
 public:
- explicit manual_reset_event( bool = false);
+ template< typename Strategy >
+ manual_reset_event( scheduler< Strategy > & sched, bool isset = false) :
+ state_(
+ isset ?
+ static_cast< uint32_t >( SET) :
+ static_cast< uint32_t >( RESET) ),
+ waiters_( 0),
+ enter_mtx_( sched),
+ id_( * this),
+ strategy_( sched.strategy_)
+ { strategy_->register_object( id_); }
 
         ~manual_reset_event();
 

Modified: sandbox/fiber/boost/fiber/mutex.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/mutex.hpp (original)
+++ sandbox/fiber/boost/fiber/mutex.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -14,6 +14,8 @@
 #include <boost/utility.hpp>
 
 #include <boost/fiber/object/id.hpp>
+#include <boost/fiber/scheduler.hpp>
+#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
@@ -23,11 +25,17 @@
 private:
         volatile uint32_t state_;
         object::id id_;
+ strategy::ptr_t strategy_;
 
 public:
         typedef unique_lock< mutex > scoped_lock;
 
- mutex();
+ template< typename Strategy >
+ mutex( scheduler< Strategy > & sched) :
+ state_( 0),
+ id_( * this),
+ strategy_( sched.strategy_)
+ { strategy_->register_object( id_); }
 
         ~mutex();
 

Modified: sandbox/fiber/boost/fiber/round_robin.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/round_robin.hpp (original)
+++ sandbox/fiber/boost/fiber/round_robin.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -53,16 +53,16 @@
                 {}
         };
 
- typedef std::map< fiber::id, schedulable > fiber_map;
         typedef std::list< fiber::id > fiber_id_list;
         typedef std::map< object::id, fiber_id_list > object_map;
+ typedef std::map< fiber::id, schedulable > fiber_map;
         typedef std::list< fiber::id > runnable_queue;
         typedef std::queue< fiber::id > terminated_queue;
 
         fiber_map fibers_;
+ object_map objects_;
         runnable_queue runnable_fibers_;
         terminated_queue terminated_fibers_;
- object_map objects_;
 
 public:
         round_robin();

Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp (original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -11,7 +11,7 @@
 #include <memory>
 
 #include <boost/preprocessor/repetition.hpp>
-#include <boost/thread/tss.hpp>
+#include <boost/intrusive_ptr.hpp>
 #include <boost/utility.hpp>
 
 #include <boost/fiber/detail/config.hpp>
@@ -29,49 +29,53 @@
 namespace boost {
 namespace fibers {
 
+class auto_reset_event;
+class condition;
+class count_down_event;
+class manual_reset_event;
+class mutex;
+
 template< typename Strategy = round_robin >
 class BOOST_FIBER_DECL scheduler : private noncopyable
 {
 private:
+ friend class auto_reset_event;
+ friend class condition;
+ friend class count_down_event;
+ friend class manual_reset_event;
+ friend class mutex;
 
- typedef thread_specific_ptr< strategy > impl_t;
-
- impl_t impl_;
+ typedef intrusive_ptr< strategy > strategy_t;
 
- strategy * access_()
- {
- if ( ! impl_.get() )
- impl_.reset( new Strategy() );
- return impl_.get();
- }
+ strategy_t strategy_;
 
 public:
         scheduler() :
- impl_()
+ strategy_( new Strategy() )
         {}
 
         ~scheduler()
- { impl_.reset(); }
+ {}
 
         bool run()
- { return access_()->run(); }
+ { return strategy_->run(); }
 
         bool empty()
- { return access_()->empty(); }
+ { return strategy_->empty(); }
 
         std::size_t size()
- { return access_()->size(); }
+ { return strategy_->size(); }
 
         void submit_fiber( fiber f)
- { access_()->add( f); }
+ { strategy_->add( f); }
 
         template< typename Fn >
         void make_fiber( Fn fn)
- { access_()->add( fiber( fn) ); }
+ { strategy_->add( fiber( fn) ); }
 
         template< typename Fn >
         void make_fiber( std::size_t stack_size, Fn fn)
- { access_()->add( fiber( stack_size, fn) ); }
+ { strategy_->add( fiber( stack_size, fn) ); }
 
 #ifndef BOOST_FIBER_MAX_ARITY
 #define BOOST_FIBER_MAX_ARITY 10
@@ -84,10 +88,10 @@
 #define BOOST_FIBER_MAKE_FIBER_FUNCTION(z, n, unused) \
         template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
         void make_fiber( Fn fn, BOOST_ENUM_FIBER_ARGS(n)) \
- { access_()->add( fiber( fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); } \
+ { strategy_->add( fiber( fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); } \
         template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
         void make_fiber( std::size_t stack_size, Fn fn, BOOST_ENUM_FIBER_ARGS(n)) \
- { access_()->add( fiber( stack_size, fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); }
+ { strategy_->add( fiber( stack_size, fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); }
 
 BOOST_PP_REPEAT_FROM_TO( 1, BOOST_FIBER_MAX_ARITY, BOOST_FIBER_MAKE_FIBER_FUNCTION, ~)
 

Added: sandbox/fiber/boost/fiber/spin_auto_reset_event.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin_auto_reset_event.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,39 @@
+
+// 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)
+
+#ifndef BOOST_FIBERS_SPIN_AUTO_RESET_EVENT_H
+#define BOOST_FIBERS_SPIN_AUTO_RESET_EVENT_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+class spin_auto_reset_event : private noncopyable
+{
+private:
+ enum state_t
+ {
+ RESET = 0,
+ SET
+ };
+
+ volatile uint32_t state_;
+
+public:
+ explicit spin_auto_reset_event( bool = false);
+
+ void set();
+
+ void wait();
+
+ bool try_wait();
+};
+
+}}
+
+#endif // BOOST_FIBERS_SPIN_AUTO_RESET_EVENT_H

Added: sandbox/fiber/boost/fiber/spin_condition.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin_condition.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,71 @@
+
+// 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)
+//
+// based on boost::interprocess::sync::interprocess_spin_condition
+
+#ifndef BOOST_FIBERS_SPIN_CONDITION_H
+#define BOOST_FIBERS_SPIN_CONDITION_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/exceptions.hpp>
+#include <boost/fiber/spin_mutex.hpp>
+
+namespace boost {
+namespace fibers {
+
+class spin_condition : private noncopyable
+{
+private:
+ enum command_t
+ {
+ SLEEPING = 0,
+ NOTIFY_ONE,
+ NOTIFY_ALL
+ };
+
+ volatile uint32_t cmd_;
+ volatile uint32_t waiters_;
+ spin_mutex enter_mtx_;
+ spin_mutex check_mtx_;
+
+ void wait_( spin_mutex &);
+
+ void notify_( uint32_t);
+
+public:
+ spin_condition();
+
+ void notify_one();
+
+ void notify_all();
+
+ template< typename Lock >
+ void wait( Lock & lk)
+ {
+ if ( ! lk)
+ throw lock_error();
+ wait_( * lk.mutex() );
+ }
+
+ template<
+ typename Lock,
+ typename Pred
+ >
+ void wait( Lock & lk, Pred pred)
+ {
+ if ( ! lk)
+ throw lock_error();
+
+ while ( ! pred() )
+ wait_( * lk.mutex() );
+ }
+};
+
+}}
+
+#endif // BOOST_FIBERS_SPIN_CONDITION_H

Added: sandbox/fiber/boost/fiber/spin_count_down_event.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin_count_down_event.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,38 @@
+
+// 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)
+
+#ifndef BOOST_FIBERS_SPIN_COUNT_DOWN_EVENT_H
+#define BOOST_FIBERS_SPIN_COUNT_DOWN_EVENT_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+class spin_count_down_event : private noncopyable
+{
+private:
+ uint32_t initial_;
+ volatile uint32_t current_;
+
+public:
+ explicit spin_count_down_event( uint32_t);
+
+ uint32_t initial() const;
+
+ uint32_t current() const;
+
+ bool is_set() const;
+
+ void set();
+
+ void wait();
+};
+
+}}
+
+#endif // BOOST_FIBERS_SPIN_COUNT_DOWN_EVENT_H

Added: sandbox/fiber/boost/fiber/spin_manual_reset_event.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin_manual_reset_event.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,45 @@
+
+// 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)
+
+#ifndef BOOST_FIBERS_SPIN_MANUAL_RESET_EVENT_H
+#define BOOST_FIBERS_SPIN_MANUAL_RESET_EVENT_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/spin_mutex.hpp>
+
+namespace boost {
+namespace fibers {
+
+class spin_manual_reset_event : private noncopyable
+{
+private:
+ enum state_t
+ {
+ RESET = 0,
+ SET
+ };
+
+ volatile uint32_t state_;
+ volatile uint32_t waiters_;
+ spin_mutex enter_mtx_;
+
+public:
+ explicit spin_manual_reset_event( bool = false);
+
+ void set();
+
+ void reset();
+
+ void wait();
+
+ bool try_wait();
+};
+
+}}
+
+#endif // BOOST_FIBERS_SPIN_MANUAL_RESET_EVENT_H

Added: sandbox/fiber/boost/fiber/spin_mutex.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin_mutex.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,40 @@
+
+// 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)
+//
+// based on boost::interprocess::sync::interprocess_spin_mutex
+
+#ifndef BOOST_FIBERS_SPIN_MUTEX_H
+#define BOOST_FIBERS_SPIN_MUTEX_H
+
+#include <boost/cstdint.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+class spin_mutex : private noncopyable
+{
+private:
+ volatile uint32_t state_;
+
+public:
+ typedef unique_lock< spin_mutex > scoped_lock;
+
+ spin_mutex();
+
+ void lock();
+
+ bool try_lock();
+
+ void unlock();
+};
+
+typedef spin_mutex try_spin_mutex;
+
+}}
+
+#endif // BOOST_FIBERS_SPIN_MUTEX_H

Modified: sandbox/fiber/boost/fiber/strategy.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/strategy.hpp (original)
+++ sandbox/fiber/boost/fiber/strategy.hpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -8,10 +8,9 @@
 #define BOOST_FIBERS_STRATEGY_H
 
 #include <cstddef>
-#include <list>
-#include <map>
 
 #include <boost/function.hpp>
+#include <boost/intrusive_ptr.hpp>
 #include <boost/thread/tss.hpp>
 
 #include <boost/fiber/detail/interrupt_flags.hpp>
@@ -80,7 +79,7 @@
         friend class manual_reset_event;
         friend class mutex;
 
- typedef function< void() > callable_t;
+ typedef function< void() > callable_t;
 
         static bool runs_as_fiber_();
 
@@ -104,20 +103,12 @@
 
         static void cancel_();
 
- static void register_object_( object::id const&);
-
- static void unregister_object_( object::id const&);
-
- static void wait_for_object_( object::id const&);
-
- static void object_notify_one_( object::id const&);
-
- static void object_notify_all_( object::id const&);
+ uint32_t use_count_;
 
 protected:
         typedef thread_specific_ptr< fiber > fiber_t;
 
- static fiber_t active_fiber;
+ static fiber_t active_fiber;
 
         fiber master_fiber;
 
@@ -156,6 +147,8 @@
         void set_state_terminated( fiber &);
 
 public:
+ typedef intrusive_ptr< strategy > ptr_t;
+
         strategy();
 
         virtual ~strategy();
@@ -187,6 +180,12 @@
         virtual bool empty() = 0;
 
         virtual std::size_t size() = 0;
+
+ inline friend void intrusive_ptr_add_ref( strategy * p)
+ { ++p->use_count_; }
+
+ inline friend void intrusive_ptr_release( strategy * p)
+ { if ( --p->use_count_ == 0) delete p; }
 };
 
 }}

Modified: sandbox/fiber/libs/fiber/build/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/build/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/build/Jamfile.v2 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -50,6 +50,11 @@
         manual_reset_event.cpp
         mutex.cpp
         round_robin.cpp
+ spin_auto_reset_event.cpp
+ spin_condition.cpp
+ spin_count_down_event.cpp
+ spin_manual_reset_event.cpp
+ spin_mutex.cpp
         strategy.cpp
     : ## requirements ##
       <fiberapi>win32
@@ -66,6 +71,11 @@
         manual_reset_event.cpp
         mutex.cpp
         round_robin.cpp
+ spin_auto_reset_event.cpp
+ spin_condition.cpp
+ spin_count_down_event.cpp
+ spin_manual_reset_event.cpp
+ spin_mutex.cpp
         strategy.cpp
     : ## requirements ##
       <fiberapi>posix

Modified: sandbox/fiber/libs/fiber/src/auto_reset_event.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/auto_reset_event.cpp (original)
+++ sandbox/fiber/libs/fiber/src/auto_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -7,27 +7,18 @@
 #include "boost/fiber/auto_reset_event.hpp"
 
 #include <boost/fiber/detail/atomic.hpp>
-#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
 
-auto_reset_event::auto_reset_event( bool isset) :
- state_(
- isset ?
- static_cast< uint32_t >( SET) :
- static_cast< uint32_t >( RESET) ),
- id_( * this)
-{ strategy::register_object_( id_); }
-
 auto_reset_event::~auto_reset_event()
-{ strategy::unregister_object_( id_); }
+{ strategy_->unregister_object( id_); }
 
 void
 auto_reset_event::set()
 {
         detail::atomic_exchange( & state_, static_cast< uint32_t >( SET) );
- strategy::object_notify_one_( id_);
+ strategy_->object_notify_one( id_);
 }
 
 void
@@ -38,7 +29,7 @@
                         & state_, & expected,
                         static_cast< uint32_t >( RESET) ) )
         {
- strategy::wait_for_object_( id_);
+ strategy_->wait_for_object( id_);
                 expected = static_cast< uint32_t >( SET);
         }
 }

Modified: sandbox/fiber/libs/fiber/src/condition.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/condition.cpp (original)
+++ sandbox/fiber/libs/fiber/src/condition.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -10,8 +10,6 @@
 #include <boost/thread.hpp>
 
 #include <boost/fiber/detail/atomic.hpp>
-#include <boost/fiber/mutex.hpp>
-#include <boost/fiber/strategy.hpp>
 #include <boost/fiber/utility.hpp>
 
 namespace boost {
@@ -31,7 +29,7 @@
         for (;;)
         {
                 while ( static_cast< uint32_t >( SLEEPING) == detail::atomic_load( & cmd_) )
- strategy::wait_for_object_( id_);
+ strategy_->wait_for_object( id_);
 
                 mutex::scoped_lock lk( check_mtx_);
                 BOOST_ASSERT( lk);
@@ -68,16 +66,8 @@
         mtx.lock();
 }
 
-condition::condition() :
- cmd_( static_cast< uint32_t >( SLEEPING) ),
- waiters_( 0),
- enter_mtx_(),
- check_mtx_(),
- id_( * this)
-{ strategy::register_object_( id_); }
-
 condition::~condition()
-{ strategy::unregister_object_( id_); }
+{ strategy_->unregister_object( id_); }
 
 void
 condition::notify_one()
@@ -96,7 +86,7 @@
                                 & cmd_, & expected, cmd) )
                 this_fiber::yield();
         
- strategy::object_notify_one_( id_);
+ strategy_->object_notify_one( id_);
 }
 
 void
@@ -116,7 +106,7 @@
                                 & cmd_, & expected, cmd) )
                 this_fiber::yield();
 
- strategy::object_notify_all_( id_);
+ strategy_->object_notify_all( id_);
 }
 
 }}

Modified: sandbox/fiber/libs/fiber/src/count_down_event.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/count_down_event.cpp (original)
+++ sandbox/fiber/libs/fiber/src/count_down_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -7,20 +7,12 @@
 #include "boost/fiber/count_down_event.hpp"
 
 #include <boost/fiber/detail/atomic.hpp>
-#include <boost/fiber/mutex.hpp>
-#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
 
-count_down_event::count_down_event( uint32_t initial) :
- initial_( initial),
- current_( initial_),
- id_( * this)
-{ strategy::register_object_( id_); }
-
 count_down_event::~count_down_event()
-{ strategy::unregister_object_( id_); }
+{ strategy_->unregister_object( id_); }
 
 uint32_t
 count_down_event::initial() const
@@ -46,14 +38,14 @@
                         break;
         }
         if ( 0 == detail::atomic_load( & current_) )
- strategy::object_notify_all_( id_);
+ strategy_->object_notify_all( id_);
 }
 
 void
 count_down_event::wait()
 {
         while ( 0 != detail::atomic_load( & current_) )
- strategy::wait_for_object_( id_);
+ strategy_->wait_for_object( id_);
 }
 
 }}

Modified: sandbox/fiber/libs/fiber/src/manual_reset_event.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/manual_reset_event.cpp (original)
+++ sandbox/fiber/libs/fiber/src/manual_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -9,23 +9,12 @@
 #include <boost/assert.hpp>
 
 #include <boost/fiber/detail/atomic.hpp>
-#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
 
-manual_reset_event::manual_reset_event( bool isset) :
- state_(
- isset ?
- static_cast< uint32_t >( SET) :
- static_cast< uint32_t >( RESET) ),
- waiters_( 0),
- enter_mtx_(),
- id_( * this)
-{ strategy::register_object_( id_); }
-
 manual_reset_event::~manual_reset_event()
-{ strategy::unregister_object_( id_); }
+{ strategy_->unregister_object( id_); }
 
 void
 manual_reset_event::set()
@@ -39,7 +28,7 @@
                 ! detail::atomic_load( & waiters_ ) )
                 enter_mtx_.unlock();
         else
- strategy::object_notify_all_( id_);
+ strategy_->object_notify_all( id_);
 }
 
 void
@@ -62,7 +51,7 @@
         }
 
         while ( static_cast< uint32_t >( RESET) == detail::atomic_load( & state_) )
- strategy::wait_for_object_( id_);
+ strategy_->wait_for_object( id_);
 
         if ( 1 == detail::atomic_fetch_sub( & waiters_, 1) )
                 enter_mtx_.unlock();

Modified: sandbox/fiber/libs/fiber/src/mutex.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/mutex.cpp (original)
+++ sandbox/fiber/libs/fiber/src/mutex.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -7,18 +7,12 @@
 #include <boost/fiber/mutex.hpp>
 
 #include <boost/fiber/detail/atomic.hpp>
-#include <boost/fiber/strategy.hpp>
 
 namespace boost {
 namespace fibers {
 
-mutex::mutex() :
- state_( 0),
- id_( * this)
-{ strategy::register_object_( id_); }
-
 mutex::~mutex()
-{ strategy::unregister_object_( id_); }
+{ strategy_->unregister_object( id_); }
 
 void
 mutex::lock()
@@ -29,7 +23,7 @@
                 if ( detail::atomic_compare_exchange_strong( & state_, & expected, 1) )
                         break;
                 else
- strategy::wait_for_object_( id_);
+ strategy_->wait_for_object( id_);
         }
 }
 
@@ -44,7 +38,7 @@
 mutex::unlock()
 {
         detail::atomic_exchange( & state_, 0);
- strategy::object_notify_one_( id_);
+ strategy_->object_notify_one( id_);
 }
 
 }}

Modified: sandbox/fiber/libs/fiber/src/round_robin.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/round_robin.cpp (original)
+++ sandbox/fiber/libs/fiber/src/round_robin.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -22,9 +22,9 @@
 
 round_robin::round_robin() :
         fibers_(),
+ objects_(),
         runnable_fibers_(),
- terminated_fibers_(),
- objects_()
+ terminated_fibers_()
 {}
 
 round_robin::~round_robin()

Added: sandbox/fiber/libs/fiber/src/spin_auto_reset_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/spin_auto_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,48 @@
+
+// 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 "boost/fiber/spin_auto_reset_event.hpp"
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+spin_auto_reset_event::spin_auto_reset_event( bool isset) :
+ state_(
+ isset ?
+ static_cast< uint32_t >( SET) :
+ static_cast< uint32_t >( RESET) )
+{}
+
+void
+spin_auto_reset_event::set()
+{ detail::atomic_exchange( & state_, static_cast< uint32_t >( SET) ); }
+
+void
+spin_auto_reset_event::wait()
+{
+ uint32_t expected = static_cast< uint32_t >( SET);
+ while ( ! detail::atomic_compare_exchange_strong(
+ & state_, & expected,
+ static_cast< uint32_t >( RESET) ) )
+ {
+ this_fiber::yield();
+ expected = static_cast< uint32_t >( SET);
+ }
+}
+
+bool
+spin_auto_reset_event::try_wait()
+{
+ uint32_t expected = static_cast< uint32_t >( SET);
+ return detail::atomic_compare_exchange_strong(
+ & state_, & expected,
+ static_cast< uint32_t >( RESET) );
+}
+
+}}

Added: sandbox/fiber/libs/fiber/src/spin_condition.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/spin_condition.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,102 @@
+
+// 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 "boost/fiber/spin_condition.hpp"
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/spin_mutex.hpp>
+#include <boost/fiber/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+void
+spin_condition::notify_( uint32_t cmd)
+{
+ enter_mtx_.lock();
+
+ if ( 0 == detail::atomic_load( & waiters_) )
+ {
+ enter_mtx_.unlock();
+ return;
+ }
+
+ uint32_t expected = static_cast< uint32_t >( SLEEPING);
+ while ( ! detail::atomic_compare_exchange_strong(
+ & cmd_, & expected, cmd) )
+ this_fiber::yield();
+}
+
+void
+spin_condition::wait_( spin_mutex & mtx)
+{
+ {
+ spin_mutex::scoped_lock lk( enter_mtx_);
+ BOOST_ASSERT( lk);
+ detail::atomic_fetch_add( & waiters_, 1);
+ mtx.unlock();
+ }
+
+ bool unlock_enter_mtx = false;
+ for (;;)
+ {
+ while ( static_cast< uint32_t >( SLEEPING) == detail::atomic_load( & cmd_) )
+ this_fiber::yield();
+
+ spin_mutex::scoped_lock lk( check_mtx_);
+ BOOST_ASSERT( lk);
+
+ uint32_t expected = static_cast< uint32_t >( NOTIFY_ONE);
+ detail::atomic_compare_exchange_strong(
+ & cmd_, & expected,
+ static_cast< uint32_t >( SLEEPING) );
+ if ( static_cast< uint32_t >( SLEEPING) == expected)
+ continue;
+ else if ( static_cast< uint32_t >( NOTIFY_ONE) == expected)
+ {
+ unlock_enter_mtx = true;
+ detail::atomic_fetch_sub( & waiters_, 1);
+ break;
+ }
+ else
+ {
+ unlock_enter_mtx = 1 == detail::atomic_fetch_sub( & waiters_, 1);
+ if ( unlock_enter_mtx)
+ {
+ expected = static_cast< uint32_t >( NOTIFY_ALL);
+ detail::atomic_compare_exchange_strong(
+ & cmd_, & expected,
+ static_cast< uint32_t >( SLEEPING) );
+ }
+ break;
+ }
+ }
+
+ if ( unlock_enter_mtx)
+ enter_mtx_.unlock();
+
+ mtx.lock();
+}
+
+spin_condition::spin_condition() :
+ cmd_( static_cast< uint32_t >( SLEEPING) ),
+ waiters_( 0),
+ enter_mtx_(),
+ check_mtx_()
+{}
+
+void
+spin_condition::notify_one()
+{ notify_( static_cast< uint32_t >( NOTIFY_ONE) ); }
+
+void
+spin_condition::notify_all()
+{ notify_( static_cast< uint32_t >( NOTIFY_ALL) ); }
+
+}}

Added: sandbox/fiber/libs/fiber/src/spin_count_down_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/spin_count_down_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,53 @@
+
+// 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 "boost/fiber/spin_count_down_event.hpp"
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/spin_mutex.hpp>
+#include <boost/fiber/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+spin_count_down_event::spin_count_down_event( uint32_t initial) :
+ initial_( initial),
+ current_( initial_)
+{}
+
+uint32_t
+spin_count_down_event::initial() const
+{ return initial_; }
+
+uint32_t
+spin_count_down_event::current() const
+{ return detail::atomic_load( & current_); }
+
+bool
+spin_count_down_event::is_set() const
+{ return 0 == detail::atomic_load( & current_); }
+
+void
+spin_count_down_event::set()
+{
+ for (;;)
+ {
+ if ( 0 == detail::atomic_load( & current_) )
+ return;
+ uint32_t expected = current_;
+ if ( detail::atomic_compare_exchange_strong( & current_, & expected, expected - 1) )
+ return;
+ }
+}
+
+void
+spin_count_down_event::wait()
+{
+ while ( 0 != detail::atomic_load( & current_) )
+ this_fiber::yield();
+}
+
+}}

Added: sandbox/fiber/libs/fiber/src/spin_manual_reset_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/spin_manual_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,82 @@
+
+// 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 "boost/fiber/spin_manual_reset_event.hpp"
+
+#include <boost/assert.hpp>
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+spin_manual_reset_event::spin_manual_reset_event( bool isset) :
+ state_(
+ isset ?
+ static_cast< uint32_t >( SET) :
+ static_cast< uint32_t >( RESET) ),
+ waiters_( 0),
+ enter_mtx_()
+{}
+
+void
+spin_manual_reset_event::set()
+{
+ enter_mtx_.lock();
+
+ uint32_t expected = static_cast< uint32_t >( RESET);
+ if ( ! detail::atomic_compare_exchange_strong(
+ & state_, & expected,
+ static_cast< uint32_t >( SET) ) ||
+ ! detail::atomic_load( & waiters_ ) )
+ enter_mtx_.unlock();
+}
+
+void
+spin_manual_reset_event::reset()
+{
+ spin_mutex::scoped_lock lk( enter_mtx_);
+ BOOST_ASSERT( lk);
+
+ detail::atomic_exchange( & state_,
+ static_cast< uint32_t >( RESET) );
+}
+
+void
+spin_manual_reset_event::wait()
+{
+ {
+ spin_mutex::scoped_lock lk( enter_mtx_);
+ BOOST_ASSERT( lk);
+ detail::atomic_fetch_add( & waiters_, 1);
+ }
+
+ while ( static_cast< uint32_t >( RESET) == detail::atomic_load( & state_) )
+ this_fiber::yield();
+
+ if ( 1 == detail::atomic_fetch_sub( & waiters_, 1) )
+ enter_mtx_.unlock();
+}
+
+bool
+spin_manual_reset_event::try_wait()
+{
+ {
+ spin_mutex::scoped_lock lk( enter_mtx_);
+ BOOST_ASSERT( lk);
+ detail::atomic_fetch_add( & waiters_, 1);
+ }
+
+ bool result = static_cast< uint32_t >( SET) == detail::atomic_load( & state_);
+
+ if ( 1 == detail::atomic_fetch_sub( & waiters_, 1) )
+ enter_mtx_.unlock();
+
+ return result;
+}
+
+}}

Added: sandbox/fiber/libs/fiber/src/spin_mutex.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/spin_mutex.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,43 @@
+
+// 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 <boost/fiber/spin_mutex.hpp>
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/utility.hpp>
+
+namespace boost {
+namespace fibers {
+
+spin_mutex::spin_mutex() :
+ state_( 0)
+{}
+
+void
+spin_mutex::lock()
+{
+ for (;;)
+ {
+ uint32_t expected = 0;
+ if ( detail::atomic_compare_exchange_strong( & state_, & expected, 1) )
+ break;
+ else
+ this_fiber::yield();
+ }
+}
+
+bool
+spin_mutex::try_lock()
+{
+ uint32_t expected = 0;
+ return detail::atomic_compare_exchange_strong( & state_, & expected, 1);
+}
+
+void
+spin_mutex::unlock()
+{ detail::atomic_exchange( & state_, 0); }
+
+}}

Modified: sandbox/fiber/libs/fiber/src/strategy.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/strategy.cpp (original)
+++ sandbox/fiber/libs/fiber/src/strategy.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -101,52 +101,8 @@
         active->info_()->st->cancel( active_fiber->get_id() );
 }
 
-void
-strategy::register_object_( object::id const& oid)
-{
- fiber * active( active_fiber.get() );
- if ( ! active) throw fiber_error("not a fiber");
- if ( ! active->info_()->st) throw scheduler_error("no valid scheduler");
- active->info_()->st->register_object( oid);
-}
-
-void
-strategy::unregister_object_( object::id const& oid)
-{
- fiber * active( active_fiber.get() );
- if ( ! active) throw fiber_error("not a fiber");
- if ( ! active->info_()->st) throw scheduler_error("no valid scheduler");
- active->info_()->st->unregister_object( oid);
-}
-
-void
-strategy::wait_for_object_( object::id const& oid)
-{
- fiber * active( active_fiber.get() );
- if ( ! active) throw fiber_error("not a fiber");
- if ( ! active->info_()->st) throw scheduler_error("no valid scheduler");
- active->info_()->st->wait_for_object( oid);
-}
-
-void
-strategy::object_notify_one_( object::id const& oid)
-{
- fiber * active( active_fiber.get() );
- if ( ! active) throw fiber_error("not a fiber");
- if ( ! active->info_()->st) throw scheduler_error("no valid scheduler");
- active->info_()->st->object_notify_one( oid);
-}
-
-void
-strategy::object_notify_all_( object::id const& oid)
-{
- fiber * active( active_fiber.get() );
- if ( ! active) throw fiber_error("not a fiber");
- if ( ! active->info_()->st) throw scheduler_error("no valid scheduler");
- active->info_()->st->object_notify_all( oid);
-}
-
 strategy::strategy() :
+ use_count_( 0),
         master_fiber()
 {
         fiber::convert_thread_to_fiber();

Modified: sandbox/fiber/libs/fiber/test/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/test/Jamfile.v2 (original)
+++ sandbox/fiber/libs/fiber/test/Jamfile.v2 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -33,10 +33,16 @@
     [ fiber-test test_join ]
     [ fiber-test test_interrupt ]
     [ fiber-test test_at_exit ]
-# [ 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 ]
+ [ fiber-test test_mutex ]
+ [ fiber-test test_lock ]
+ [ fiber-test test_auto_reset_event ]
+ [ fiber-test test_manual_reset_event ]
+ [ fiber-test test_count_down_event ]
+ [ fiber-test test_condition ]
+ [ fiber-test test_spin_mutex ]
+ [ fiber-test test_spin_lock ]
+ [ fiber-test test_spin_auto_reset_event ]
+ [ fiber-test test_spin_manual_reset_event ]
+ [ fiber-test test_spin_count_down_event ]
+ [ fiber-test test_spin_condition ]
     ;

Modified: sandbox/fiber/libs/fiber/test/test_auto_reset_event.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_auto_reset_event.cpp (original)
+++ sandbox/fiber/libs/fiber/test/test_auto_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -32,8 +32,8 @@
 void test_case_1()
 {
         value = 0;
- boost::fibers::auto_reset_event ev;
         boost::fibers::scheduler<> sched;
+ boost::fibers::auto_reset_event ev( sched);
 
         sched.make_fiber(
                 wait_fn,
@@ -70,8 +70,8 @@
 void test_case_2()
 {
         value = 0;
- boost::fibers::auto_reset_event ev( true);
         boost::fibers::scheduler<> sched;
+ boost::fibers::auto_reset_event ev( sched, true);
 
         sched.make_fiber(
                 wait_fn,
@@ -101,8 +101,8 @@
 
 void test_case_3()
 {
- boost::fibers::auto_reset_event ev;
         boost::fibers::scheduler<> sched;
+ boost::fibers::auto_reset_event ev( sched);
 
         BOOST_CHECK_EQUAL( false, ev.try_wait() );
 

Modified: sandbox/fiber/libs/fiber/test/test_condition.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_condition.cpp (original)
+++ sandbox/fiber/libs/fiber/test/test_condition.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -44,9 +44,9 @@
 void test_case_1()
 {
         value = 0;
- boost::fibers::mutex mtx;
- boost::fibers::condition cond;
         boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::fibers::condition cond( sched);
 
         sched.make_fiber(
                 wait_fn,
@@ -88,9 +88,9 @@
 void test_case_2()
 {
         value = 0;
- boost::fibers::mutex mtx;
- boost::fibers::condition cond;
         boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::fibers::condition cond( sched);
 
         sched.make_fiber(
                 wait_fn,
@@ -150,9 +150,9 @@
 void test_case_3()
 {
         value = 0;
- boost::fibers::mutex mtx;
- boost::fibers::condition cond;
         boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::fibers::condition cond( sched);
 
         sched.make_fiber(
                 wait_fn,

Modified: sandbox/fiber/libs/fiber/test/test_count_down_event.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_count_down_event.cpp (original)
+++ sandbox/fiber/libs/fiber/test/test_count_down_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -30,8 +30,8 @@
 void test_case_1()
 {
         boost::uint32_t n = 3;
- boost::fibers::count_down_event ev( n);
         boost::fibers::scheduler<> sched;
+ boost::fibers::count_down_event ev( sched, n);
 
         BOOST_CHECK_EQUAL( ev.initial(), n);
         BOOST_CHECK_EQUAL( ev.current(), n);
@@ -57,8 +57,8 @@
 {
         value = 0;
         boost::uint32_t n = 3;
- boost::fibers::count_down_event ev( n);
         boost::fibers::scheduler<> sched;
+ boost::fibers::count_down_event ev( sched, n);
 
         BOOST_CHECK_EQUAL( ev.initial(), n);
         BOOST_CHECK_EQUAL( ev.current(), n);

Added: sandbox/fiber/libs/fiber/test/test_lock.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_lock.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,209 @@
+
+// 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::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::unique_lock< boost::fibers::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::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::unique_lock< boost::fibers::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::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ mtx.lock();
+ boost::unique_lock< boost::fibers::mutex > lk( mtx, boost::adopt_lock);
+
+ BOOST_CHECK( lk);
+ BOOST_CHECK( lk.owns_lock() );
+}
+
+void test_try_lock()
+{
+ boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::unique_lock< boost::fibers::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::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::unique_lock< boost::fibers::mutex > lk( mtx);
+
+ BOOST_CHECK_THROW( lk.lock(), boost::lock_error);
+}
+
+void test_try_lock_twice()
+{
+ boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::unique_lock< boost::fibers::mutex > lk( mtx);
+
+ BOOST_CHECK_THROW( lk.try_lock(), boost::lock_error);
+}
+
+void test_unlock_twice()
+{
+ boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
+ boost::unique_lock< boost::fibers::mutex > lk( mtx);
+ lk.unlock();
+
+ BOOST_CHECK_THROW( lk.unlock(), boost::lock_error);
+}
+
+void test_default_ctor()
+{
+ boost::unique_lock< boost::fibers::mutex > lk;
+
+ BOOST_CHECK( ! lk);
+ BOOST_CHECK( ! lk.owns_lock() );
+}
+
+void test_lock_concept()
+{
+ boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx1( sched), mtx2( sched), mtx3( sched);
+
+ boost::fibers::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::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::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx1( sched), mtx2( sched);
+
+ boost::unique_lock< boost::fibers::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;
+}

Modified: sandbox/fiber/libs/fiber/test/test_manual_reset_event.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_manual_reset_event.cpp (original)
+++ sandbox/fiber/libs/fiber/test/test_manual_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -31,8 +31,8 @@
 void test_case_1()
 {
         value = 0;
- boost::fibers::manual_reset_event ev;
         boost::fibers::scheduler<> sched;
+ boost::fibers::manual_reset_event ev( sched);
 
         sched.make_fiber(
                 wait_fn,
@@ -61,8 +61,8 @@
 void test_case_2()
 {
         value = 0;
- boost::fibers::manual_reset_event ev;
         boost::fibers::scheduler<> sched;
+ boost::fibers::manual_reset_event ev( sched);
 
         sched.make_fiber(
                 wait_fn,
@@ -107,8 +107,8 @@
 void test_case_3()
 {
         value = 0;
- boost::fibers::manual_reset_event ev( true);
         boost::fibers::scheduler<> sched;
+ boost::fibers::manual_reset_event ev( sched, true);
 
         sched.make_fiber(
                 wait_fn,
@@ -130,8 +130,8 @@
 
 void test_case_4()
 {
- boost::fibers::manual_reset_event ev;
         boost::fibers::scheduler<> sched;
+ boost::fibers::manual_reset_event ev( sched);
 
         BOOST_CHECK_EQUAL( false, ev.try_wait() );
 

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-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -27,35 +27,35 @@
     typedef M mutex_type;
     typedef typename M::scoped_lock lock_type;
 
- void operator()()
+ void operator()( boost::fibers::scheduler<> & sched)
     {
- mutex_type mutex;
+ mutex_type mtx( sched);
 
         // Test the lock's constructors.
         {
- lock_type lock(mutex, boost::defer_lock);
- BOOST_CHECK(!lock);
+ lock_type lk(mtx, boost::defer_lock);
+ BOOST_CHECK(!lk);
         }
- lock_type lock(mutex);
- BOOST_CHECK(lock ? true : false);
+ lock_type lk(mtx);
+ BOOST_CHECK(lk ? true : false);
 
         // Test the lock and unlock methods.
- lock.unlock();
- BOOST_CHECK(!lock);
- lock.lock();
- BOOST_CHECK(lock ? true : false);
+ lk.unlock();
+ BOOST_CHECK(!lk);
+ lk.lock();
+ BOOST_CHECK(lk ? true : false);
     }
 };
 
-void do_test_mutex()
+void do_test_mutex( boost::fibers::scheduler<> & sched)
 {
- test_lock< boost::fibers::mutex >()();
+ test_lock< boost::fibers::mutex >()( sched);
 }
 
-void test_1()
+void test_case1()
 {
         boost::fibers::scheduler<> sched;
- sched.make_fiber( & do_test_mutex);
+ sched.make_fiber( & do_test_mutex, boost::ref( sched) );
         sched.run();
 }
 
@@ -77,10 +77,10 @@
         ++value2;
 }
 
-void test_2()
+void test_case2()
 {
- boost::fibers::mutex mtx;
         boost::fibers::scheduler<> sched;
+ boost::fibers::mutex mtx( sched);
     sched.make_fiber( & test_fn1, boost::ref( mtx) );
     sched.make_fiber( & test_fn2, boost::ref( mtx) );
 
@@ -115,28 +115,6 @@
         BOOST_CHECK_EQUAL( 2, value2);
 }
 
-void test_case1()
-{
- boost::fibers::scheduler<> sched;
- sched.make_fiber( & test_1);
- for (;;)
- {
- while ( sched.run() );
- if ( sched.empty() ) break;
- }
-}
-
-void test_case2()
-{
- boost::fibers::scheduler<> sched;
- sched.make_fiber( & test_2);
- for (;;)
- {
- while ( sched.run() );
- if ( sched.empty() ) break;
- }
-}
-
 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
 {
     boost::unit_test_framework::test_suite * test =

Added: sandbox/fiber/libs/fiber/test/test_spin_auto_reset_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_spin_auto_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,123 @@
+
+// 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::fibers::spin_auto_reset_event & ev)
+{
+ ev.wait();
+ ++value;
+}
+
+// check wait
+void test_case_1()
+{
+ value = 0;
+ boost::fibers::spin_auto_reset_event ev;
+ boost::fibers::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::fibers::spin_auto_reset_event ev( true);
+ boost::fibers::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::fibers::spin_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: spin-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_spin_condition.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_spin_condition.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,228 @@
+
+// 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 notify_one_fn( boost::fibers::spin_condition & cond)
+{
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::fibers::spin_condition & cond)
+{
+ cond.notify_all();
+}
+
+void wait_fn(
+ boost::fibers::spin_mutex & mtx,
+ boost::fibers::spin_condition & cond)
+{
+ boost::fibers::spin_mutex::scoped_lock lk( mtx);
+ cond.wait( lk);
+ ++value;
+}
+
+void test_case_1()
+{
+ value = 0;
+ boost::fibers::spin_mutex mtx;
+ boost::fibers::spin_condition cond;
+ boost::fibers::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::fibers::spin_mutex mtx;
+ boost::fibers::spin_condition cond;
+ boost::fibers::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::fibers::spin_mutex mtx;
+ boost::fibers::spin_condition cond;
+ boost::fibers::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: spin-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_spin_count_down_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_spin_count_down_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 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::fibers::spin_count_down_event & ev)
+{
+ ev.wait();
+ ++value;
+}
+
+void test_case_1()
+{
+ boost::uint32_t n = 3;
+ boost::fibers::spin_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::fibers::spin_count_down_event ev( n);
+ boost::fibers::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_spin_lock.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_spin_lock.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 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::fibers::spin_mutex mtx;
+ boost::unique_lock< boost::fibers::spin_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::fibers::spin_mutex mtx;
+ boost::unique_lock< boost::fibers::spin_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::fibers::spin_mutex mtx;
+ mtx.lock();
+ boost::unique_lock< boost::fibers::spin_mutex > lk( mtx, boost::adopt_lock);
+
+ BOOST_CHECK( lk);
+ BOOST_CHECK( lk.owns_lock() );
+}
+
+void test_try_lock()
+{
+ boost::fibers::spin_mutex mtx;
+ boost::unique_lock< boost::fibers::spin_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::fibers::spin_mutex mtx;
+ boost::unique_lock< boost::fibers::spin_mutex > lk( mtx);
+
+ BOOST_CHECK_THROW( lk.lock(), boost::lock_error);
+}
+
+void test_try_lock_twice()
+{
+ boost::fibers::spin_mutex mtx;
+ boost::unique_lock< boost::fibers::spin_mutex > lk( mtx);
+
+ BOOST_CHECK_THROW( lk.try_lock(), boost::lock_error);
+}
+
+void test_unlock_twice()
+{
+ boost::fibers::spin_mutex mtx;
+ boost::unique_lock< boost::fibers::spin_mutex > lk( mtx);
+ lk.unlock();
+
+ BOOST_CHECK_THROW( lk.unlock(), boost::lock_error);
+}
+
+void test_default_ctor()
+{
+ boost::unique_lock< boost::fibers::spin_mutex > lk;
+
+ BOOST_CHECK( ! lk);
+ BOOST_CHECK( ! lk.owns_lock() );
+}
+
+void test_lock_concept()
+{
+ boost::fibers::spin_mutex mtx1, mtx2, mtx3;
+
+ boost::fibers::spin_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::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::fibers::spin_mutex mtx1, mtx2;
+
+ boost::unique_lock< boost::fibers::spin_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;
+}

Added: sandbox/fiber/libs/fiber/test/test_spin_manual_reset_event.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_spin_manual_reset_event.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,157 @@
+
+// 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::fibers::spin_manual_reset_event & ev)
+{
+ ev.wait();
+ ++value;
+}
+
+void test_case_1()
+{
+ value = 0;
+ boost::fibers::spin_manual_reset_event ev;
+ boost::fibers::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::fibers::spin_manual_reset_event ev;
+ boost::fibers::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::fibers::spin_manual_reset_event ev( true);
+ boost::fibers::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::fibers::spin_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: spin-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;
+}

Added: sandbox/fiber/libs/fiber/test/test_spin_mutex.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_spin_mutex.cpp 2009-12-07 15:49:34 EST (Mon, 07 Dec 2009)
@@ -0,0 +1,131 @@
+
+// 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>
+
+template< typename M >
+struct test_lock
+{
+ typedef M spin_mutex_type;
+ typedef typename M::scoped_lock lock_type;
+
+ void operator()()
+ {
+ spin_mutex_type spin_mutex;
+ boost::fibers::spin_condition condition;
+
+ // Test the lock's constructors.
+ {
+ lock_type lock(spin_mutex, boost::defer_lock);
+ BOOST_CHECK(!lock);
+ }
+ lock_type lock(spin_mutex);
+ BOOST_CHECK(lock ? true : false);
+
+ // Test the lock and unlock methods.
+ lock.unlock();
+ BOOST_CHECK(!lock);
+ lock.lock();
+ BOOST_CHECK(lock ? true : false);
+ }
+};
+
+void do_test_spin_mutex()
+{
+ test_lock< boost::fibers::spin_mutex >()();
+}
+
+void test_case1()
+{
+ boost::fibers::scheduler<> sched;
+ sched.make_fiber( & do_test_spin_mutex);
+ sched.run();
+}
+
+int value1 = 0;
+int value2 = 0;
+
+void test_fn1( boost::fibers::spin_mutex & mtx)
+{
+ boost::fibers::spin_mutex::scoped_lock lk( mtx);
+ ++value1;
+ for ( int i = 0; i < 3; ++i)
+ boost::this_fiber::yield();
+}
+
+void test_fn2( boost::fibers::spin_mutex & mtx)
+{
+ boost::fibers::spin_mutex::scoped_lock lk( mtx);
+ ++value2;
+}
+
+void test_case2()
+{
+ boost::fibers::spin_mutex mtx;
+ boost::fibers::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: spin-mutex test suite");
+
+ test->add(BOOST_TEST_CASE(&test_case1));
+ test->add(BOOST_TEST_CASE(&test_case2));
+
+ 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