|
Boost-Commit : |
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;
+}
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