Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r57728 - in sandbox/fiber: boost/fiber boost/fiber/detail libs/fiber/examples libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-11-17 14:46:24


Author: olli
Date: 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
New Revision: 57728
URL: http://svn.boost.org/trac/boost/changeset/57728

Log:
- thread_specific_ptr reintroduced (because of static ptr and multi-threading)
- at_fiber_exit() added

Added:
   sandbox/fiber/libs/fiber/examples/simple_mt.cpp (contents, props changed)
   sandbox/fiber/libs/fiber/test/test_at_exit.cpp (contents, props changed)
Text files modified:
   sandbox/fiber/boost/fiber/detail/fiber_info_base_posix.hpp | 8 ++
   sandbox/fiber/boost/fiber/detail/fiber_info_base_windows.hpp | 6 ++
   sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp | 17 +++++
   sandbox/fiber/boost/fiber/fiber.hpp | 2
   sandbox/fiber/boost/fiber/interruption.hpp | 12 ++--
   sandbox/fiber/boost/fiber/scheduler.hpp | 41 ++++++++++---
   sandbox/fiber/boost/fiber/utility.hpp | 32 +++++++++-
   sandbox/fiber/libs/fiber/examples/Jamfile.v2 | 1
   sandbox/fiber/libs/fiber/src/fiber.cpp | 7 --
   sandbox/fiber/libs/fiber/src/fiber_info_base_posix.cpp | 3
   sandbox/fiber/libs/fiber/src/fiber_info_base_windows.cpp | 3
   sandbox/fiber/libs/fiber/src/fiber_posix.cpp | 13 +++-
   sandbox/fiber/libs/fiber/src/scheduler.cpp | 120 ++++++++++++++++++++++++++++-----------
   sandbox/fiber/libs/fiber/src/scheduler_impl.cpp | 65 +++++++++++++++++++--
   sandbox/fiber/libs/fiber/test/Jamfile.v2 | 1
   sandbox/fiber/libs/fiber/test/test_interrupt.cpp | 5 +
   16 files changed, 258 insertions(+), 78 deletions(-)

Modified: sandbox/fiber/boost/fiber/detail/fiber_info_base_posix.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/fiber_info_base_posix.hpp (original)
+++ sandbox/fiber/boost/fiber/detail/fiber_info_base_posix.hpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -13,7 +13,10 @@
 
 }
 
+#include <stack>
+
 #include <boost/cstdint.hpp>
+#include <boost/function.hpp>
 #include <boost/intrusive_ptr.hpp>
 #include <boost/shared_array.hpp>
 
@@ -29,7 +32,9 @@
 
 struct BOOST_FIBER_DECL fiber_info_base
 {
- typedef intrusive_ptr< fiber_info_base > ptr_t;
+ typedef intrusive_ptr< fiber_info_base > ptr_t;
+ typedef function< void() > callable_t;
+ typedef std::stack< callable_t > callable_stack_t;
 
         uint32_t use_count;
         attributes attrs;
@@ -37,6 +42,7 @@
         shared_array< char > uctx_stack;
         fiber_state_t state;
         fiber_interrupt_t interrupt;
+ callable_stack_t at_exit;
 
         fiber_info_base();
 

Modified: sandbox/fiber/boost/fiber/detail/fiber_info_base_windows.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/detail/fiber_info_base_windows.hpp (original)
+++ sandbox/fiber/boost/fiber/detail/fiber_info_base_windows.hpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -15,7 +15,10 @@
 
 }
 
+#include <stack>
+
 #include <boost/cstdint.hpp>
+#include <boost/function.hpp>
 #include <boost/intrusive_ptr.hpp>
 
 #include <boost/fiber/attributes.hpp>
@@ -31,12 +34,15 @@
 struct BOOST_FIBER_DECL fiber_info_base
 {
         typedef intrusive_ptr< fiber_info_base > ptr_t;
+ typedef function< void() > callable_t;
+ typedef std::stack< callable_t > callable_stack_t;
 
         uint32_t use_count;
         attributes attrs;
         LPVOID uctx;
         fiber_state_t state;
         fiber_interrupt_t interrupt;
+ callable_stack_t at_exit;
 
         fiber_info_base();
 

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-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -12,9 +12,11 @@
 #include <map>
 #include <queue>
 
+#include <boost/function.hpp>
 #include <boost/utility.hpp>
 
 #include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/fiber_state.hpp>
 #include <boost/fiber/fiber.hpp>
 
 #include <boost/config/abi_prefix.hpp>
@@ -43,6 +45,7 @@
         typedef std::map< fiber::id, schedulable > container;
         typedef std::list< fiber::id > runnable_queue;
         typedef std::queue< fiber::id > terminated_queue;
+ typedef function< void() > callable_t;
 
         fiber master_;
         fiber active_;
@@ -53,9 +56,11 @@
 public:
         scheduler_impl();
 
+ ~scheduler_impl();
+
         void add_fiber( fiber);
 
- fiber const& active_fiber() const;
+ fiber::id id_active_fiber() const;
 
         void yield_active_fiber();
 
@@ -65,8 +70,18 @@
 
         void interrupt_active_fiber();
 
+ bool interruption_requested_active_fiber() const;
+
+ bool interruption_enabled_active_fiber() const;
+
+ fiber_interrupt_t & interrupt_flags_active_fiber();
+
+ int priority_active_fiber();
+
         void priority_active_fiber( int);
 
+ void at_exit_active_fiber( callable_t);
+
         void cancel_fiber( fiber::id const&);
 
         void suspend_fiber( fiber::id const&);

Modified: sandbox/fiber/boost/fiber/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/fiber.hpp (original)
+++ sandbox/fiber/boost/fiber/fiber.hpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -200,8 +200,6 @@
 
         void interrupt();
 
- bool interruption_requested() const;
-
         void cancel();
 
         void suspend();

Modified: sandbox/fiber/boost/fiber/interruption.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/interruption.hpp (original)
+++ sandbox/fiber/boost/fiber/interruption.hpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -27,16 +27,16 @@
 
 public:
         disable_interruption() :
- set_( ( scheduler::active_fiber().info_->interrupt & detail::INTERRUPTION_BLOCKED) != 0)
+ set_( ( scheduler::interrupt_flags_active_fiber() & detail::INTERRUPTION_BLOCKED) != 0)
         {
                 if ( ! set_)
- scheduler::active_fiber().info_->interrupt |= detail::INTERRUPTION_BLOCKED;
+ scheduler::interrupt_flags_active_fiber() |= detail::INTERRUPTION_BLOCKED;
         }
 
         ~disable_interruption()
         {
                 if ( ! set_)
- scheduler::active_fiber().info_->interrupt &= ~detail::INTERRUPTION_BLOCKED;
+ scheduler::interrupt_flags_active_fiber() &= ~detail::INTERRUPTION_BLOCKED;
         }
 };
 
@@ -47,16 +47,16 @@
 
 public:
         restore_interruption() :
- set_( ( scheduler::active_fiber().info_->interrupt & detail::INTERRUPTION_BLOCKED) != 0)
+ set_( ( scheduler::interrupt_flags_active_fiber() & detail::INTERRUPTION_BLOCKED) != 0)
         {
                 if ( set_)
- scheduler::active_fiber().info_->interrupt &= ~detail::INTERRUPTION_BLOCKED;
+ scheduler::interrupt_flags_active_fiber() &= ~detail::INTERRUPTION_BLOCKED;
         }
 
         ~restore_interruption()
         {
                 if ( set_)
- scheduler::active_fiber().info_->interrupt |= detail::INTERRUPTION_BLOCKED;
+ scheduler::interrupt_flags_active_fiber() |= detail::INTERRUPTION_BLOCKED;
         }
 };
 

Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp (original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -10,12 +10,14 @@
 #include <cstddef>
 #include <memory>
 
+#include <boost/function.hpp>
 #include <boost/preprocessor/repetition.hpp>
-#include <boost/scoped_ptr.hpp>
+#include <boost/thread/tss.hpp>
 #include <boost/utility.hpp>
 
 #include <boost/fiber/attributes.hpp>
 #include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/fiber_state.hpp>
 #include <boost/fiber/detail/scheduler_impl.hpp>
 #include <boost/fiber/fiber.hpp>
 
@@ -34,6 +36,11 @@
 void priority( int);
 void interruption_point();
 bool interruption_requested();
+bool interruption_enabled();
+template< typename Callable >
+void at_fiber_exit( Callable);
+void at_fiber_exit( function< void() >);
+void at_fiber_exit( void (*)() );
 
 }
 
@@ -54,17 +61,23 @@
         friend void this_fiber::priority( int);
         friend void this_fiber::interruption_point();
         friend bool this_fiber::interruption_requested();
+ friend bool this_fiber::interruption_enabled();
+ template< typename Callable >
+ friend void this_fiber::at_fiber_exit( Callable);
+ friend void this_fiber::at_fiber_exit( function< void() >);
+ friend void this_fiber::at_fiber_exit( void (*)() );
         friend class fiber;
         friend class disable_interruption;
         friend class restore_interruption;
 
- typedef scoped_ptr< detail::scheduler_impl > impl_t;
+ typedef thread_specific_ptr< detail::scheduler_impl > impl_t;
+ typedef function< void() > callable_t;
 
         static impl_t impl_;
 
         static bool runs_as_fiber();
 
- static fiber const& active_fiber();
+ static fiber::id id_active_fiber();
 
         static void yield_active_fiber();
 
@@ -74,8 +87,18 @@
 
         static void interrupt_active_fiber();
 
+ static bool interruption_requested_active_fiber();
+
+ static bool interruption_enabled_active_fiber();
+
+ static detail::fiber_interrupt_t & interrupt_flags_active_fiber();
+
+ static int priority_active_fiber();
+
         static void priority_active_fiber( int);
 
+ static void at_exit_active_fiber( callable_t);
+
         static void cancel_fiber( fiber::id const&);
 
         static void suspend_fiber( fiber::id const&);
@@ -86,9 +109,9 @@
 
         static void join_fiber( fiber::id const&);
 
-public:
- scheduler();
+ detail::scheduler_impl * access_();
 
+public:
         ~scheduler();
 
         bool run();
@@ -101,11 +124,11 @@
 
         template< typename Fn >
         void make_fiber( Fn fn)
- { impl_->add_fiber( fiber( fn) ); }
+ { access_()->add_fiber( fiber( fn) ); }
 
         template< typename Fn >
         void make_fiber( attributes attrs, Fn fn)
- { impl_->add_fiber( fiber( attrs, fn) ); }
+ { access_()->add_fiber( fiber( attrs, fn) ); }
 
 #ifndef BOOST_FIBER_MAX_ARITY
 #define BOOST_FIBER_MAX_ARITY 10
@@ -118,10 +141,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)) \
- { impl_->add_fiber( 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)) \
- { impl_->add_fiber( fiber( attrs, fn, BOOST_PP_ENUM_PARAMS(n, a) ) ); }
+ { 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, ~)
 

Modified: sandbox/fiber/boost/fiber/utility.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/utility.hpp (original)
+++ sandbox/fiber/boost/fiber/utility.hpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -7,9 +7,9 @@
 #ifndef BOOST_THIS_FIBER_UTILITY_H
 #define BOOST_THIS_FIBER_UTILITY_H
 
+#include <boost/bind.hpp>
 #include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <boost/thread/thread_time.hpp>
+#include <boost/function.hpp>
 
 #include <boost/fiber/fiber.hpp>
 #include <boost/fiber/scheduler.hpp>
@@ -25,7 +25,7 @@
 
 inline
 fiber::id get_id()
-{ return fibers::scheduler::active_fiber().get_id(); }
+{ return fibers::scheduler::id_active_fiber(); }
 
 inline
 void yield()
@@ -41,7 +41,7 @@
 
 inline
 int priority()
-{ return fibers::scheduler::active_fiber().priority(); }
+{ return fibers::scheduler::priority_active_fiber(); }
 
 inline
 void priority( int prio)
@@ -53,7 +53,29 @@
 
 inline
 bool interruption_requested()
-{ return fibers::scheduler::active_fiber().interruption_requested(); }
+{ return fibers::scheduler::interruption_requested_active_fiber(); }
+
+inline
+bool interruption_enabled()
+{ return fibers::scheduler::interruption_enabled_active_fiber(); }
+
+template< typename Callable >
+void at_fiber_exit( Callable ca)
+{
+ fibers::scheduler::at_exit_active_fiber(
+ boost::bind( boost::type< void >(), ca) );
+}
+
+inline
+void at_fiber_exit( function< void() > ca)
+{ fibers::scheduler::at_exit_active_fiber( ca); }
+
+inline
+void at_fiber_exit( void ( * ca)() )
+{
+ fibers::scheduler::at_exit_active_fiber(
+ boost::bind( boost::type< void >(), ca) );
+}
 
 }}
 

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-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -28,4 +28,5 @@
 exe interrupt : interrupt.cpp ;
 exe cancel : cancel.cpp ;
 exe simple : simple.cpp ;
+exe simple_mt : simple_mt.cpp ;
 exe ping_pong : ping_pong.cpp ;

Added: sandbox/fiber/libs/fiber/examples/simple_mt.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/examples/simple_mt.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -0,0 +1,80 @@
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/fiber.hpp>
+
+void f( std::string const& str, int n)
+{
+ for ( int i = 0; i < n; ++i)
+ {
+ std::ostringstream os1;
+ std::ostringstream os2;
+ os1 << boost::this_thread::get_id();
+ os2 << boost::this_fiber::get_id();
+ fprintf( stderr, "(thread: %s, fiber: %s) %d: %s\n", os1.str().c_str(), os2.str().c_str(), i, str.c_str() );
+ boost::this_fiber::yield();
+ }
+}
+
+void run_thread(
+ boost::barrier & b,
+ boost::fibers::scheduler & sched,
+ std::string const& msg, int n)
+{
+ std::ostringstream os;
+ os << boost::this_thread::get_id();
+ fprintf( stderr, "start (thread: %s)\n", os.str().c_str() );
+ sched.make_fiber( & f, msg, n);
+
+ b.wait();
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+ fprintf( stderr, "finish (thread: %s)\n", os.str().c_str() );
+}
+
+int main()
+{
+ try
+ {
+ boost::fibers::scheduler sched;
+
+ std::cout << "start" << std::endl;
+
+ boost::barrier b( 2);
+ boost::thread th1(
+ run_thread,
+ boost::ref( b),
+ boost::ref( sched), "abc", 3);
+ boost::thread th2(
+ run_thread,
+ boost::ref( b),
+ boost::ref( sched), "xyz", 4);
+
+ th1.join();
+ th2.join();
+
+ 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/src/fiber.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/fiber.cpp (original)
+++ sandbox/fiber/libs/fiber/src/fiber.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -127,13 +127,6 @@
         info_->interrupt |= detail::INTERRUPTION_ENABLED;
 }
 
-bool
-fiber::interruption_requested() const
-{
- if ( ! info_) throw fiber_moved();
- return ( info_->interrupt & detail::INTERRUPTION_ENABLED) != 0;
-}
-
 void
 fiber::cancel()
 { scheduler::cancel_fiber( get_id() ); }

Modified: sandbox/fiber/libs/fiber/src/fiber_info_base_posix.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/fiber_info_base_posix.cpp (original)
+++ sandbox/fiber/libs/fiber/src/fiber_info_base_posix.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -23,7 +23,8 @@
         uctx(),
         uctx_stack(),
         state( STATE_MASTER),
- interrupt( INTERRUPTION_DISABLED)
+ interrupt( INTERRUPTION_DISABLED),
+ at_exit()
 {}
 
 fiber_info_base::fiber_info_base( attributes const& attrs_) :

Modified: sandbox/fiber/libs/fiber/src/fiber_info_base_windows.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/fiber_info_base_windows.cpp (original)
+++ sandbox/fiber/libs/fiber/src/fiber_info_base_windows.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -24,7 +24,8 @@
         attrs(),
         uctx(),
         state( STATE_MASTER),
- interrupt( INTERRUPTION_DISABLED)
+ interrupt( INTERRUPTION_DISABLED),
+ at_exit()
 {
         uctx = ::GetCurrentFiber();
         if ( ! uctx)

Modified: sandbox/fiber/libs/fiber/src/fiber_posix.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/fiber_posix.cpp (original)
+++ sandbox/fiber/libs/fiber/src/fiber_posix.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -29,10 +29,15 @@
         BOOST_ASSERT( self);
         try
         { self->run(); }
- catch ( fiber_interrupted const&)
- {}
- catch (...)
- {}
+ catch ( fiber_interrupted const&) {}
+ catch (...) {}
+ while ( ! self->at_exit.empty() )
+ {
+ detail::fiber_info_base::callable_t ca;
+ self->at_exit.top().swap( ca);
+ self->at_exit.pop();
+ ca();
+ }
          this_fiber::cancel();
 }
 

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-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -19,110 +19,162 @@
 
 bool
 scheduler::runs_as_fiber()
-{ return impl_; }
+{ return impl_.get() != 0; }
 
-fiber const&
-scheduler::active_fiber()
+fiber::id
+scheduler::id_active_fiber()
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- return impl_->active_fiber();
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ return impl->id_active_fiber();
 }
 
 void
 scheduler::yield_active_fiber()
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->yield_active_fiber();
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->yield_active_fiber();
 }
 
 void
 scheduler::cancel_active_fiber()
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->cancel_active_fiber();
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->cancel_active_fiber();
 }
 
 void
 scheduler::suspend_active_fiber()
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->suspend_active_fiber();
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->suspend_active_fiber();
 }
 
 void
 scheduler::interrupt_active_fiber()
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->interrupt_active_fiber();
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->interrupt_active_fiber();
+}
+
+bool
+scheduler::interruption_requested_active_fiber()
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ return impl->interruption_requested_active_fiber();
+}
+
+bool
+scheduler::interruption_enabled_active_fiber()
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ return impl->interruption_enabled_active_fiber();
+}
+
+detail::fiber_interrupt_t &
+scheduler::interrupt_flags_active_fiber()
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ return impl->interrupt_flags_active_fiber();
+}
+
+int
+scheduler::priority_active_fiber()
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ return impl->priority_active_fiber();
 }
 
 void
 scheduler::priority_active_fiber( int prio)
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->priority_active_fiber( prio);
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->priority_active_fiber( prio);
+}
+
+void
+scheduler::at_exit_active_fiber( callable_t ca)
+{
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->at_exit_active_fiber( ca);
 }
 
 void
 scheduler::cancel_fiber( fiber::id const& id)
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->cancel_fiber( id);
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->cancel_fiber( id);
 }
 
 void
 scheduler::suspend_fiber( fiber::id const& id)
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->suspend_fiber( id);
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->suspend_fiber( id);
 }
 
 void
 scheduler::resume_fiber( fiber::id const& id)
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->resume_fiber( id);
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->resume_fiber( id);
 }
 
 void
 scheduler::reschedule_fiber( fiber::id const& id)
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->reschedule_fiber( id);
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->reschedule_fiber( id);
 }
 
 void
 scheduler::join_fiber( fiber::id const& id)
 {
- if ( ! impl_) throw fiber_error("not a fiber");
- impl_->join_fiber( id);
+ detail::scheduler_impl * impl( impl_.get() );
+ if ( ! impl) throw fiber_error("not a fiber");
+ impl->join_fiber( id);
 }
 
-scheduler::scheduler()
+detail::scheduler_impl *
+scheduler::access_()
 {
- fiber::convert_thread_to_fiber();
- impl_.reset(
- new detail::scheduler_impl() );
+ if ( ! impl_.get() )
+ impl_.reset( new detail::scheduler_impl() );
+ return impl_.get();
 }
 
 scheduler::~scheduler()
-{ fiber::convert_fiber_to_thread(); }
+{ impl_.reset(); }
 
 bool
 scheduler::run()
-{ return impl_->run(); }
+{ return access_()->run(); }
 
 bool
 scheduler::empty()
-{ return impl_->empty(); }
+{ return access_()->empty(); }
 
 std::size_t
 scheduler::size()
-{ return impl_->size(); }
+{ return access_()->size(); }
 
 void
 scheduler::submit_fiber( fiber f)
-{ impl_->add_fiber( f); }
+{ access_()->add_fiber( f); }
 
 }}
 

Modified: sandbox/fiber/libs/fiber/src/scheduler_impl.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/src/scheduler_impl.cpp (original)
+++ sandbox/fiber/libs/fiber/src/scheduler_impl.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -44,14 +44,20 @@
         ( state & STATE_TERMINATED) != 0
 
 scheduler_impl::scheduler_impl() :
- master_(
- fiber_info_base::ptr_t(
- new fiber_info_default() ) ),
+ master_(),
         active_(),
         fibers_(),
         runnable_fibers_(),
         terminated_fibers_()
-{}
+{
+ fiber::convert_thread_to_fiber();
+ master_ = fiber(
+ fiber_info_base::ptr_t(
+ new fiber_info_default() ) );
+}
+
+scheduler_impl::~scheduler_impl()
+{ fiber::convert_fiber_to_thread(); }
 
 void
 scheduler_impl::add_fiber( fiber f)
@@ -70,9 +76,9 @@
         runnable_fibers_.push_back( result.first->first);
 }
 
-fiber const&
-scheduler_impl::active_fiber() const
-{ return active_; }
+fiber::id
+scheduler_impl::id_active_fiber() const
+{ return active_.get_id(); }
 
 void
 scheduler_impl::yield_active_fiber()
@@ -133,6 +139,42 @@
                 throw fiber_interrupted();
 }
 
+bool
+scheduler_impl::interruption_requested_active_fiber() const
+{
+ BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+
+ return ( active_.info_->interrupt & detail::INTERRUPTION_ENABLED) != 0;
+}
+
+bool
+scheduler_impl::interruption_enabled_active_fiber() const
+{
+ BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+
+ return active_.info_->interrupt == detail::INTERRUPTION_ENABLED;
+}
+
+fiber_interrupt_t &
+scheduler_impl::interrupt_flags_active_fiber()
+{
+ BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+
+ return active_.info_->interrupt;
+}
+
+int
+scheduler_impl::priority_active_fiber()
+{
+ BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+
+ return active_.priority();
+}
+
 void
 scheduler_impl::priority_active_fiber( int prio)
 {
@@ -144,6 +186,15 @@
 }
 
 void
+scheduler_impl::at_exit_active_fiber( callable_t ca)
+{
+ BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
+ BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+
+ active_.info_->at_exit.push( ca);
+}
+
+void
 scheduler_impl::cancel_fiber( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);

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-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -33,6 +33,7 @@
     [ fiber-test test_priority ]
     [ fiber-test test_join ]
     [ fiber-test test_interrupt ]
+ [ fiber-test test_at_exit ]
     [ fiber-test test_mutex ]
     [ fiber-test test_auto_reset_event ]
     [ fiber-test test_manual_reset_event ]

Added: sandbox/fiber/libs/fiber/test/test_at_exit.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/test/test_at_exit.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -0,0 +1,61 @@
+
+// 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 <vector>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber.hpp>
+
+std::vector< int > vec;
+bool set = false;
+
+void at_exit_1()
+{ vec.push_back( 1); }
+
+void at_exit_2()
+{ vec.push_back( 2); }
+
+void fn()
+{
+ boost::this_fiber::at_fiber_exit( at_exit_1);
+ boost::this_fiber::at_fiber_exit( at_exit_2);
+ set = true;
+}
+
+void test_case_1()
+{
+ boost::fibers::scheduler sched;
+
+ sched.make_fiber( fn);
+
+ BOOST_CHECK_EQUAL( std::size_t( 0), vec.size() );
+ BOOST_CHECK( vec.empty() );
+ BOOST_CHECK_EQUAL( false, set);
+
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+ BOOST_CHECK_EQUAL( std::size_t( 2), vec.size() );
+ BOOST_CHECK( ! vec.empty() );
+ BOOST_CHECK_EQUAL( 2, vec[0]);
+ BOOST_CHECK_EQUAL( 1, vec[1]);
+ BOOST_CHECK_EQUAL( true, set);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: at-exit test suite");
+
+ test->add( BOOST_TEST_CASE( & test_case_1) );
+
+ return test;
+}

Modified: sandbox/fiber/libs/fiber/test/test_interrupt.cpp
==============================================================================
--- sandbox/fiber/libs/fiber/test/test_interrupt.cpp (original)
+++ sandbox/fiber/libs/fiber/test/test_interrupt.cpp 2009-11-17 14:46:23 EST (Tue, 17 Nov 2009)
@@ -5,6 +5,7 @@
 // http://www.boost.org/LICENSE_1_0.txt)
 
 #include <sstream>
+#include <stdexcept>
 #include <string>
 
 #include <boost/test/unit_test.hpp>
@@ -34,6 +35,8 @@
 void fn_2()
 {
         boost::fibers::disable_interruption disabled;
+ if ( boost::this_fiber::interruption_enabled() )
+ throw std::logic_error("interruption enabled");
         for ( int i = 0; i < 5; ++i)
         {
                 ++value1;
@@ -47,6 +50,8 @@
         try
         {
                 boost::fibers::disable_interruption disabled;
+ if ( boost::this_fiber::interruption_enabled() )
+ throw std::logic_error("interruption enabled");
                 for ( int i = 0; i < 5; ++i)
                 {
                         ++value1;


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