$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r57600 - in sandbox/fiber: boost boost/fiber boost/fiber/detail libs/fiber/build libs/fiber/examples libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-11-12 13:56:10
Author: olli
Date: 2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
New Revision: 57600
URL: http://svn.boost.org/trac/boost/changeset/57600
Log:
- fiber-state introduced
- fifos (buffers for synch. of fibers) added
- unit tests enhanced
- test using fifo added (ping-pong)
- refactoring of rrp -> scheduler_impl (only one scheduler)
Added:
   sandbox/fiber/boost/fiber/bounded_fifo.hpp   (contents, props changed)
   sandbox/fiber/boost/fiber/detail/fiber_state.hpp   (contents, props changed)
   sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp   (contents, props changed)
   sandbox/fiber/boost/fiber/unbounded_fifo.hpp   (contents, props changed)
   sandbox/fiber/libs/fiber/examples/ping_pong.cpp   (contents, props changed)
   sandbox/fiber/libs/fiber/src/scheduler_impl.cpp   (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_scheduler.cpp   (contents, props changed)
Removed:
   sandbox/fiber/boost/fiber/policy.hpp
   sandbox/fiber/boost/fiber/rrp.hpp
   sandbox/fiber/libs/fiber/src/rrp.cpp
   sandbox/fiber/libs/fiber/test/test_rrp.cpp
Text files modified: 
   sandbox/fiber/boost/fiber.hpp                         |     2 +                                       
   sandbox/fiber/boost/fiber/detail/fiber_info_posix.hpp |    27 +-------------                          
   sandbox/fiber/boost/fiber/fiber.hpp                   |    76 ++++++++++++++++++++++++++++++--------- 
   sandbox/fiber/boost/fiber/scheduler.hpp               |    40 ++++----------------                    
   sandbox/fiber/boost/fiber/utility.hpp                 |     2                                         
   sandbox/fiber/libs/fiber/build/Jamfile.v2             |     4 +-                                      
   sandbox/fiber/libs/fiber/examples/Jamfile.v2          |     1                                         
   sandbox/fiber/libs/fiber/examples/simple.cpp          |    11 +++--                                   
   sandbox/fiber/libs/fiber/examples/simple_mt.cpp       |     6 +-                                      
   sandbox/fiber/libs/fiber/src/fiber.cpp                |    28 ++++++--------                          
   sandbox/fiber/libs/fiber/src/fiber_info_posix.cpp     |     6 ++-                                     
   sandbox/fiber/libs/fiber/src/scheduler.cpp            |    40 ++++++--------------                    
   sandbox/fiber/libs/fiber/test/Jamfile.v2              |     2                                         
   sandbox/fiber/libs/fiber/test/test_fiber.cpp          |     6 +++                                     
   14 files changed, 119 insertions(+), 132 deletions(-)
Modified: sandbox/fiber/boost/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber.hpp	(original)
+++ sandbox/fiber/boost/fiber.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -9,6 +9,7 @@
 
 #include <boost/fiber/attributes.hpp>
 #include <boost/fiber/auto_reset_event.hpp>
+#include <boost/fiber/bounded_fifo.hpp>
 #include <boost/fiber/condition.hpp>
 #include <boost/fiber/count_down_event.hpp>
 #include <boost/fiber/exceptions.hpp>
@@ -16,6 +17,7 @@
 #include <boost/fiber/manual_reset_event.hpp>
 #include <boost/fiber/mutex.hpp>
 #include <boost/fiber/scheduler.hpp>
+#include <boost/fiber/unbounded_fifo.hpp>
 #include <boost/fiber/unique_lock.hpp>
 #include <boost/fiber/utility.hpp>
 
Added: sandbox/fiber/boost/fiber/bounded_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/bounded_fifo.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -0,0 +1,304 @@
+
+//          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_BOUNDED_FIFO_H
+#define BOOST_FIBERS_BOUNDED_FIFO_H
+
+#include <cstddef>
+#include <stdexcept>
+
+#include <boost/cstdint.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/condition.hpp>
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/exceptions.hpp>
+#include <boost/fiber/mutex.hpp>
+#include <boost/fiber/unique_lock.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+
+template< typename T >
+class bounded_fifo : private noncopyable
+{
+
+public:
+	typedef optional< T >	value_type;
+
+private:
+	struct node
+	{
+		typedef intrusive_ptr< node >	ptr_t;
+
+		uint32_t	use_count;
+		value_type	va;
+		ptr_t		next;
+
+		node() :
+			use_count( 0),
+			va(),
+			next()
+		{}
+
+		inline friend void intrusive_ptr_add_ref( node * p)
+		{ ++p->use_count; }
+		
+		inline friend void intrusive_ptr_release( node * p)
+		{ if ( --p->use_count == 0) delete p; }
+	};
+
+	volatile uint32_t		state_;
+	volatile uint32_t		count_;
+	typename node::ptr_t	head_;
+	mutex					head_mtx_;
+	typename node::ptr_t	tail_;
+	mutex					tail_mtx_;
+	condition				not_empty_cond_;
+	condition				not_full_cond_;
+	std::size_t				hwm_;
+	std::size_t				lwm_;
+
+	bool active_() const
+	{ return 0 == state_; }
+
+	void deactivate_()
+	{ detail::atomic_fetch_add( & state_, 1); }
+
+	uint32_t size_()
+	{ return count_; }
+
+	bool empty_()
+	{ return head_ == get_tail_(); }
+
+	bool full_()
+	{ return size_() >= hwm_; }
+
+	typename node::ptr_t get_tail_()
+	{
+		mutex::scoped_lock lk( tail_mtx_);	
+		typename node::ptr_t tmp = tail_;
+		return tmp;
+	}
+
+	typename node::ptr_t pop_head_()
+	{
+		typename node::ptr_t old_head = head_;
+		head_ = old_head->next;
+		detail::atomic_fetch_sub( & count_, 1);
+		return old_head;
+	}
+
+public:
+	bounded_fifo(
+			std::size_t const& hwm,
+			std::size_t const& lwm) :
+		state_( 0),
+		count_( 0),
+		head_( new node),
+		head_mtx_(),
+		tail_( head_),
+		tail_mtx_(),
+		not_empty_cond_(),
+		not_full_cond_(),
+		hwm_( hwm),
+		lwm_( lwm)
+	{
+		if ( hwm_ < lwm_)
+			throw std::invalid_argument("invalid watermark");
+	}
+
+	bounded_fifo( std::size_t const& wm) :
+		state_( 0),
+		count_( 0),
+		head_( new node),
+		head_mtx_(),
+		tail_( head_),
+		tail_mtx_(),
+		not_empty_cond_(),
+		not_full_cond_(),
+		hwm_( wm),
+		lwm_( wm)
+	{}
+
+	void upper_bound_( std::size_t hwm)
+	{
+		if ( hwm < lwm_)
+			throw std::invalid_argument("invalid watermark");
+		std::size_t tmp( hwm_);
+		hwm_ = hwm;
+		if ( hwm_ > tmp) not_full_cond_.notify_one();
+	}
+
+	std::size_t upper_bound()
+	{ return hwm_; }
+
+	void lower_bound_( std::size_t lwm)
+	{
+		if ( lwm > hwm_ )
+			throw std::invalid_argument("invalid watermark");
+		std::size_t tmp( lwm_);
+		lwm_ = lwm;
+		if ( lwm_ > tmp) not_full_cond_.notify_one();
+	}
+
+	std::size_t lower_bound()
+	{ return lwm_; }
+
+	void deactivate()
+	{ deactivate_(); }
+
+	bool empty()
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		return empty_();
+	}
+
+	void put( T const& t)
+	{
+		typename node::ptr_t new_node( new node);
+		{
+			mutex::scoped_lock lk( tail_mtx_);
+
+			if ( full_() )
+			{
+				while ( active_() && full_() )
+					not_full_cond_.wait( lk);
+			}
+			if ( ! active_() )
+				throw std::runtime_error("queue is not active");
+
+			tail_->va = t;
+			tail_->next = new_node;
+			tail_ = new_node;
+			detail::atomic_fetch_add( & count_, 1);
+		}
+		not_empty_cond_.notify_one();
+	}
+
+	void put(
+		T const& t,
+		posix_time::time_duration const& rel_time)
+	{
+		typename node::sptr_t new_node( new node);
+		{
+			mutex::scoped_lock lk( tail_mtx_);
+
+			if ( full_() )
+			{
+				while ( active_() && full_() )
+					if ( ! not_full_cond_.timed_wait( lk, rel_time) )
+						throw std::runtime_error("timed out");
+			}
+			if ( ! active_() )
+				throw std::runtime_error("queue is not active");
+
+			tail_->va = t;
+			tail_->next = new_node;
+			tail_ = new_node;
+			detail::atomic_fetch_add( & count_, 1);
+		}
+		not_empty_cond_.notify_one();
+	}
+
+	bool take( value_type & va)
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		bool empty = empty_();
+		if ( ! active_() && empty)
+			return false;
+		if ( empty)
+		{
+			try
+			{
+				while ( active_() && empty_() )
+					not_empty_cond_.wait( lk);
+			}
+			catch ( fiber_interrupted const&)
+			{ return false; }
+		}
+		if ( ! active_() && empty_() )
+			return false;
+		swap( va, head_->va);
+		pop_head_();
+		if ( size_() <= lwm_)
+		{
+			if ( lwm_ == hwm_)
+				not_full_cond_.notify_one();
+			else
+				// more than one producer could be waiting
+				// for submiting an action object
+				not_full_cond_.notify_all();
+		}
+		return va;
+	}
+
+	bool take(
+		value_type & va,
+		posix_time::time_duration const& rel_time)
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		bool empty = empty_();
+		if ( ! active_() && empty)
+			return false;
+		if ( empty)
+		{
+			try
+			{
+				while ( active_() && empty_() )
+					if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
+						return false;
+			}
+			catch ( fiber_interrupted const&)
+			{ return false; }
+		}
+		if ( ! active_() && empty_() )
+			return false;
+		swap( va, head_->va);
+		pop_head_();
+		if ( size_() <= lwm_)
+		{
+			if ( lwm_ == hwm_)
+				not_full_cond_.notify_one();
+			else
+				// more than one producer could be waiting
+				// for submiting an action object
+				not_full_cond_.notify_all();
+		}
+		return va;
+	}
+
+	bool try_take( value_type & va)
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		if ( empty_() )
+			return false;
+		swap( va, head_->va);
+		pop_head_();
+		bool valid = va;
+		if ( valid && size_() <= lwm_)
+		{
+			if ( lwm_ == hwm_)
+				not_full_cond_.notify_one();
+			else
+				// more than one producer could be waiting
+				// in order to submit an task
+				not_full_cond_.notify_all();
+		}
+		return valid;
+	}
+};
+
+}}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_FIBERS_BOUNDED_FIFO_H
Modified: sandbox/fiber/boost/fiber/detail/fiber_info_posix.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/fiber_info_posix.hpp	(original)
+++ sandbox/fiber/boost/fiber/detail/fiber_info_posix.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -13,13 +13,13 @@
 
 }
 
-#include <boost/config.hpp>
 #include <boost/cstdint.hpp>
 #include <boost/intrusive_ptr.hpp>
 #include <boost/shared_array.hpp>
 
 #include <boost/fiber/attributes.hpp>
 #include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/fiber_state.hpp>
 
 #include <boost/config/abi_prefix.hpp>
 
@@ -35,6 +35,7 @@
         attributes				attrs;
         ::ucontext_t			uctx;
         shared_array< char >	uctx_stack;
+	fiber_state_t		state;
 
         static void convert_thread_to_fiber() {}
 
@@ -46,39 +47,15 @@
 
         virtual void run() = 0;
 
-#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
-
     inline friend void intrusive_ptr_add_ref( fiber_info_base * p)
     { ++p->use_count; }
 
     inline friend void intrusive_ptr_release( fiber_info_base * p)
     { if ( --p->use_count == 0) delete p; }
-
-#else
-
-    void add_ref()
-    { ++use_count; }
-
-    void release()
-    { if ( --use_count == 0) delete this; }
-
-#endif
 };
 
 }}
 
-#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
-
-inline
-void intrusive_ptr_add_ref( fiber::detail::fiber_info_base * p)
-{ p->add_ref(); }
-
-inline
-void intrusive_ptr_release( fiber::detail::fiber_info_base * p)
-{ p->release(); }
-
-#endif
-
 }
 
 #include <boost/config/abi_suffix.hpp>
Added: sandbox/fiber/boost/fiber/detail/fiber_state.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/detail/fiber_state.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -0,0 +1,35 @@
+
+//          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_DETAIL_FIBER_STATE_H
+#define BOOST_FIBERS_DETAIL_FIBER_STATE_H
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+enum fiber_state_t
+{
+	STATE_MASTER			= 0X00,
+	STATE_NOT_STARTED		= 0X10,
+	STATE_RUNNABLE			= 0x20,
+		STATE_READY		= 0x21,
+		STATE_RUNNING		= 0x22,
+	STATE_NOT_RUNNABLE		= 0x40,
+		STATE_SUSPENDED		= 0x41,
+		STATE_WAITING		= 0x42,
+	STATE_TERMINATED		= 0x80
+};
+
+}}
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_FIBERS_DETAIL_FIBER_STATE_H
Added: sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -0,0 +1,56 @@
+
+//          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_DETAIL_SCHEDULER_IMPL_H
+#define BOOST_FIBERS_DETAIL_SCHEDULER_IMPL_H
+
+#include <cstddef>
+#include <map>
+#include <queue>
+
+#include <boost/utility.hpp>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/fiber.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+class BOOST_FIBER_DECL scheduler_impl : private noncopyable
+{
+private:
+	fiber							master_;
+	fiber::id						f_id_;
+	std::map< fiber::id, fiber >	fibers_;
+	std::queue< fiber::id >			runnable_fibers_;
+	std::queue< fiber::id >			terminated_fibers_;
+
+public:
+	scheduler_impl();
+
+	void add_fiber( fiber);
+
+	fiber::id active_fiber();
+
+	void yield_active_fiber();
+
+	void terminate_active_fiber();
+
+	bool run();
+
+	bool empty();
+
+	std::size_t size();
+};
+
+}}}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_FIBERS_DETAIL_SCHEDULER_IMPL_H
Modified: sandbox/fiber/boost/fiber/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/fiber.hpp	(original)
+++ sandbox/fiber/boost/fiber/fiber.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -25,13 +25,16 @@
 
 namespace boost {
 namespace fibers {
+namespace detail {
 
-class rrp;
+class scheduler_impl;
+
+}
 
 class BOOST_FIBER_DECL fiber
 {
 private:
-	friend class rrp;
+	friend class detail::scheduler_impl;
 
         struct dummy;
 
@@ -39,35 +42,36 @@
 
         explicit fiber( detail::fiber_info_base::ptr_t);
 
-	fiber( fiber &);
-	fiber & operator=( fiber &);
-
         void init_();
 
 #ifdef BOOST_HAS_RVALUE_REFS
         template< typename Fn >
-	static detail::fiber_info_base::ptr_t make_info_( Fn && fn)
+	static detail::fiber_info_base::ptr_t make_info_(
+		attributes attrs, Fn && fn)
         {
                 return detail::fiber_info_base::ptr_t(
                         new detail::fiber_info< typename remove_reference< Fn >::type >(
-				static_cast< Fn && >( fn), attributes() ) );
+				static_cast< Fn && >( fn), attrs) );
         }
 
-	static detail::fiber_info_base::ptr_t make_info_( void ( * fn)() );
+	static detail::fiber_info_base::ptr_t make_info_(
+		attributes attrs, void ( * fn)() );
 #else
         template< typename Fn >
-	static detail::fiber_info_base::ptr_t make_info_( Fn fn)
+	static detail::fiber_info_base::ptr_t make_info_(
+		attributes attrs, Fn fn)
         {
                 return detail::fiber_info_base::ptr_t(
-			new detail::fiber_info< Fn >( fn, attributes() ) );
+			new detail::fiber_info< Fn >( fn, attrs) );
         }
 
         template< typename Fn >
         static detail::fiber_info_base::ptr_t make_info_(
+		attributes attrs,
                 boost::detail::fiber_move_t< Fn > fn)
         {
                 return detail::fiber_info_base::ptr_t(
-			new detail::fiber_info< Fn >( fn, attributes() ) );
+			new detail::fiber_info< Fn >( fn, attrs) );
         }
 #endif
 
@@ -81,7 +85,11 @@
 #ifdef BOOST_HAS_RVALUE_REFS
         template< typename Fn >
         fiber( Fn && fn) :
-		info_( make_info_( static_cast< Fn && >( fn) ) )
+		info_( make_info_( attributes(), static_cast< Fn && >( fn) ) )
+	{ init_(); }
+
+	fiber( attributes attrs, Fn && fn) :
+		info_( make_info_( attrs, static_cast< Fn && >( fn) ) )
         { init_(); }
 
         fiber( fiber &&);
@@ -93,19 +101,37 @@
 #ifdef BOOST_NO_SFINAE
         template< typename Fn >
         explicit fiber( Fn fn) :
-		info_( make_info_( fn) )
+		info_( make_info_( attributes(), fn) )
+	{ init_(); }
+
+	template< typename Fn >
+	explicit fiber( attributes attrs, Fn fn) :
+		info_( make_info_( attrs, fn) )
         { init_(); }
 #else
         template< typename Fn >
         explicit fiber(
                         Fn fn,
                         typename disable_if< boost::is_convertible< Fn &, boost::detail::fiber_move_t< Fn > >, dummy * >::type = 0) :
-		info_( make_info_( fn) )
+		info_( make_info_( attributes(), fn) )
+	{ init_(); }
+
+	template< typename Fn >
+	explicit fiber(
+			attributes attrs,
+			Fn fn,
+			typename disable_if< boost::is_convertible< Fn &, boost::detail::fiber_move_t< Fn > >, dummy * >::type = 0) :
+		info_( make_info_( attrs, fn) )
         { init_(); }
 #endif
         template< typename Fn >
         explicit fiber( boost::detail::fiber_move_t< Fn > fn) :
-		info_( make_info_( fn) )
+		info_( make_info_( attributes(), fn) )
+	{ init_(); }
+
+	template< typename Fn >
+	explicit fiber( attributes attrs, boost::detail::fiber_move_t< Fn > fn) :
+		info_( make_info_( attrs, fn) )
         { init_(); }
 
         fiber( boost::detail::fiber_move_t< fiber >);
@@ -126,8 +152,16 @@
         fiber( Fn fn, BOOST_ENUM_FIBER_ARGS(n)) : \
                 info_( \
                         make_info_( \
+				attributes(), \
                                 boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a)) ) ) \
         { init_(); } \
+	template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
+	fiber( attributes attrs, Fn fn, BOOST_ENUM_FIBER_ARGS(n)) : \
+		info_( \
+			make_info_( \
+				attrs, \
+				boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a)) ) ) \
+	{ init_(); }
 
 #ifndef BOOST_FIBER_MAX_ARITY
 #define BOOST_FIBER_MAX_ARITY 10
@@ -147,12 +181,11 @@
 
         id get_id() const;
 
-	attributes const& get_attributes() const;
-	void set_attributes( attributes const&);
-
         bool operator==( fiber const& other) const;
         bool operator!=( fiber const& other) const;
 
+	bool is_alive() const;
+
         void switch_to( fiber &);
 };
 
@@ -205,10 +238,17 @@
 fiber make_fiber( Fn fn)
 { return fiber( fn); }
 
+template< typename Fn >
+fiber make_fiber( attributes attrs, Fn fn)
+{ return fiber( attrs, fn); }
+
 #define BOOST_FIBER_make_info_FUNCTION(z, n, unused) \
 template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
 fiber make_fiber( Fn fn, BOOST_ENUM_FIBER_ARGS(n)) \
 { return fiber( fn, BOOST_PP_ENUM_PARAMS(n, a) ); } \
+template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
+fiber make_fiber( attributes attrs, Fn fn, BOOST_ENUM_FIBER_ARGS(n)) \
+{ return fiber( attrs, fn, BOOST_PP_ENUM_PARAMS(n, a) ); }
 
 BOOST_PP_REPEAT_FROM_TO( 1, BOOST_FIBER_MAX_ARITY, BOOST_FIBER_make_info_FUNCTION, ~)
 
Deleted: sandbox/fiber/boost/fiber/policy.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/policy.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
+++ (empty file)
@@ -1,48 +0,0 @@
-
-//          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_POLICY_H
-#define BOOST_FIBERS_POLICY_H
-
-#include <cstddef>
-#include <memory>
-
-#include <boost/fiber/fiber.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost {
-namespace fibers {
-
-struct policy
-{
-	virtual ~policy() {}
-
-	virtual void add_fiber( std::auto_ptr< fiber >) = 0;
-
-	virtual fiber::id active_fiber() = 0;
-
-	virtual void yield_active_fiber() = 0;
-
-	virtual void exit_active_fiber() = 0;
-
-	virtual bool run() = 0;
-
-	virtual bool empty() = 0;
-
-	virtual std::size_t size() = 0;
-};
-
-enum policy_t
-{
-	round_robin_policy = 0
-};
-
-}}
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_FIBERS_POLICY_H
Deleted: sandbox/fiber/boost/fiber/rrp.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/rrp.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
+++ (empty file)
@@ -1,58 +0,0 @@
-
-//          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_RRP_H
-#define BOOST_FIBERS_RRP_H
-
-#include <cstddef>
-#include <memory>
-#include <queue>
-
-#include <boost/ptr_container/ptr_map.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/fiber/detail/config.hpp>
-#include <boost/fiber/fiber.hpp>
-#include <boost/fiber/policy.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost {
-namespace fibers {
-
-class BOOST_FIBER_DECL rrp : private noncopyable,
-							 public policy
-{
-private:
-	fiber						master_;
-	fiber::id					f_id_;
-	ptr_map< fiber::id, fiber >	fibers_;
-	std::queue< fiber::id >		runnable_fibers_;
-	std::queue< fiber::id >		dead_fibers_;
-
-public:
-	rrp();
-
-	void add_fiber( std::auto_ptr< fiber >);
-
-	fiber::id active_fiber();
-
-	void yield_active_fiber();
-
-	void exit_active_fiber();
-
-	bool run();
-
-	bool empty();
-
-	std::size_t size();
-};
-
-}}
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_FIBERS_RRP_H
Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp	(original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -16,9 +16,8 @@
 
 #include <boost/fiber/attributes.hpp>
 #include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/scheduler_impl.hpp>
 #include <boost/fiber/fiber.hpp>
-#include <boost/fiber/policy.hpp>
-#include <boost/fiber/rrp.hpp>
 
 #include <boost/config/abi_prefix.hpp>
 
@@ -43,9 +42,9 @@
         friend void this_fiber::yield();
         friend void this_fiber::cancel();
 
-	typedef thread_specific_ptr< policy >	tss_policy_t;
+	typedef thread_specific_ptr< detail::scheduler_impl >	tss_impl_t;
 
-	static tss_policy_t	impl_;
+	static tss_impl_t	impl_;
 
         static bool runs_as_fiber();
 
@@ -53,17 +52,13 @@
 
         static void fiber_yield();
 
-	static void fiber_exit();
+	static void fiber_terminate();
 
         static void fiber_failed();
 
-	policy_t	pol_;
-
-	policy * access_();
+	detail::scheduler_impl * access_();
 
 public:
-	scheduler( policy_t = round_robin_policy);
-
         ~scheduler();
 
         bool run();
@@ -76,19 +71,11 @@
 
         template< typename Fn >
         void make_fiber( Fn fn)
-	{
-		access_()->add_fiber(
-			std::auto_ptr< fiber >(
-				new fiber( fn) ) );
-	}
+	{ access_()->add_fiber( fiber( fn) ); }
 
         template< typename Fn >
         void make_fiber( attributes attrs, Fn fn)
-	{
-		std::auto_ptr< fiber > f( new fiber( fn) );
-		f->set_attributes( attrs);
-		access_()->add_fiber( f);
-	}
+	{ access_()->add_fiber( fiber( attrs, fn) ); }
 
 #ifndef BOOST_FIBER_MAX_ARITY
 #define BOOST_FIBER_MAX_ARITY 10
@@ -101,19 +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( \
-			std::auto_ptr< fiber >( \
-				new fiber( fn, BOOST_PP_ENUM_PARAMS(n, a) ) ) ); \
-	} \
+	{ access_()->add_fiber( fiber( fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); } \
         template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
         void make_fiber( attributes const& attrs, Fn fn, BOOST_ENUM_FIBER_ARGS(n)) \
-	{ \
-		std::auto_ptr< fiber > f( \
-			new fiber( fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); \
-		f->set_attributes( attrs); \
-		access_()->add_fiber( f);\
-	}
+	{ access_()->add_fiber( fiber( attrs, 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/unbounded_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/unbounded_fifo.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -0,0 +1,185 @@
+
+//          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_UNBOUNDED_FIFO_H
+#define BOOST_FIBERS_UNBOUNDED_FIFO_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/condition.hpp>
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/exceptions.hpp>
+#include <boost/fiber/mutex.hpp>
+#include <boost/fiber/unique_lock.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+
+template< typename T >
+class unbounded_fifo : private noncopyable
+{
+
+public:
+	typedef optional< T >	value_type;
+
+private:
+	struct node
+	{
+		typedef intrusive_ptr< node >	ptr_t;
+
+		uint32_t	use_count;
+		value_type	va;
+		ptr_t		next;
+
+		node() :
+			use_count( 0),
+			va(),
+			next()
+		{}
+
+		inline friend void intrusive_ptr_add_ref( node * p)
+		{ ++p->use_count; }
+		
+		inline friend void intrusive_ptr_release( node * p)
+		{ if ( --p->use_count == 0) delete p; }
+	};
+
+	volatile uint32_t		state_;
+	typename node::ptr_t	head_;
+	mutex					head_mtx_;
+	typename node::ptr_t	tail_;
+	mutex					tail_mtx_;
+	condition				not_empty_cond_;
+
+	bool active_() const
+	{ return 0 == state_; }
+
+	void deactivate_()
+	{ detail::atomic_fetch_add( & state_, 1); }
+
+	bool empty_()
+	{ return head_ == get_tail_(); }
+
+	typename node::ptr_t get_tail_()
+	{
+		mutex::scoped_lock lk( tail_mtx_);	
+		typename node::ptr_t tmp = tail_;
+		return tmp;
+	}
+
+	typename node::ptr_t pop_head_()
+	{
+		typename node::ptr_t old_head = head_;
+		head_ = old_head->next;
+		return old_head;
+	}
+
+public:
+	unbounded_fifo() :
+		state_( 0),
+		head_( new node),
+		head_mtx_(),
+		tail_( head_),
+		tail_mtx_(),
+		not_empty_cond_()
+	{}
+
+	void deactivate()
+	{ deactivate_(); }
+
+	bool empty()
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		return empty_();
+	}
+
+	void put( T const& t)
+	{
+		typename node::ptr_t new_node( new node);
+		{
+			mutex::scoped_lock lk( tail_mtx_);
+
+			tail_->va = t;
+			tail_->next = new_node;
+			tail_ = new_node;
+		}
+		not_empty_cond_.notify_one();
+	}
+
+	bool take( value_type & va)
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		bool empty = empty_();
+		if ( ! active_() && empty)
+			return false;
+		if ( empty)
+		{
+			try
+			{
+				while ( active_() && empty_() )
+					not_empty_cond_.wait( lk);
+			}
+			catch ( fiber_interrupted const&)
+			{ return false; }
+		}
+		if ( ! active_() && empty_() )
+			return false;
+		swap( va, head_->va);
+		pop_head_();
+		return va;
+	}
+
+	bool take(
+		value_type & va,
+		posix_time::time_duration const& rel_time)
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		bool empty = empty_();
+		if ( ! active_() && empty)
+			return false;
+		if ( empty)
+		{
+			try
+			{
+				while ( active_() && empty_() )
+					if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
+						return false;
+			}
+			catch ( fiber_interrupted const&)
+			{ return false; }
+		}
+		if ( ! active_() && empty_() )
+			return false;
+		swap( va, head_->va);
+		pop_head_();
+		return va;
+	}
+
+	bool try_take( value_type & va)
+	{
+		mutex::scoped_lock lk( head_mtx_);
+		if ( empty_() )
+			return false;
+		swap( va, head_->va);
+		pop_head_();
+		return va;
+	}
+};
+
+}}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_FIBERS_UNBOUNDED_FIFO_H
Modified: sandbox/fiber/boost/fiber/utility.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/utility.hpp	(original)
+++ sandbox/fiber/boost/fiber/utility.hpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -33,7 +33,7 @@
 
 inline
 void cancel()
-{ fibers::scheduler::fiber_exit(); }
+{ fibers::scheduler::fiber_terminate(); }
 
 }}
 
Modified: sandbox/fiber/libs/fiber/build/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/build/Jamfile.v2	(original)
+++ sandbox/fiber/libs/fiber/build/Jamfile.v2	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -44,8 +44,8 @@
         fiber_windows.cpp
         manual_reset_event.cpp
         mutex.cpp
-	rrp.cpp
         scheduler.cpp
+	scheduler_impl.cpp
     : ## requirements ##
       <fiberapi>win32
     ;
@@ -61,8 +61,8 @@
         fiber_posix.cpp
         manual_reset_event.cpp
         mutex.cpp
-	rrp.cpp
         scheduler.cpp
+	scheduler_impl.cpp
     : ## requirements ##
       <fiberapi>posix
     ;
Modified: sandbox/fiber/libs/fiber/examples/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/examples/Jamfile.v2	(original)
+++ sandbox/fiber/libs/fiber/examples/Jamfile.v2	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -25,3 +25,4 @@
 
 exe simple : simple.cpp ;
 exe simple_mt : simple_mt.cpp ;
+exe ping_pong : ping_pong.cpp ;
Added: sandbox/fiber/libs/fiber/examples/ping_pong.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/examples/ping_pong.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -0,0 +1,102 @@
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+#include <boost/assert.hpp>
+#include <boost/ref.hpp>
+#include <boost/optional.hpp>
+#include <boost/system/system_error.hpp>
+
+#include <boost/fiber.hpp>
+
+typedef boost::fibers::unbounded_fifo< std::string >	fifo_t;
+typedef boost::shared_ptr< fifo_t >			fifo_ptr_t;
+inline
+void ping(
+		fifo_ptr_t & recv_buf,
+		fifo_ptr_t & send_buf)
+{
+	boost::optional< std::string > value;
+
+	send_buf->put("ping");
+	BOOST_ASSERT( recv_buf->take( value) );
+	std::cout << * value << std::endl;
+	value.reset();
+
+	send_buf->put("ping");
+	BOOST_ASSERT( recv_buf->take( value) );
+	std::cout << * value << std::endl;
+	value.reset();
+
+	send_buf->put("ping");
+	BOOST_ASSERT( recv_buf->take( value) );
+	std::cout << * value << std::endl;
+	value.reset();
+
+	send_buf->deactivate();
+}
+
+inline
+void pong(
+		fifo_ptr_t & recv_buf,
+		fifo_ptr_t & send_buf)
+{
+	boost::optional< std::string > value;
+
+	BOOST_ASSERT( recv_buf->take( value) );
+	std::cout << * value << std::endl;
+	value.reset();
+	send_buf->put("pong");
+
+	BOOST_ASSERT( recv_buf->take( value) );
+	std::cout << * value << std::endl;
+	value.reset();
+	send_buf->put("pong");
+
+	BOOST_ASSERT( recv_buf->take( value) );
+	std::cout << * value << std::endl;
+	value.reset();
+	send_buf->put("pong");
+
+	send_buf->deactivate();
+}
+
+void f( boost::fibers::scheduler & sched)
+{
+	fifo_ptr_t buf1( new fifo_t() );
+	fifo_ptr_t buf2( new fifo_t() );
+	
+	sched.make_fiber( & ping, buf1, buf2);
+	sched.make_fiber( & pong, buf2, buf1);
+}
+
+int main()
+{
+	try
+	{
+		boost::fibers::scheduler sched;
+
+		sched.make_fiber( & f, boost::ref( sched) );
+
+		std::cout << "start" << std::endl;
+
+		for (;;)
+		{
+			while ( sched.run() );
+			if ( sched.empty() ) break;
+		}
+
+		std::cout << "finish" << std::endl;
+
+		return EXIT_SUCCESS;
+	}
+	catch ( boost::system::system_error const& e)
+	{ std::cerr << "system_error: " << e.code().value() << std::endl; }
+	catch ( boost::fibers::scheduler_error const& e)
+	{ std::cerr << "scheduler_error: " << e.what() << std::endl; }
+	catch ( std::exception const& e)
+	{ std::cerr << "exception: " << e.what() << std::endl; }
+	catch (...)
+	{ std::cerr << "unhandled exception" << std::endl; }
+	return EXIT_FAILURE;
+}
Modified: sandbox/fiber/libs/fiber/examples/simple.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/examples/simple.cpp	(original)
+++ sandbox/fiber/libs/fiber/examples/simple.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -8,7 +8,7 @@
 #include <boost/fiber.hpp>
 
 inline
-void f( std::string const& str, int n)
+void fn( std::string const& str, int n)
 {
         for ( int i = 0; i < n; ++i)
         {
@@ -21,10 +21,11 @@
 {
         try
         {
-		boost::fiber::scheduler sched;
+		boost::fibers::scheduler sched;
 
-		sched.make_fiber( & f, "abc", 5);
-		sched.make_fiber( & f, "xyz", 7);
+		boost::fiber f( fn, "abc", 5);
+		sched.submit_fiber( boost::move( f) );
+		sched.make_fiber( & fn, "xyz", 7);
 
                 std::cout << "start" << std::endl;
 
@@ -40,7 +41,7 @@
         }
         catch ( boost::system::system_error const& e)
         { std::cerr << "system_error: " << e.code().value() << std::endl; }
-	catch ( boost::fiber::scheduler_error const& e)
+	catch ( boost::fibers::scheduler_error const& e)
         { std::cerr << "scheduler_error: " << e.what() << std::endl; }
         catch ( std::exception const& e)
         { std::cerr << "exception: " << e.what() << std::endl; }
Modified: sandbox/fiber/libs/fiber/examples/simple_mt.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/examples/simple_mt.cpp	(original)
+++ sandbox/fiber/libs/fiber/examples/simple_mt.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -25,7 +25,7 @@
 
 void run_thread(
                 boost::barrier & b,
-		boost::fiber::scheduler & sched,
+		boost::fibers::scheduler & sched,
                 std::string const& msg, int n)
 {
                 std::ostringstream os;
@@ -47,7 +47,7 @@
 {
         try
         {
-		boost::fiber::scheduler sched;
+		boost::fibers::scheduler sched;
 
                 std::cout << "start" << std::endl;
 
@@ -70,7 +70,7 @@
         }
         catch ( boost::system::system_error const& e)
         { std::cerr << "system_error: " << e.code().value() << std::endl; }
-	catch ( boost::fiber::scheduler_error const& e)
+	catch ( boost::fibers::scheduler_error const& e)
         { std::cerr << "scheduler_error: " << e.what() << std::endl; }
         catch ( std::exception const& e)
         { std::cerr << "exception: " << e.what() << std::endl; }
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-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -8,6 +8,7 @@
 
 #include <boost/assert.hpp>
 
+#include <boost/fiber/detail/fiber_state.hpp>
 #include <boost/fiber/exceptions.hpp>
 
 #include <boost/config/abi_prefix.hpp>
@@ -21,10 +22,10 @@
 
 #ifdef BOOST_HAS_RVALUE_REFS
 detail::fiber_info_base::ptr_t
-fiber::make_info_( void ( * fn)() )
+fiber::make_info_( attributes attrs, void ( * fn)() )
 {
         return detail::fiber_info_base::ptr_t(
-		new detail::fiber_info< void( *)() >( fn, attributes() ) );
+		new detail::fiber_info< void( *)() >( fn, attrs) );
 }
 #endif
 
@@ -91,20 +92,6 @@
 fiber::get_id() const
 { return fiber::id( info_); }
 
-attributes const&
-fiber::get_attributes() const
-{
-	if ( ! info_) throw fiber_moved();
-	return info_->attrs;
-}
-
-void
-fiber::set_attributes( attributes const& attrs)
-{
-	if ( ! info_) throw fiber_moved();
-	info_->attrs = attrs;
-}
-
 bool
 fiber::operator==( fiber const& other) const
 { return get_id() == other.get_id(); }
@@ -113,6 +100,15 @@
 fiber::operator!=( fiber const& other) const
 { return !( get_id() == other.get_id() ); }
 
+bool
+fiber::is_alive() const
+{
+	if ( ! info_)
+		throw fiber_moved();
+	return ( info_->state & detail::STATE_RUNNABLE) == detail::STATE_RUNNABLE ||
+		( info_->state & detail::STATE_NOT_RUNNABLE) == detail::STATE_NOT_RUNNABLE;
+}
+
 }}
 
 #include <boost/config/abi_suffix.hpp>
Modified: sandbox/fiber/libs/fiber/src/fiber_info_posix.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/fiber_info_posix.cpp	(original)
+++ sandbox/fiber/libs/fiber/src/fiber_info_posix.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -20,13 +20,15 @@
 fiber_info_base::fiber_info_base() :
         attrs(),
         uctx(),
-	uctx_stack()
+	uctx_stack(),
+	state( STATE_MASTER)
 {}
 
 fiber_info_base::fiber_info_base( attributes const& attrs_) :
         attrs( attrs_),
         uctx(),
-	uctx_stack( new char[attrs.stack_size()])
+	uctx_stack( new char[attrs.stack_size()]),
+	state( STATE_NOT_STARTED)
 {
         BOOST_ASSERT( uctx_stack);
 
Deleted: sandbox/fiber/libs/fiber/src/rrp.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/rrp.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
+++ (empty file)
@@ -1,88 +0,0 @@
-
-//          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/rrp.hpp>
-
-#include <utility>
-
-#include <boost/fiber/detail/fiber_info.hpp>
-#include <boost/fiber/detail/move.hpp>
-#include <boost/fiber/exceptions.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost {
-namespace fibers {
-
-rrp::rrp() :
-	master_(
-		detail::fiber_info_base::ptr_t(
-			new detail::fiber_info_default() ) ),
-	f_id_(),
-	fibers_(),
-	runnable_fibers_(),
-	dead_fibers_()
-{}
-
-void
-rrp::add_fiber( std::auto_ptr< fiber > f)
-{
-	fiber::id id( f->get_id() );
-	std::pair< ptr_map< fiber::id, fiber >::iterator, bool > result(
-		fibers_.insert( id, f) );
-	if ( ! result.second) throw scheduler_error("inserting fiber failed");
-	runnable_fibers_.push( result.first->first);
-}
-
-fiber::id
-rrp::active_fiber()
-{ return f_id_; }
-
-void
-rrp::yield_active_fiber()
-{
-	runnable_fibers_.push( f_id_);
-	fibers_[f_id_].switch_to( master_);
-}
-
-void
-rrp::exit_active_fiber()
-{
-	dead_fibers_.push( f_id_);
-	fibers_[f_id_].switch_to( master_);
-}
-
-bool
-rrp::run()
-{
-	bool result( false);
-	if ( ! runnable_fibers_.empty() )
-	{
-		f_id_ = runnable_fibers_.front();
-		master_.switch_to( fibers_[f_id_]);
-		runnable_fibers_.pop();
-		result = true;
-	}
-	if ( ! dead_fibers_.empty() )
-	{
-		fibers_.erase( dead_fibers_.front() );
-		dead_fibers_.pop();
-		result = true;
-	}
-	return result;
-}
-
-bool
-rrp::empty()
-{ return fibers_.empty(); }
-
-std::size_t
-rrp::size()
-{ return fibers_.size(); }
-
-}}
-
-#include <boost/config/abi_suffix.hpp>
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-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -7,15 +7,15 @@
 #include <boost/fiber/scheduler.hpp>
 
 #include <boost/fiber/detail/move.hpp>
+#include <boost/fiber/detail/scheduler_impl.hpp>
 #include <boost/fiber/exceptions.hpp>
-#include <boost/fiber/rrp.hpp>
 
 #include <boost/config/abi_prefix.hpp>
 
 namespace boost {
 namespace fibers {
 
-scheduler::tss_policy_t scheduler::impl_;
+scheduler::tss_impl_t scheduler::impl_;
 
 bool
 scheduler::runs_as_fiber()
@@ -24,7 +24,7 @@
 fiber::id
 scheduler::get_id()
 {
-	policy * impl( impl_.get() );
+	detail::scheduler_impl * impl( impl_.get() );
         if (  ! impl) throw fiber_error("not a fiber");
         return impl->active_fiber();
 }
@@ -32,45 +32,34 @@
 void
 scheduler::fiber_yield()
 {
-	policy * impl( impl_.get() );
+	detail::scheduler_impl * impl( impl_.get() );
         if (  ! impl) throw fiber_error("not a fiber");
         impl->yield_active_fiber();
 }
 
 void
-scheduler::fiber_exit()
+scheduler::fiber_terminate()
 {
-	policy * impl( impl_.get() );
+	detail::scheduler_impl * impl( impl_.get() );
         if (  ! impl) throw fiber_error("not a fiber");
-	impl->exit_active_fiber();
+	impl->terminate_active_fiber();
 }
 
 void
 scheduler::fiber_failed()
 {
-	policy * impl( impl_.get() );
+	detail::scheduler_impl * impl( impl_.get() );
         if (  ! impl) throw fiber_error("not a fiber");
-	impl->exit_active_fiber();
+	impl->terminate_active_fiber();
 }
 
-scheduler::scheduler( policy_t pol) :
-	pol_( pol)
-{}
-
-policy *
+detail::scheduler_impl *
 scheduler::access_()
 {
         if ( ! impl_.get() )
         {
                 fiber::convert_thread_to_fiber();
-		switch ( pol_)
-		{
-		case round_robin_policy:
-			impl_.reset( new rrp() );
-			break;
-		default:
-			throw scheduler_error("invalid scheduling policy");
-		}
+		impl_.reset( new detail::scheduler_impl() );
         }
         return impl_.get();
 }
@@ -92,12 +81,7 @@
 
 void
 scheduler::submit_fiber( fiber f)
-{
-	access_()->add_fiber(
-		std::auto_ptr< fiber >(
-			new fiber(
-				boost::move( f) ) ) );
-}
+{ access_()->add_fiber( f); }
 
 }}
 
Added: sandbox/fiber/libs/fiber/src/scheduler_impl.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/src/scheduler_impl.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 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/detail/scheduler_impl.hpp>
+
+#include <utility>
+
+#include <boost/assert.hpp>
+
+#include <boost/fiber/detail/fiber_info.hpp>
+#include <boost/fiber/detail/move.hpp>
+#include <boost/fiber/detail/fiber_state.hpp>
+#include <boost/fiber/exceptions.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+scheduler_impl::scheduler_impl() :
+	master_(
+		detail::fiber_info_base::ptr_t(
+			new detail::fiber_info_default() ) ),
+	f_id_(),
+	fibers_(),
+	runnable_fibers_(),
+	terminated_fibers_()
+{}
+
+void
+scheduler_impl::add_fiber( fiber f)
+{
+	if ( ! f) throw fiber_moved();
+	fiber::id id( f.get_id() );
+	BOOST_ASSERT( f.info_->state == detail::STATE_NOT_STARTED);
+	f.info_->state = detail::STATE_READY;
+	std::pair< std::map< fiber::id, fiber >::iterator, bool > result(
+		fibers_.insert( std::make_pair( id, f) ) );
+	if ( ! result.second) throw scheduler_error("inserting fiber failed");
+	runnable_fibers_.push( result.first->first);
+}
+
+fiber::id
+scheduler_impl::active_fiber()
+{ return f_id_; }
+
+void
+scheduler_impl::yield_active_fiber()
+{
+	BOOST_ASSERT( fibers_[f_id_].info_->state == detail::STATE_RUNNING);
+	fibers_[f_id_].info_->state = detail::STATE_READY;
+	runnable_fibers_.push( f_id_);
+	fibers_[f_id_].switch_to( master_);
+}
+
+void
+scheduler_impl::terminate_active_fiber()
+{
+	BOOST_ASSERT( fibers_[f_id_].info_->state == detail::STATE_RUNNING);
+	fibers_[f_id_].info_->state = detail::STATE_TERMINATED;
+	terminated_fibers_.push( f_id_);
+	fibers_[f_id_].switch_to( master_);
+}
+
+bool
+scheduler_impl::run()
+{
+	bool result( false);
+	if ( ! runnable_fibers_.empty() )
+	{
+		f_id_ = runnable_fibers_.front();
+		BOOST_ASSERT( fibers_[f_id_].info_->state == detail::STATE_READY);
+		fibers_[f_id_].info_->state = detail::STATE_RUNNING;
+		master_.switch_to( fibers_[f_id_]);
+		runnable_fibers_.pop();
+		result = true;
+	}
+	while ( ! terminated_fibers_.empty() )
+	{
+		BOOST_ASSERT( fibers_[terminated_fibers_.front()].info_->state == detail::STATE_TERMINATED);	
+		fibers_.erase( terminated_fibers_.front() );
+		terminated_fibers_.pop();
+		result = true;
+	}
+	return result;
+}
+
+bool
+scheduler_impl::empty()
+{ return fibers_.empty(); }
+
+std::size_t
+scheduler_impl::size()
+{ return fibers_.size(); }
+
+}}}
+
+#include <boost/config/abi_suffix.hpp>
Modified: sandbox/fiber/libs/fiber/test/Jamfile.v2
==============================================================================
--- sandbox/fiber/libs/fiber/test/Jamfile.v2	(original)
+++ sandbox/fiber/libs/fiber/test/Jamfile.v2	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -26,7 +26,7 @@
 
 test-suite fiber :
     [ fiber-test test_fiber ]
-    [ fiber-test test_rrp ]
+    [ fiber-test test_scheduler ]
     [ fiber-test test_utility ]
     [ fiber-test test_mutex ]
     [ fiber-test test_auto_reset_event ]
Modified: sandbox/fiber/libs/fiber/test/test_fiber.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_fiber.cpp	(original)
+++ sandbox/fiber/libs/fiber/test/test_fiber.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -24,6 +24,7 @@
         boost::fiber f2;
         BOOST_CHECK( f1);
         BOOST_CHECK( ! f2);
+	BOOST_CHECK( ! f1.is_alive() );
 }
 
 void test_case_2()
@@ -42,6 +43,11 @@
         boost::fiber f2( boost::move( f1) );
         BOOST_CHECK( ! f1);
         BOOST_CHECK( f2);
+	boost::fiber f3;
+	BOOST_CHECK( ! f3);
+	f3 = f2;
+	BOOST_CHECK( f3);
+	BOOST_CHECK_EQUAL( f2, f3);
 }
 
 void test_case_4()
Deleted: sandbox/fiber/libs/fiber/test/test_rrp.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_rrp.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
+++ (empty file)
@@ -1,85 +0,0 @@
-
-//          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 <sstream>
-#include <string>
-
-#include <boost/test/unit_test.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/fiber.hpp>
-
-int value1 = 0;
-int value2 = 0;
-
-void zero_args_fn() {}
-
-void value1_fn()
-{ value1 = 1; }
-
-void value2_fn()
-{ value2 = 1; }
-
-void test_case_1()
-{
-	boost::fibers::scheduler sched( boost::fibers::round_robin_policy);
-	BOOST_CHECK( sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
-	BOOST_CHECK( ! sched.run() );
-
-	boost::fiber f( boost::fibers::make_fiber( zero_args_fn) );
-	sched.submit_fiber( boost::move( f) );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
-
-	sched.submit_fiber(
-		boost::fibers::make_fiber( zero_args_fn) );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
-
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
-
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
-}
-
-void test_case_2()
-{
-	boost::fibers::scheduler sched( boost::fibers::round_robin_policy);
-
-	sched.make_fiber( value1_fn);
-	sched.make_fiber( value2_fn);
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
-	BOOST_CHECK_EQUAL( 0, value1);
-	BOOST_CHECK_EQUAL( 0, value2);
-
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	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( sched.empty() );
-	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::test_suite * test =
-		BOOST_TEST_SUITE("Boost.Fiber: rrp 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_scheduler.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_scheduler.cpp	2009-11-12 13:56:07 EST (Thu, 12 Nov 2009)
@@ -0,0 +1,89 @@
+
+//          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 <sstream>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+int value1 = 0;
+int value2 = 0;
+
+void zero_args_fn() {}
+
+void value1_fn()
+{ value1 = 1; }
+
+void value2_fn()
+{ value2 = 1; }
+
+void test_case_1()
+{
+	boost::fibers::scheduler sched;
+	BOOST_CHECK( sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+	BOOST_CHECK( ! sched.run() );
+
+	boost::fiber f( boost::fibers::make_fiber( zero_args_fn) );
+	BOOST_CHECK( ! f.is_alive() );
+	sched.submit_fiber( f);
+	BOOST_CHECK( f.is_alive() );
+	BOOST_CHECK( ! sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+
+	sched.submit_fiber(
+		boost::fibers::make_fiber( zero_args_fn) );
+	BOOST_CHECK( ! sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+
+	BOOST_CHECK( sched.run() );
+	BOOST_CHECK( ! sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
+
+	BOOST_CHECK( sched.run() );
+	BOOST_CHECK( sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+
+	BOOST_CHECK( ! f.is_alive() );
+}
+
+void test_case_2()
+{
+	boost::fibers::scheduler sched;
+
+	sched.make_fiber( value1_fn);
+	sched.make_fiber( value2_fn);
+	BOOST_CHECK( ! sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
+	BOOST_CHECK_EQUAL( 0, value1);
+	BOOST_CHECK_EQUAL( 0, value2);
+
+	BOOST_CHECK( sched.run() );
+	BOOST_CHECK( ! sched.empty() );
+	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( sched.empty() );
+	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::test_suite * test =
+		BOOST_TEST_SUITE("Boost.Fiber: rrp test suite");
+
+	test->add( BOOST_TEST_CASE( & test_case_1) );
+	test->add( BOOST_TEST_CASE( & test_case_2) );
+
+	return test;
+}