|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r57639 - in sandbox/fiber: boost/fiber boost/fiber/detail libs/fiber/src
From: oliver.kowalke_at_[hidden]
Date: 2009-11-13 13:18:15
Author: olli
Date: 2009-11-13 13:18:14 EST (Fri, 13 Nov 2009)
New Revision: 57639
URL: http://svn.boost.org/trac/boost/changeset/57639
Log:
- implemetation of cancel_fiber(), suspend_fiber(), resume_fiber()
Text files modified:
sandbox/fiber/boost/fiber/detail/fiber_state.hpp | 22 +++---
sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp | 16 +++-
sandbox/fiber/boost/fiber/fiber.hpp | 4 +
sandbox/fiber/boost/fiber/scheduler.hpp | 12 +++
sandbox/fiber/boost/fiber/utility.hpp | 8 +
sandbox/fiber/libs/fiber/src/fiber.cpp | 11 ++
sandbox/fiber/libs/fiber/src/scheduler.cpp | 30 ++++++++
sandbox/fiber/libs/fiber/src/scheduler_impl.cpp | 131 +++++++++++++++++++++++++++++++++++----
8 files changed, 195 insertions(+), 39 deletions(-)
Modified: sandbox/fiber/boost/fiber/detail/fiber_state.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/fiber_state.hpp (original)
+++ sandbox/fiber/boost/fiber/detail/fiber_state.hpp 2009-11-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -13,19 +13,21 @@
namespace fibers {
namespace detail {
-enum fiber_state_t
+enum 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
+ STATE_MASTER = 1 << 0,
+ STATE_NOT_STARTED = 1 << 1,
+ STATE_READY = 1 << 2,
+ STATE_RUNNING = 1 << 3,
+ STATE_SUSPENDED = 1 << 4,
+ STATE_WAITING = 1 << 5,
+ STATE_TERMINATED = 1 << 6
};
+typedef char fiber_state_t;
+
+#define IS_ALIVE_BIT_MASK 0x3C
+
}}
}
Modified: sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp (original)
+++ sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp 2009-11-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -10,6 +10,7 @@
#include <cstddef>
#include <list>
#include <map>
+#include <queue>
#include <boost/utility.hpp>
@@ -26,13 +27,14 @@
{
private:
typedef std::map< fiber::id, fiber > container;
- typedef std::list< fiber::id > queue;
+ typedef std::list< fiber::id > runnable_queue;
+ typedef std::queue< fiber::id > terminated_queue;
fiber master_;
fiber::id f_id_;
container fibers_;
- queue runnable_fibers_;
- queue terminated_fibers_;
+ runnable_queue runnable_fibers_;
+ terminated_queue terminated_fibers_;
public:
scheduler_impl();
@@ -43,10 +45,16 @@
void yield_active_fiber();
- void terminate_active_fiber();
+ void cancel_active_fiber();
+
+ void suspend_active_fiber();
void cancel_fiber( fiber::id const&);
+ void suspend_fiber( fiber::id const&);
+
+ void resume_fiber( fiber::id const&);
+
bool run();
bool empty();
Modified: sandbox/fiber/boost/fiber/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/fiber.hpp (original)
+++ sandbox/fiber/boost/fiber/fiber.hpp 2009-11-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -189,6 +189,10 @@
bool is_alive() const;
void cancel();
+
+ void suspend();
+
+ void resume();
};
class fiber::id
Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp (original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp 2009-11-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -29,6 +29,7 @@
fiber::fiber::id get_id();
void yield();
void cancel();
+void suspend();
}
@@ -41,6 +42,7 @@
friend fiber::id this_fiber::get_id();
friend void this_fiber::yield();
friend void this_fiber::cancel();
+ friend void this_fiber::suspend();
friend class fiber;
typedef thread_specific_ptr< detail::scheduler_impl > tss_impl_t;
@@ -49,14 +51,20 @@
static bool runs_as_fiber();
- static fiber::id get_id();
+ static fiber::id active_fiber();
static void yield_active_fiber();
- static void terminate_active_fiber();
+ static void cancel_active_fiber();
+
+ static void suspend_active_fiber();
static void cancel_fiber( fiber::id const&);
+ static void suspend_fiber( fiber::id const&);
+
+ static void resume_fiber( fiber::id const&);
+
detail::scheduler_impl * access_();
public:
Modified: sandbox/fiber/boost/fiber/utility.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/utility.hpp (original)
+++ sandbox/fiber/boost/fiber/utility.hpp 2009-11-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -25,7 +25,7 @@
inline
fiber::id get_id()
-{ return fibers::scheduler::get_id(); }
+{ return fibers::scheduler::active_fiber(); }
inline
void yield()
@@ -33,7 +33,11 @@
inline
void cancel()
-{ fibers::scheduler::terminate_active_fiber(); }
+{ fibers::scheduler::cancel_active_fiber(); }
+
+inline
+void suspend()
+{ fibers::scheduler::suspend_active_fiber(); }
}}
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-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -106,14 +106,21 @@
{
if ( ! info_)
throw fiber_moved();
- return ( info_->state & detail::STATE_RUNNABLE) == detail::STATE_RUNNABLE ||
- ( info_->state & detail::STATE_NOT_RUNNABLE) == detail::STATE_NOT_RUNNABLE;
+ return ( info_->state & IS_ALIVE_BIT_MASK) != 0;
}
void
fiber::cancel()
{ scheduler::cancel_fiber( get_id() ); }
+void
+fiber::suspend()
+{ scheduler::suspend_fiber( get_id() ); }
+
+void
+fiber::resume()
+{ scheduler::resume_fiber( get_id() ); }
+
}}
#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-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -22,7 +22,7 @@
{ return impl_.get() != 0; }
fiber::id
-scheduler::get_id()
+scheduler::active_fiber()
{
detail::scheduler_impl * impl( impl_.get() );
if ( ! impl) throw fiber_error("not a fiber");
@@ -38,11 +38,19 @@
}
void
-scheduler::terminate_active_fiber()
+scheduler::cancel_active_fiber()
{
detail::scheduler_impl * impl( impl_.get() );
if ( ! impl) throw fiber_error("not a fiber");
- impl->terminate_active_fiber();
+ impl->cancel_active_fiber();
+}
+
+void
+scheduler::suspend_active_fiber()
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->suspend_active_fiber();
}
void
@@ -53,6 +61,22 @@
impl->cancel_fiber( f_id);
}
+void
+scheduler::suspend_fiber( fiber::id const& f_id)
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->suspend_fiber( f_id);
+}
+
+void
+scheduler::resume_fiber( fiber::id const& f_id)
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->resume_fiber( f_id);
+}
+
detail::scheduler_impl *
scheduler::access_()
{
Modified: sandbox/fiber/libs/fiber/src/scheduler_impl.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/scheduler_impl.cpp (original)
+++ sandbox/fiber/libs/fiber/src/scheduler_impl.cpp 2009-11-13 13:18:14 EST (Fri, 13 Nov 2009)
@@ -21,6 +21,27 @@
namespace fibers {
namespace detail {
+#define HAS_STATE_MASTER( state) \
+ ( state & STATE_MASTER) != 0
+
+#define HAS_STATE_NOT_STARTED( state) \
+ ( state & STATE_NOT_STARTED) != 0
+
+#define HAS_STATE_READY( state) \
+ ( state & STATE_READY) != 0
+
+#define HAS_STATE_RUNNING( state) \
+ ( state & STATE_RUNNING) != 0
+
+#define HAS_STATE_SUSPENDED( state) \
+ ( state & STATE_SUSPENDED) != 0
+
+#define HAS_STATE_WAITING( state) \
+ ( state & STATE_WAITING) != 0
+
+#define HAS_STATE_TERMINATED( state) \
+ ( state & STATE_TERMINATED) != 0
+
scheduler_impl::scheduler_impl() :
master_(
fiber_info_base::ptr_t(
@@ -58,11 +79,19 @@
}
void
-scheduler_impl::terminate_active_fiber()
+scheduler_impl::cancel_active_fiber()
{
BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].info_->state);
fibers_[f_id_].info_->state = STATE_TERMINATED;
- terminated_fibers_.push_back( f_id_);
+ terminated_fibers_.push( f_id_);
+ fibers_[f_id_].switch_to_( master_);
+}
+
+void
+scheduler_impl::suspend_active_fiber()
+{
+ BOOST_ASSERT( STATE_RUNNING == fibers_[f_id_].info_->state);
+ fibers_[f_id_].info_->state |= STATE_SUSPENDED;
fibers_[f_id_].switch_to_( master_);
}
@@ -73,30 +102,92 @@
if ( i == fibers_.end() ) return;
fiber f( i->second);
BOOST_ASSERT( f);
- BOOST_ASSERT( STATE_MASTER != f.info_->state);
- if ( STATE_TERMINATED == f.info_->state) return;
- else if ( STATE_NOT_STARTED == f.info_->state)
+ BOOST_ASSERT( HAS_STATE_MASTER( f.info_->state) );
+
+ if ( HAS_STATE_TERMINATED( f.info_->state) ||
+ HAS_STATE_NOT_STARTED( f.info_->state) )
+ return;
+
+ if ( HAS_STATE_READY( f.info_->state) )
{
f.info_->state = STATE_TERMINATED;
- terminated_fibers_.push_back( f_id);
+ runnable_fibers_.remove( f.get_id() );
+ terminated_fibers_.push( f_id);
}
- else if ( STATE_READY == f.info_->state)
+ else if ( HAS_STATE_RUNNING( f.info_->state) )
{
+ BOOST_ASSERT( f_id == f.get_id() );
f.info_->state = STATE_TERMINATED;
- runnable_fibers_.remove( f.get_id() );
- terminated_fibers_.push_back( f_id);
+ terminated_fibers_.push( f_id);
+ f.switch_to_( master_);
}
- else if ( STATE_RUNNING == f.info_->state)
+ else if ( HAS_STATE_WAITING( f.info_->state) )
{
f.info_->state = STATE_TERMINATED;
- terminated_fibers_.push_back( f_id);
+ // TODO: remove from waiting-queue
+ terminated_fibers_.push( f_id);
+ }
+ else
+ BOOST_ASSERT( ! "should never reached");
+}
+
+void
+scheduler_impl::suspend_fiber( fiber::id const& f_id)
+{
+ container::iterator i = fibers_.find( f_id);
+ if ( i == fibers_.end() ) return;
+ fiber f( i->second);
+ BOOST_ASSERT( f);
+ BOOST_ASSERT( STATE_MASTER != f.info_->state);
+
+ if ( HAS_STATE_TERMINATED( f.info_->state) ||
+ HAS_STATE_NOT_STARTED( f.info_->state) )
+ return;
+
+ if ( HAS_STATE_READY( f.info_->state) )
+ {
+ f.info_->state |= STATE_SUSPENDED;
+ runnable_fibers_.remove( f.get_id() );
+ }
+ else if ( HAS_STATE_RUNNING( f.info_->state) )
+ {
+ BOOST_ASSERT( f_id == f.get_id() );
+ f.info_->state |= STATE_SUSPENDED;
f.switch_to_( master_);
}
- else
+ else if ( HAS_STATE_WAITING( f.info_->state) )
{
- // TODO: remove waiting fiber/suspended fiber
- f.info_->state = STATE_TERMINATED;
- terminated_fibers_.push_back( f_id);
+ f.info_->state |= STATE_SUSPENDED;
+ // TODO: remove from waiting-queue
+ }
+ else
+ BOOST_ASSERT( ! "should never reached");
+}
+
+void
+scheduler_impl::resume_fiber( fiber::id const& f_id)
+{
+ container::iterator i = fibers_.find( f_id);
+ if ( i == fibers_.end() ) return;
+ fiber f( i->second);
+ BOOST_ASSERT( f);
+ BOOST_ASSERT( STATE_MASTER != f.info_->state);
+
+ if ( HAS_STATE_SUSPENDED( f.info_->state) )
+ {
+ f.info_->state &= ~STATE_SUSPENDED;
+ switch ( f.info_->state)
+ {
+ case STATE_READY:
+ case STATE_RUNNING:
+ runnable_fibers_.push_back( f.get_id() );
+ break;
+ case STATE_WAITING:
+ // TODO: put it into the waiting-queue
+ break;
+ default:
+ BOOST_ASSERT( ! "should never reached");
+ }
}
}
@@ -117,7 +208,7 @@
{
BOOST_ASSERT( STATE_TERMINATED == fibers_[terminated_fibers_.front()].info_->state);
fibers_.erase( terminated_fibers_.front() );
- terminated_fibers_.pop_front();
+ terminated_fibers_.pop();
result = true;
}
return result;
@@ -131,6 +222,14 @@
scheduler_impl::size()
{ return fibers_.size(); }
+#undef HAS_STATE_MASTER
+#undef HAS_STATE_NOT_STARTED
+#undef HAS_STATE_READY
+#undef HAS_STATE_RUNNING
+#undef HAS_STATE_SUSPENDED
+#undef HAS_STATE_WAITING
+#undef HAS_STATE_TERMINATED
+
}}}
#include <boost/config/abi_suffix.hpp>
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