$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r57761 - in sandbox/fiber: boost/fiber boost/fiber/detail libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-11-18 17:02:48
Author: olli
Date: 2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
New Revision: 57761
URL: http://svn.boost.org/trac/boost/changeset/57761
Log:
- refactoring of interface (remove _active_fiber/_fiber from function names)
- fiber::join() throw fiber_interrupted if fiber gets interrupted
Text files modified: 
   sandbox/fiber/boost/fiber/detail/fiber_state.hpp    |     2                                         
   sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp |    46 +++--                                   
   sandbox/fiber/boost/fiber/interruption.hpp          |    12                                         
   sandbox/fiber/boost/fiber/scheduler.hpp             |    44 +++--                                   
   sandbox/fiber/boost/fiber/utility.hpp               |    24 +-                                      
   sandbox/fiber/libs/fiber/src/fiber.cpp              |    41 +++--                                   
   sandbox/fiber/libs/fiber/src/scheduler.cpp          |    74 +++++----                               
   sandbox/fiber/libs/fiber/src/scheduler_impl.cpp     |   293 +++++++++++++++++++++++++++++---------- 
   sandbox/fiber/libs/fiber/test/test_join.cpp         |    62 +++++++                                 
   9 files changed, 411 insertions(+), 187 deletions(-)
Modified: sandbox/fiber/boost/fiber/detail/fiber_state.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/fiber_state.hpp	(original)
+++ sandbox/fiber/boost/fiber/detail/fiber_state.hpp	2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -20,7 +20,7 @@
         STATE_READY			= 1 << 2,
         STATE_RUNNING		= 1 << 3,
         STATE_SUSPENDED		= 1 << 4,
-	STATE_WAITING		= 1 << 5,
+	STATE_WAIT_FOR_JOIN	= 1 << 5,
         STATE_TERMINATED	= 1 << 6
 };
 
Modified: sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp	(original)
+++ sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp	2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -13,6 +13,7 @@
 #include <queue>
 
 #include <boost/function.hpp>
+#include <boost/optional.hpp>
 #include <boost/utility.hpp>
 
 #include <boost/fiber/detail/config.hpp>
@@ -36,21 +37,22 @@
         struct schedulable
         {
                 fiber					f;
-		std::list< fiber::id >	waiting;
+		std::list< fiber::id >	joining_fibers;
+		optional< fiber::id >	waiting_on;
 
                 schedulable() :
-			f(), waiting()
+			f(), joining_fibers(), waiting_on()
                 {}
 
                 schedulable( fiber f_) :
-			f( f_), waiting()
+			f( f_), joining_fibers(), waiting_on()
                 {}
         };
 
         typedef std::map< fiber::id, schedulable >	container;
         typedef std::list< fiber::id >				runnable_queue;
         typedef std::queue< fiber::id >				terminated_queue;
-	typedef function< void() >			callable_t;
+	typedef function< void() >					callable_t;
 
         fiber				master_;
         fiber				active_;
@@ -63,39 +65,41 @@
 
         ~scheduler_impl();
 
-	void add_fiber( fiber);
+	void add( fiber);
 
-	fiber::id id_active_fiber() const;
+	fiber::id get_id() const;
 
-	void yield_active_fiber();
+	void yield();
 
-	void cancel_active_fiber();
+	void cancel();
 
-	void suspend_active_fiber();
+	void suspend();
 
-	void interrupt_active_fiber();
+	void interrupt();
 
-	bool interruption_requested_active_fiber() const;
+	bool interruption_requested();
 
-	bool interruption_enabled_active_fiber() const;
+	bool interruption_enabled();
 
-	fiber_interrupt_t & interrupt_flags_active_fiber();
+	fiber_interrupt_t & interrupt_flags();
 
-	int priority_active_fiber();
+	int priority();
 
-	void priority_active_fiber( int);
+	void priority( int);
 
-	void at_exit_active_fiber( callable_t);
+	void at_exit( callable_t);
 
-	void cancel_fiber( fiber::id const&);
+	void interrupt( fiber::id const&);
 
-	void suspend_fiber( fiber::id const&);
+	void cancel( fiber::id const&);
 
-	void resume_fiber( fiber::id const&);
+	void suspend( fiber::id const&);
 
-	void reschedule_fiber( fiber::id const&);
+	void resume( fiber::id const&);
 
-	void join_fiber( fiber::id const&);
+	void join( fiber::id const&);
+
+	void reschedule( fiber::id const&);
 
         bool run();
 
Modified: sandbox/fiber/boost/fiber/interruption.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/interruption.hpp	(original)
+++ sandbox/fiber/boost/fiber/interruption.hpp	2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -27,16 +27,16 @@
 
 public:
         disable_interruption() :
-		set_( ( scheduler::interrupt_flags_active_fiber() & detail::INTERRUPTION_BLOCKED) != 0)
+		set_( ( scheduler::interrupt_flags() & detail::INTERRUPTION_BLOCKED) != 0)
         {
                 if ( ! set_)
-			scheduler::interrupt_flags_active_fiber() |= detail::INTERRUPTION_BLOCKED;
+			scheduler::interrupt_flags() |= detail::INTERRUPTION_BLOCKED;
         }
 
         ~disable_interruption()
         {
                 if ( ! set_)
-			scheduler::interrupt_flags_active_fiber() &= ~detail::INTERRUPTION_BLOCKED;
+			scheduler::interrupt_flags() &= ~detail::INTERRUPTION_BLOCKED;
         }
 };
 
@@ -47,16 +47,16 @@
 
 public:
         restore_interruption() :
-		set_( ( scheduler::interrupt_flags_active_fiber() & detail::INTERRUPTION_BLOCKED) != 0)
+		set_( ( scheduler::interrupt_flags() & detail::INTERRUPTION_BLOCKED) != 0)
         {
                 if ( set_)
-			scheduler::interrupt_flags_active_fiber() &= ~detail::INTERRUPTION_BLOCKED;
+			scheduler::interrupt_flags() &= ~detail::INTERRUPTION_BLOCKED;
         }
 
         ~restore_interruption()
         {  
                 if ( set_)
-			scheduler::interrupt_flags_active_fiber() |= detail::INTERRUPTION_BLOCKED;
+			scheduler::interrupt_flags() |= detail::INTERRUPTION_BLOCKED;
         }
 };
 
Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp	(original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp	2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -81,37 +81,41 @@
 
         static bool runs_as_fiber();
 
-	static fiber::id id_active_fiber();
+	static fiber::id get_id();
 
-	static void yield_active_fiber();
+	static void interrupt();
 
-	static void cancel_active_fiber();
+	static bool interruption_requested();
 
-	static void suspend_active_fiber();
+	static bool interruption_enabled();
 
-	static void interrupt_active_fiber();
+	static detail::fiber_interrupt_t & interrupt_flags();
 
-	static bool interruption_requested_active_fiber();
+	static void yield();
 
-	static bool interruption_enabled_active_fiber();
+	static void cancel();
 
-	static detail::fiber_interrupt_t & interrupt_flags_active_fiber();
+	static void suspend();
 
-	static int priority_active_fiber();
+	static int priority();
 
-	static void priority_active_fiber( int);
+	static void priority( int);
 
-	static void at_exit_active_fiber( callable_t);
+	static void at_exit( callable_t);
 
-	static void cancel_fiber( fiber::id const&);
+	static void interrupt( fiber::id const&);
 
-	static void suspend_fiber( fiber::id const&);
+	static bool interruption_requested( fiber::id const&);
 
-	static void resume_fiber( fiber::id const&);
+	static void cancel( fiber::id const&);
 
-	static void reschedule_fiber( fiber::id const&);
+	static void suspend( fiber::id const&);
 
-	static void join_fiber( fiber::id const&);
+	static void resume( fiber::id const&);
+
+	static void join( fiber::id const&);
+
+	static void reschedule( fiber::id const&);
 
         detail::scheduler_impl * access_();
 
@@ -128,11 +132,11 @@
 
         template< typename Fn >
         void make_fiber( Fn fn)
-	{ access_()->add_fiber( fiber( fn) ); }
+	{ access_()->add( fiber( fn) ); }
 
         template< typename Fn >
         void make_fiber( std::size_t stack_size, Fn fn)
-	{ access_()->add_fiber( fiber( stack_size, fn) ); }
+	{ access_()->add( fiber( stack_size, fn) ); }
 
 #ifndef BOOST_FIBER_MAX_ARITY
 #define BOOST_FIBER_MAX_ARITY 10
@@ -145,10 +149,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( fiber( fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); } \
+	{ access_()->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( fiber( stack_size, fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); }
+	{ access_()->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, ~)
 
Modified: sandbox/fiber/boost/fiber/utility.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/utility.hpp	(original)
+++ sandbox/fiber/boost/fiber/utility.hpp	2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -25,55 +25,55 @@
 
 inline
 fiber::id get_id()
-{ return fibers::scheduler::id_active_fiber(); }
+{ return fibers::scheduler::get_id(); }
 
 inline
 void yield()
-{ fibers::scheduler::yield_active_fiber(); }
+{ fibers::scheduler::yield(); }
 
 inline
 void cancel()
-{ fibers::scheduler::cancel_active_fiber(); }
+{ fibers::scheduler::cancel(); }
 
 inline
 void suspend()
-{ fibers::scheduler::suspend_active_fiber(); }
+{ fibers::scheduler::suspend(); }
 
 inline
 int priority()
-{ return fibers::scheduler::priority_active_fiber(); }
+{ return fibers::scheduler::priority(); }
 
 inline
 void priority( int prio)
-{ fibers::scheduler::priority_active_fiber( prio); }
+{ fibers::scheduler::priority( prio); }
 
 inline
 void interruption_point()
-{ fibers::scheduler::interrupt_active_fiber(); }
+{ fibers::scheduler::interrupt(); }
 
 inline
 bool interruption_requested()
-{ return fibers::scheduler::interruption_requested_active_fiber(); }
+{ return fibers::scheduler::interruption_requested(); }
 
 inline
 bool interruption_enabled()
-{ return fibers::scheduler::interruption_enabled_active_fiber(); }
+{ return fibers::scheduler::interruption_enabled(); }
 
 template< typename Callable >
 void at_fiber_exit( Callable ca)
 {
-	fibers::scheduler::at_exit_active_fiber(
+	fibers::scheduler::at_exit(
                 boost::bind( boost::type< void >(), ca) );
 }
 
 inline
 void at_fiber_exit( function< void() > ca)
-{ fibers::scheduler::at_exit_active_fiber( ca); }
+{ fibers::scheduler::at_exit( ca); }
 
 inline
 void at_fiber_exit( void ( * ca)() )
 {
-	fibers::scheduler::at_exit_active_fiber(
+	fibers::scheduler::at_exit(
                 boost::bind( boost::type< void >(), ca) );
 }
 
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-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -81,14 +81,6 @@
 fiber::operator!() const
 { return ! info_; }
 
-void
-fiber::swap( fiber & other)
-{ info_.swap( other.info_); }
-
-fiber::id
-fiber::get_id() const
-{ return fiber::id( info_); }
-
 bool
 fiber::operator==( fiber const& other) const
 { return get_id() == other.get_id(); }
@@ -97,6 +89,14 @@
 fiber::operator!=( fiber const& other) const
 { return !( get_id() == other.get_id() ); }
 
+void
+fiber::swap( fiber & other)
+{ info_.swap( other.info_); }
+
+fiber::id
+fiber::get_id() const
+{ return fiber::id( info_); }
+
 bool
 fiber::is_alive() const
 {
@@ -116,15 +116,14 @@
 {
         if ( ! info_) throw fiber_moved();
         info_->priority = prio;
-	if ( is_alive() ) scheduler::reschedule_fiber( get_id() );
+	if ( is_alive() ) scheduler::reschedule( get_id() );
 }
 
 void
 fiber::interrupt()
 {
         if ( ! info_) throw fiber_moved();
-	info_->interrupt &= ~detail::INTERRUPTION_DISABLED;
-	info_->interrupt |= detail::INTERRUPTION_ENABLED;
+	scheduler::interrupt( get_id() );
 }
 
 bool
@@ -136,19 +135,31 @@
 
 void
 fiber::cancel()
-{ scheduler::cancel_fiber( get_id() ); }
+{
+	if ( ! info_) throw fiber_moved();
+	scheduler::cancel( get_id() );
+}
 
 void
 fiber::suspend()
-{ scheduler::suspend_fiber( get_id() ); }
+{
+	if ( ! info_) throw fiber_moved();
+	scheduler::suspend( get_id() );
+}
 
 void
 fiber::resume()
-{ scheduler::resume_fiber( get_id() ); }
+{
+	if ( ! info_) throw fiber_moved();
+	scheduler::resume( get_id() );
+}
 
 void
 fiber::join()
-{ scheduler::join_fiber( get_id() ); }
+{
+	if ( ! info_) throw fiber_moved();
+	scheduler::join( get_id() );
+}
 
 }}
 
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-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -22,131 +22,139 @@
 { return impl_.get() != 0; }
 
 fiber::id
-scheduler::id_active_fiber()
+scheduler::get_id()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	return impl->id_active_fiber();
+	return impl->get_id();
 }
 
 void
-scheduler::yield_active_fiber()
+scheduler::yield()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->yield_active_fiber();
+	impl->yield();
 }
 
 void
-scheduler::cancel_active_fiber()
+scheduler::cancel()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->cancel_active_fiber();
+	impl->cancel();
 }
 
 void
-scheduler::suspend_active_fiber()
+scheduler::suspend()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->suspend_active_fiber();
+	impl->suspend();
 }
 
 void
-scheduler::interrupt_active_fiber()
+scheduler::interrupt()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->interrupt_active_fiber();
+	impl->interrupt();
 }
 
 bool
-scheduler::interruption_requested_active_fiber()
+scheduler::interruption_requested()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	return impl->interruption_requested_active_fiber();
+	return impl->interruption_requested();
 }
 
 bool
-scheduler::interruption_enabled_active_fiber()
+scheduler::interruption_enabled()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	return impl->interruption_enabled_active_fiber();
+	return impl->interruption_enabled();
 }
 
 detail::fiber_interrupt_t &
-scheduler::interrupt_flags_active_fiber()
+scheduler::interrupt_flags()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	return impl->interrupt_flags_active_fiber();
+	return impl->interrupt_flags();
 }
 
 int
-scheduler::priority_active_fiber()
+scheduler::priority()
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	return impl->priority_active_fiber();
+	return impl->priority();
 }
 
 void
-scheduler::priority_active_fiber( int prio)
+scheduler::priority( int prio)
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->priority_active_fiber( prio);
+	impl->priority( prio);
 }
 
 void
-scheduler::at_exit_active_fiber( callable_t ca)
+scheduler::at_exit( callable_t ca)
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->at_exit_active_fiber( ca);
+	impl->at_exit( ca);
 }
 
 void
-scheduler::cancel_fiber( fiber::id const& id)
+scheduler::interrupt( fiber::id const& id)
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->cancel_fiber( id);
+	impl->interrupt( id);
 }
 
 void
-scheduler::suspend_fiber( fiber::id const& id)
+scheduler::cancel( fiber::id const& id)
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->suspend_fiber( id);
+	impl->cancel( id);
 }
 
 void
-scheduler::resume_fiber( fiber::id const& id)
+scheduler::suspend( fiber::id const& id)
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->resume_fiber( id);
+	impl->suspend( id);
 }
 
 void
-scheduler::reschedule_fiber( fiber::id const& id)
+scheduler::resume( fiber::id const& id)
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->reschedule_fiber( id);
+	impl->resume( id);
 }
 
 void
-scheduler::join_fiber( fiber::id const& id)
+scheduler::join( fiber::id const& id)
 {
         detail::scheduler_impl * impl( impl_.get() );
         if ( ! impl) throw fiber_error("not a fiber");
-	impl->join_fiber( id);
+	impl->join( id);
+}
+
+void
+scheduler::reschedule( fiber::id const& id)
+{
+	detail::scheduler_impl * impl( impl_.get() );
+	if ( ! impl) throw fiber_error("not a fiber");
+	impl->reschedule( id);
 }
 
 detail::scheduler_impl *
@@ -174,7 +182,7 @@
 
 void
 scheduler::submit_fiber( fiber f)
-{ access_()->add_fiber( f); }
+{ access_()->add( f); }
 
 }}
 
Modified: sandbox/fiber/libs/fiber/src/scheduler_impl.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/scheduler_impl.cpp	(original)
+++ sandbox/fiber/libs/fiber/src/scheduler_impl.cpp	2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -37,8 +37,8 @@
 #define HAS_STATE_SUSPENDED( state) \
         ( state & STATE_SUSPENDED) != 0
 
-#define HAS_STATE_WAITING( state) \
-	( state & STATE_WAITING) != 0
+#define HAS_STATE_WAIT_FOR_JOIN( state) \
+	( state & STATE_WAIT_FOR_JOIN) != 0
 
 #define HAS_STATE_TERMINATED( state) \
         ( state & STATE_TERMINATED) != 0
@@ -60,173 +60,271 @@
 { fiber::convert_fiber_to_thread(); }
 
 void
-scheduler_impl::add_fiber( fiber f)
+scheduler_impl::add( fiber f)
 {
         if ( ! f) throw fiber_moved();
 
         BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
         BOOST_ASSERT( STATE_NOT_STARTED == f.info_->state);
+
+	// set state to ready
         f.info_->state = STATE_READY;
+
+	// insert fiber to fiber-list
         std::pair< std::map< fiber::id, schedulable >::iterator, bool > result(
                 fibers_.insert(
                         std::make_pair(
                                 f.get_id(),
                                 schedulable( f) ) ) );
+
+	// check result
         if ( ! result.second) throw scheduler_error("inserting fiber failed");
+
+	// put fiber to runnable-queue
         runnable_fibers_.push_back( result.first->first);
 }
 
 fiber::id
-scheduler_impl::id_active_fiber() const
+scheduler_impl::get_id() const
 { return active_.get_id(); }
 
 void
-scheduler_impl::yield_active_fiber()
+scheduler_impl::yield()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
+	// set state ready
         active_.info_->state = STATE_READY;
 
+	// put fiber to runnable-queue
         runnable_fibers_.push_back( active_.get_id() );
+
+	// switch to master-fiber
         active_.switch_to_( master_);
 }
 
 void
-scheduler_impl::cancel_active_fiber()
+scheduler_impl::cancel()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
-	active_.info_->state = STATE_TERMINATED;
-
-	terminated_fibers_.push( active_.get_id() );
+	schedulable s( fibers_[active_.get_id()]);
 
-	BOOST_FOREACH( fiber::id id__, fibers_[active_.get_id()].waiting)
+	// invoke each fiber waiting on this fiber
+	BOOST_FOREACH( fiber::id id__, s.joining_fibers)
         {
-		fiber f__( fibers_[id__].f);
-		BOOST_ASSERT( HAS_STATE_WAITING( f__.info_->state) );
-		f__.info_->state &= ~STATE_WAITING;
+		schedulable s__( fibers_[id__]);
+		fiber f__( s__.f);
+		BOOST_ASSERT( s__.waiting_on);
+		BOOST_ASSERT( active_.get_id() == * s__.waiting_on);
+		BOOST_ASSERT( HAS_STATE_WAIT_FOR_JOIN( f__.info_->state) );
+
+		// clear waiting-on
+		fibers_[id__].waiting_on.reset();
+
+		// remove wait-for-join state
+		f__.info_->state &= ~STATE_WAIT_FOR_JOIN;
+
+		// if fiber is in state ready or running and not suspended
+		// put it on runnable-queue
                 if ( ( HAS_STATE_READY( f__.info_->state) || HAS_STATE_RUNNING( f__.info_->state) )
                      && ! HAS_STATE_SUSPENDED( f__.info_->state)  )
                 {
                         f__.info_->state = STATE_READY;
-			runnable_fibers_.push_back( f__.get_id() );
+			runnable_fibers_.push_back( id__);
                 }
         }
-	fibers_[active_.get_id()].waiting.clear();
+	// clear waiting-queue
+	fibers_[active_.get_id()].joining_fibers.clear();
+
+	// set state to terminated
+	active_.info_->state = STATE_TERMINATED;
+
+	// put fiber to terminated-queue
+	terminated_fibers_.push( active_.get_id() );
 
+	// switch to master-fiber
         active_.switch_to_( master_);
 }
 
 void
-scheduler_impl::suspend_active_fiber()
+scheduler_impl::suspend()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
+	// set state suspended
         active_.info_->state |= STATE_SUSPENDED;
+
+	// switch to master-fiber
         active_.switch_to_( master_);
 }
 
 void
-scheduler_impl::interrupt_active_fiber()
+scheduler_impl::interrupt()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
+	// gets invoked by interruption-points
+	// if interruption flag is set throw fiber_interrupted
+	// exceptions
         if ( INTERRUPTION_ENABLED == active_.info_->interrupt)
                 throw fiber_interrupted();
 }
 
 bool
-scheduler_impl::interruption_requested_active_fiber() const
+scheduler_impl::interruption_requested()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
         return active_.interruption_requested();
 }
 
 bool
-scheduler_impl::interruption_enabled_active_fiber() const
+scheduler_impl::interruption_enabled()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
         return active_.info_->interrupt == detail::INTERRUPTION_ENABLED;
 }
 
 fiber_interrupt_t &
-scheduler_impl::interrupt_flags_active_fiber()
+scheduler_impl::interrupt_flags()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
         return active_.info_->interrupt;
 }
 
 int
-scheduler_impl::priority_active_fiber()
+scheduler_impl::priority()
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
         return active_.priority();
 }
 
 void
-scheduler_impl::priority_active_fiber( int prio)
+scheduler_impl::priority( int prio)
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
+	// set priority
         active_.priority( prio);
-	reschedule_fiber( active_.get_id() );
 }
 
 void
-scheduler_impl::at_exit_active_fiber( callable_t ca)
+scheduler_impl::at_exit( callable_t ca)
 {
-	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
 
+	// push a exit-callback on fibers stack
         active_.info_->at_exit.push( ca);
 }
 
 void
-scheduler_impl::cancel_fiber( fiber::id const& id)
+scheduler_impl::interrupt( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);
         if ( i == fibers_.end() ) return;
-	fiber f( i->second.f);
+	schedulable s( i->second);
+	fiber f( s.f);
+	BOOST_ASSERT( f);
+	BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
+	BOOST_ASSERT( ! HAS_STATE_NOT_STARTED( f.info_->state) );
+
+	// nothing to do for al terminated fiber
+	if ( HAS_STATE_TERMINATED( f.info_->state) ) return;
+
+	// remove disabled flag
+	f.info_->interrupt &= ~detail::INTERRUPTION_DISABLED;
+
+	// set enabled flag
+	f.info_->interrupt |= detail::INTERRUPTION_ENABLED;
+
+	// if fiber is waiting
+	if ( HAS_STATE_WAIT_FOR_JOIN( f.info_->state) )
+	{
+		// fiber is waiting (joining) on another fiber
+		// remove it from the waiting-queue, reset waiting-on
+		// and reset the waiting state
+		BOOST_ASSERT( s.waiting_on);
+		fibers_[* s.waiting_on].joining_fibers.remove( id);
+		fibers_[id].waiting_on.reset();
+		f.info_->interrupt &= ~STATE_WAIT_FOR_JOIN;
+
+		// if fiber is not suspended put it to runnable-queue
+		if ( ! HAS_STATE_SUSPENDED( f.info_->state) )
+		{
+			BOOST_ASSERT(
+					HAS_STATE_READY( f.info_->state) ||
+					HAS_STATE_RUNNING( f.info_->state) );
+			f.info_->state = STATE_READY;
+			runnable_fibers_.push_back( id);
+		}
+	}
+}	
+
+void
+scheduler_impl::cancel( fiber::id const& id)
+{
+	container::iterator i = fibers_.find( id);
+	if ( i == fibers_.end() ) return;
+	schedulable s( i->second);
+	fiber f( s.f);
         BOOST_ASSERT( f);
         BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
-	
-	if ( HAS_STATE_TERMINATED( f.info_->state) ||
-	     HAS_STATE_NOT_STARTED( f.info_->state) )
-		return;
-
-	BOOST_FOREACH( fiber::id id__, fibers_[id].waiting)
-	{
-		fiber f__( fibers_[id__].f);
-		BOOST_ASSERT( HAS_STATE_WAITING( f__.info_->state) );
-		f__.info_->state &= ~STATE_WAITING;
+	BOOST_ASSERT( ! HAS_STATE_NOT_STARTED( f.info_->state) );
+
+	// nothing to do for al terminated fiber
+	if ( HAS_STATE_TERMINATED( f.info_->state) ) return;
+
+	// invoke each fiber waiting on this fiber
+	BOOST_FOREACH( fiber::id id__, s.joining_fibers)
+	{
+		schedulable s__( fibers_[id__]);
+		fiber f__( s__.f);
+		BOOST_ASSERT( s__.waiting_on);
+		BOOST_ASSERT( HAS_STATE_WAIT_FOR_JOIN( f__.info_->state) );
+
+		// clear waiting-on
+		fibers_[id__].waiting_on.reset();
+
+		// remove wait-for-join state
+		f__.info_->state &= ~STATE_WAIT_FOR_JOIN;
+
+		// if fiber is in state ready or running and not suspended
+		// put it on runnable-queue
                 if ( ( HAS_STATE_READY( f__.info_->state) || HAS_STATE_RUNNING( f__.info_->state) )
                      && ! HAS_STATE_SUSPENDED( f__.info_->state)  )
                 {
                         f__.info_->state = STATE_READY;
-			runnable_fibers_.push_back( f__.get_id() );
+			runnable_fibers_.push_back( id__);
                 }
         }
-	fibers_[id].waiting.clear();
+	// clear waiting-queue
+	fibers_[id].joining_fibers.clear();
 
+	// if fiber is ready remove it from the runnable-queue
+	// and put it to terminated-queue
         if ( HAS_STATE_READY( f.info_->state) )
         {
                 f.info_->state = STATE_TERMINATED;
-		runnable_fibers_.remove( f.get_id() );
+		runnable_fibers_.remove( id);
                 terminated_fibers_.push( id);	
         }
+	// if fiber is running (== active fiber)
+	// put it to terminated-queue and switch
+	// to master fiber
         else if ( HAS_STATE_RUNNING( f.info_->state) )
         {
                 BOOST_ASSERT( active_.get_id() == id);
@@ -234,95 +332,137 @@
                 terminated_fibers_.push( id);
                 f.switch_to_( master_);
         }
-	else if ( HAS_STATE_WAITING( f.info_->state) )
+	// if fiber is waiting then remove it from the
+	// waiting-queue and put it to terminated-queue
+	else if ( HAS_STATE_WAIT_FOR_JOIN( f.info_->state) )
         {
+		BOOST_ASSERT( s.waiting_on);
                 f.info_->state = STATE_TERMINATED;
-		// TODO: remove from waiting-queue
+		fibers_[* s.waiting_on].joining_fibers.remove( id);
                 terminated_fibers_.push( id);	
         }
+	// suspended state is only used with one of the
+	// other states
         else
                 BOOST_ASSERT( ! "should never reached");
 }
 
 void
-scheduler_impl::suspend_fiber( fiber::id const& id)
+scheduler_impl::suspend( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);
         if ( i == fibers_.end() ) return;
         fiber f( i->second.f);
         BOOST_ASSERT( f);
         BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
-	
-	if ( HAS_STATE_TERMINATED( f.info_->state) ||
-	     HAS_STATE_NOT_STARTED( f.info_->state) )
-		return;
+	BOOST_ASSERT( ! HAS_STATE_NOT_STARTED( f.info_->state) );
+
+	// nothing to do for a terminated fiber
+	if ( HAS_STATE_TERMINATED( f.info_->state) ) return;
 
+	// if fiber is ready remove it from the
+	// runnable-queue
         if ( HAS_STATE_READY( f.info_->state) )
         {
                 f.info_->state |= STATE_SUSPENDED;
-		runnable_fibers_.remove( f.get_id() );
+		runnable_fibers_.remove( id);
         }
+	// if fiber is running (== active fiber)
+	// switch to master-fiber
         else if ( HAS_STATE_RUNNING( f.info_->state) )
         {
                 BOOST_ASSERT( active_.get_id() == id);
                 f.info_->state |= STATE_SUSPENDED;
                 f.switch_to_( master_);
         }
-	else if ( HAS_STATE_WAITING( f.info_->state) )
+	// if fiber is in waiting state mark it only
+	// as suspended
+	else if ( HAS_STATE_WAIT_FOR_JOIN( f.info_->state) )
                 f.info_->state |= STATE_SUSPENDED;
         else
                 BOOST_ASSERT( ! "should never reached");
 }
 
 void
-scheduler_impl::resume_fiber( fiber::id const& id)
+scheduler_impl::resume( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);
         if ( i == fibers_.end() ) return;
         fiber f( i->second.f);
         BOOST_ASSERT( f);
         BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
+	BOOST_ASSERT( ! HAS_STATE_NOT_STARTED( f.info_->state) );
 
         BOOST_ASSERT( active_.get_id() != id);
 
+	// nothing to do for already terminated fiber
+	if ( HAS_STATE_TERMINATED( f.info_->state) ) return;
+
+	// remove suspended state an requeue fiber
         if ( HAS_STATE_SUSPENDED( f.info_->state) )
         {
                 f.info_->state &= ~STATE_SUSPENDED;
+		// if suspended fiber was ready or running and not waiting
+		// put it to the runnable-queue
                 if ( ( HAS_STATE_READY( f.info_->state) || HAS_STATE_RUNNING( f.info_->state) )
-			 && ! HAS_STATE_WAITING( f.info_->state) )
+			 && ! HAS_STATE_WAIT_FOR_JOIN( f.info_->state) )
                 {
                         f.info_->state = STATE_READY;
-			runnable_fibers_.push_back( f.get_id() );
+			runnable_fibers_.push_back( id);
                 }
         }
 }
 
 void
-scheduler_impl::reschedule_fiber( fiber::id const& id)
+scheduler_impl::join( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);
         if ( i == fibers_.end() ) return;
-	fiber f( i->second.f);
+	schedulable s( i->second);
+	fiber f( s.f);
         BOOST_ASSERT( f);
         BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
+	BOOST_ASSERT( ! HAS_STATE_NOT_STARTED( f.info_->state) );
 
-	// TODO: re-schedule fiber == remove from
-	// runnable_fibers + re-insert
+	// nothing to do for a terminated fiber
+	if ( HAS_STATE_TERMINATED( f.info_->state) ) return;
+
+	// prevent self-join
+	if ( active_.get_id() == id) throw scheduler_error("self-join denied");
+
+	// register on fiber to be joined
+	fibers_[id].joining_fibers.push_back( active_.get_id() );
+
+	// set state waiting
+	active_.info_->state |= STATE_WAIT_FOR_JOIN;
+
+	// set fiber-id waiting-on
+	fibers_[active_.get_id()].waiting_on = id;
+
+	// switch to master-fiber
+	active_.switch_to_( master_);
+
+	// fiber was invoked
+	BOOST_ASSERT( ! HAS_STATE_WAIT_FOR_JOIN( active_.info_->state) );
+	BOOST_ASSERT( ! fibers_[active_.get_id()].waiting_on);
+
+	// check if interruption was requested
+	interrupt();
 }
 
 void
-scheduler_impl::join_fiber( fiber::id const& id)
+scheduler_impl::reschedule( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);
         if ( i == fibers_.end() ) return;
         fiber f( i->second.f);
         BOOST_ASSERT( f);
         BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
+	BOOST_ASSERT( ! HAS_STATE_NOT_STARTED( f.info_->state) );
+	BOOST_ASSERT( ! HAS_STATE_TERMINATED( f.info_->state) );
 
-	if ( active_.get_id() == id) throw scheduler_error("self-join denied");
-	fibers_[id].waiting.push_back( active_.get_id() );
-	active_.info_->state |= STATE_WAITING;
-	active_.switch_to_( master_);
+	// TODO: re-schedule fiber == remove from
+	// runnable_fibers + re-insert
 }
 
 bool
@@ -331,7 +471,9 @@
         bool result( false);
         if ( ! runnable_fibers_.empty() )
         {
-		active_ = fibers_[runnable_fibers_.front()].f;
+		schedulable s = fibers_[runnable_fibers_.front()];
+		active_ = s.f;
+		BOOST_ASSERT( ! s.waiting_on);
                 BOOST_ASSERT( active_.info_->state == STATE_READY);
                 active_.info_->state = STATE_RUNNING;
                 master_.switch_to_( active_);
@@ -339,14 +481,15 @@
                 result = true;
         }
         else
-		boost::move( active_);
+		active_.move();
 
         while ( ! terminated_fibers_.empty() )
         {
-		fiber f( fibers_[terminated_fibers_.front()].f);
+		schedulable s = fibers_[terminated_fibers_.front()];
+		fiber f( s.f);
                 terminated_fibers_.pop();
+		BOOST_ASSERT( s.joining_fibers.empty() );	
                 BOOST_ASSERT( STATE_TERMINATED == f.info_->state);	
-		BOOST_ASSERT( fibers_[f.get_id()].waiting.empty() );	
                 fibers_.erase( f.get_id() );
                 result = true;
         }
@@ -366,7 +509,7 @@
 #undef HAS_STATE_READY
 #undef HAS_STATE_RUNNING
 #undef HAS_STATE_SUSPENDED
-#undef HAS_STATE_WAITING
+#undef HAS_STATE_WAIT_FOR_JOIN
 #undef HAS_STATE_TERMINATED
 
 }}}
Modified: sandbox/fiber/libs/fiber/test/test_join.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_join.cpp	(original)
+++ sandbox/fiber/libs/fiber/test/test_join.cpp	2009-11-18 17:02:46 EST (Wed, 18 Nov 2009)
@@ -15,6 +15,7 @@
 int value1 = 0;
 int value2 = 0;
 int value3 = 0;
+bool interrupted = false;
 
 void fn_1()
 {
@@ -27,12 +28,17 @@
 
 void fn_2( boost::fiber f)
 {
-	for ( int i = 0; i < 5; ++i)
+	try
         {
-		++value2;
-		if ( i == 1) f.join();
-		boost::this_fiber::yield();
+		for ( int i = 0; i < 5; ++i)
+		{
+			++value2;
+			if ( i == 1) f.join();
+			boost::this_fiber::yield();
+		}
         }
+	catch ( boost::fibers::fiber_interrupted const&)
+	{ interrupted = true; }
 }
 
 void fn_3( boost::fiber f)
@@ -45,6 +51,16 @@
         }
 }
 
+void fn_4( boost::fiber f)
+{
+	for ( int i = 0; i < 5; ++i)
+	{
+		++value3;
+		if ( i == 3) f.interrupt();
+		boost::this_fiber::yield();
+	}
+}
+
 void test_case_1()
 {
         value1 = 0;
@@ -288,6 +304,43 @@
         BOOST_CHECK_EQUAL( 5, value3);
 }
 
+void test_case_3()
+{
+	value1 = 0;
+	value2 = 0;
+	value3 = 0;
+
+	boost::fibers::scheduler sched;
+
+	boost::fiber f1( fn_1);
+	sched.submit_fiber( f1);
+	boost::fiber f2( fn_2, f1);
+	sched.submit_fiber( f2);
+	sched.make_fiber( fn_4, f2);
+
+	BOOST_CHECK( ! sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 3), sched.size() );
+
+	BOOST_CHECK_EQUAL( 0, value1);
+	BOOST_CHECK_EQUAL( 0, value2);
+	BOOST_CHECK_EQUAL( 0, value3);
+	BOOST_CHECK_EQUAL( false, interrupted);
+
+	for (;;)
+	{
+		while ( sched.run() );
+		if ( sched.empty() ) break;
+	}
+
+	BOOST_CHECK( ! sched.run() );
+	BOOST_CHECK( sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+	BOOST_CHECK_EQUAL( 5, value1);
+	BOOST_CHECK_EQUAL( 2, value2);
+	BOOST_CHECK_EQUAL( 5, value3);
+	BOOST_CHECK_EQUAL( true, interrupted);
+}
+
 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
 {
         boost::unit_test::test_suite * test =
@@ -295,6 +348,7 @@
 
         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;
 }