$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r57711 - in sandbox/fiber: boost boost/fiber boost/fiber/detail libs/fiber/examples libs/fiber/src libs/fiber/test
From: oliver.kowalke_at_[hidden]
Date: 2009-11-16 15:51:57
Author: olli
Date: 2009-11-16 15:51:54 EST (Mon, 16 Nov 2009)
New Revision: 57711
URL: http://svn.boost.org/trac/boost/changeset/57711
Log:
- classes disable_interruption and restore_interruption added
- example for interruption added
Added:
   sandbox/fiber/boost/fiber/interruption.hpp   (contents, props changed)
   sandbox/fiber/libs/fiber/examples/interrupt.cpp   (contents, props changed)
Text files modified: 
   sandbox/fiber/boost/fiber.hpp                                |     1                                         
   sandbox/fiber/boost/fiber/detail/fiber_info_base_posix.hpp   |     2                                         
   sandbox/fiber/boost/fiber/detail/fiber_info_base_windows.hpp |     2                                         
   sandbox/fiber/boost/fiber/detail/fiber_state.hpp             |    11 +++                                     
   sandbox/fiber/boost/fiber/detail/scheduler_impl.hpp          |    12 +--                                     
   sandbox/fiber/boost/fiber/fiber.hpp                          |     5 +                                       
   sandbox/fiber/boost/fiber/scheduler.hpp                      |    23 +++++---                                
   sandbox/fiber/boost/fiber/utility.hpp                        |    12 ++-                                     
   sandbox/fiber/libs/fiber/examples/Jamfile.v2                 |     1                                         
   sandbox/fiber/libs/fiber/src/fiber.cpp                       |     9 +-                                      
   sandbox/fiber/libs/fiber/src/fiber_info_base_posix.cpp       |     4                                         
   sandbox/fiber/libs/fiber/src/fiber_info_base_windows.cpp     |     4                                         
   sandbox/fiber/libs/fiber/src/scheduler.cpp                   |    39 +++++++------                           
   sandbox/fiber/libs/fiber/src/scheduler_impl.cpp              |    46 +++++----------                         
   sandbox/fiber/libs/fiber/test/test_interrupt.cpp             |   112 +++++++++++++++++++++------------------ 
   15 files changed, 150 insertions(+), 133 deletions(-)
Modified: sandbox/fiber/boost/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber.hpp	(original)
+++ sandbox/fiber/boost/fiber.hpp	2009-11-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -14,6 +14,7 @@
 #include <boost/fiber/count_down_event.hpp>
 #include <boost/fiber/exceptions.hpp>
 #include <boost/fiber/fiber.hpp>
+#include <boost/fiber/interruption.hpp>
 #include <boost/fiber/manual_reset_event.hpp>
 #include <boost/fiber/mutex.hpp>
 #include <boost/fiber/scheduler.hpp>
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -36,7 +36,7 @@
         ::ucontext_t			uctx;
         shared_array< char >	uctx_stack;
         fiber_state_t			state;
-	bool					interrupt;
+	fiber_interrupt_t					interrupt;
 
         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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -36,7 +36,7 @@
         attributes		attrs;
         LPVOID			uctx;
         fiber_state_t	state;
-	bool			interrupt;
+	fiber_interrupt_t			interrupt;
 
         fiber_info_base();
 
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -28,9 +28,16 @@
 
 #define IS_ALIVE_BIT_MASK 0x3C
 
-}}
+enum interrupt_t
+{
+	INTERRUPTION_DISABLED	= 1 << 0,
+	INTERRUPTION_ENABLED	= 1 << 1,
+	INTERRUPTION_BLOCKED	= 1 << 2
+};
 
-}
+typedef char fiber_interrupt_t;
+
+}}}
 
 #include <boost/config/abi_suffix.hpp>
 
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -55,7 +55,7 @@
 
         void add_fiber( fiber);
 
-	fiber::id active_fiber() const;
+	fiber const& active_fiber() const;
 
         void yield_active_fiber();
 
@@ -65,19 +65,17 @@
 
         void interrupt_active_fiber();
 
+	void priority_active_fiber( int);
+
         void cancel_fiber( fiber::id const&);
 
         void suspend_fiber( fiber::id const&);
 
         void resume_fiber( fiber::id const&);
 
-	int priority( fiber::id const&);
-
-	void priority( fiber::id const&, int);
-
-	void re_schedule( fiber::id const&);
+	void reschedule_fiber( fiber::id const&);
 
-	void join( fiber::id const&);
+	void join_fiber( fiber::id const&);
 
         bool run();
 
Modified: sandbox/fiber/boost/fiber/fiber.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/fiber.hpp	(original)
+++ sandbox/fiber/boost/fiber/fiber.hpp	2009-11-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -31,10 +31,15 @@
 
 }
 
+class disable_interruption;
+class restore_interruption;
+
 class BOOST_FIBER_DECL fiber
 {
 private:
         friend class detail::scheduler_impl;
+	friend class disable_interruption;
+	friend class restore_interruption;
 
         struct dummy;
 
Added: sandbox/fiber/boost/fiber/interruption.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/interruption.hpp	2009-11-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -0,0 +1,67 @@
+
+//          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_INTERRUPTION_H
+#define BOOST_FIBERS_INTERRUPTION_H
+
+#include <cstddef>
+
+#include <boost/utility.hpp>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/fiber_state.hpp>
+#include <boost/fiber/scheduler.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+
+class BOOST_FIBER_DECL disable_interruption : private noncopyable
+{
+private:
+	bool	set_;
+
+public:
+	disable_interruption() :
+		set_( ( scheduler::active_fiber().info_->interrupt & detail::INTERRUPTION_BLOCKED) != 0)
+	{
+		if ( ! set_)
+			scheduler::active_fiber().info_->interrupt |= detail::INTERRUPTION_BLOCKED;
+	}
+
+	~disable_interruption()
+	{
+		if ( ! set_)
+			scheduler::active_fiber().info_->interrupt &= ~detail::INTERRUPTION_BLOCKED;
+	}
+};
+
+class BOOST_FIBER_DECL restore_interruption : private noncopyable
+{
+private:
+	bool	set_;
+
+public:
+	restore_interruption() :
+		set_( ( scheduler::active_fiber().info_->interrupt & detail::INTERRUPTION_BLOCKED) != 0)
+	{
+		if ( set_)
+			scheduler::active_fiber().info_->interrupt &= ~detail::INTERRUPTION_BLOCKED;
+	}
+
+	~restore_interruption()
+	{  
+		if ( set_)
+			scheduler::active_fiber().info_->interrupt |= detail::INTERRUPTION_BLOCKED;
+	}
+};
+
+}}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_FIBERS_INTERRUPTION_H
Modified: sandbox/fiber/boost/fiber/scheduler.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/scheduler.hpp	(original)
+++ sandbox/fiber/boost/fiber/scheduler.hpp	2009-11-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -33,11 +33,15 @@
 int priority();
 void priority( int);
 void interruption_point();
+bool interruption_requested();
 
 }
 
 namespace fibers {
 
+class disable_interruption;
+class restore_interruption;
+
 class BOOST_FIBER_DECL scheduler : private noncopyable
 {
 private:
@@ -49,7 +53,10 @@
         friend int this_fiber::priority();
         friend void this_fiber::priority( int);
         friend void this_fiber::interruption_point();
+	friend bool this_fiber::interruption_requested();
         friend class fiber;
+	friend class disable_interruption;
+	friend class restore_interruption;
 
         typedef scoped_ptr< detail::scheduler_impl >	impl_t;
 
@@ -57,7 +64,7 @@
 
         static bool runs_as_fiber();
 
-	static fiber::id active_fiber();
+	static fiber const& active_fiber();
 
         static void yield_active_fiber();
 
@@ -65,21 +72,19 @@
 
         static void suspend_active_fiber();
 
+	static void interrupt_active_fiber();
+
+	static void priority_active_fiber( int);
+
         static void cancel_fiber( fiber::id const&);
 
         static void suspend_fiber( fiber::id const&);
 
         static void resume_fiber( fiber::id const&);
 
-	static int priority( fiber::id const&);
-
-	static void priority( fiber::id const&, int);
-
-	static void re_schedule( fiber::id const&);
-
-	static void join( fiber::id const&);
+	static void reschedule_fiber( fiber::id const&);
 
-	static void interruption_point();
+	static void join_fiber( fiber::id const&);
 
 public:
         scheduler();
Modified: sandbox/fiber/boost/fiber/utility.hpp
==============================================================================
--- sandbox/fiber/boost/fiber/utility.hpp	(original)
+++ sandbox/fiber/boost/fiber/utility.hpp	2009-11-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -25,7 +25,7 @@
 
 inline
 fiber::id get_id()
-{ return fibers::scheduler::active_fiber(); }
+{ return fibers::scheduler::active_fiber().get_id(); }
 
 inline
 void yield()
@@ -41,15 +41,19 @@
 
 inline
 int priority()
-{ return fibers::scheduler::priority( get_id() ); }
+{ return fibers::scheduler::active_fiber().priority(); }
 
 inline
 void priority( int prio)
-{ fibers::scheduler::priority( get_id(), prio); }
+{ fibers::scheduler::priority_active_fiber( prio); }
 
 inline
 void interruption_point()
-{ fibers::scheduler::interruption_point(); }
+{ fibers::scheduler::interrupt_active_fiber(); }
+
+inline
+bool interruption_requested()
+{ return fibers::scheduler::active_fiber().interruption_requested(); }
 
 }}
 
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -25,6 +25,7 @@
 
 exe suspend : suspend.cpp ;
 exe join : join.cpp ;
+exe interrupt : interrupt.cpp ;
 exe cancel : cancel.cpp ;
 exe simple : simple.cpp ;
 exe ping_pong : ping_pong.cpp ;
Added: sandbox/fiber/libs/fiber/examples/interrupt.cpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/libs/fiber/examples/interrupt.cpp	2009-11-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -0,0 +1,121 @@
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+#include <boost/bind.hpp>
+#include <boost/system/system_error.hpp>
+
+#include <boost/fiber.hpp>
+
+int value1 = 0;
+int value2 = 0;
+int value3 = 0;
+
+void fn_1()
+{
+	for ( int i = 0; i < 10; ++i)
+	{
+		++value1;
+		std::cout << "fn_1() increment value1 " << value1 << std::endl;
+		boost::this_fiber::interruption_point();
+		boost::this_fiber::yield();
+	}
+}
+
+void fn_2()
+{
+	boost::fibers::disable_interruption disabled;
+	for ( int i = 0; i < 10; ++i)
+	{
+		++value2;
+		std::cout << "fn_2() increment value2 " << value2 << std::endl;
+		boost::this_fiber::interruption_point();
+		boost::this_fiber::yield();
+	}
+}
+
+void fn_3()
+{
+	boost::fibers::disable_interruption disabled;
+	for ( int i = 0; i < 10; ++i)
+	{
+		++value3;
+		std::cout << "fn_3() increment value3 " << value3 << std::endl;
+		boost::fibers::restore_interruption restored;
+		boost::this_fiber::interruption_point();
+		boost::this_fiber::yield();
+	}
+}
+
+void fn_4( boost::fiber f)
+{
+	for ( int i = 0; i < 10; ++i)
+	{
+		if ( i == 1)
+		{
+			std::cout << "fn_4() interrupt fiber " << f.get_id() << std::endl;
+			f.interrupt();
+			break;
+		}
+		boost::this_fiber::yield();
+	}
+}
+
+int main()
+{
+	try
+	{
+		boost::fibers::scheduler sched;
+
+		boost::fiber f1( fn_1);
+		sched.submit_fiber( f1);
+		sched.make_fiber( fn_4, f1);
+
+		std::cout << "start: interrupt fn_1()" << std::endl;
+
+		for (;;)
+		{
+			while ( sched.run() );
+			if ( sched.empty() ) break;
+		}
+
+		std::cout << "finish: value1 == " << value1 << std::endl;
+
+		boost::fiber f2( fn_2);
+		sched.submit_fiber( f2);
+		sched.make_fiber( fn_4, f2);
+		std::cout << "start: interrupt fn_2()" << std::endl;
+
+		for (;;)
+		{
+			while ( sched.run() );
+			if ( sched.empty() ) break;
+		}
+
+		std::cout << "finish: value2 == " << value2 << std::endl;
+
+		boost::fiber f3( fn_3);
+		sched.submit_fiber( f3);
+		sched.make_fiber( fn_4, f3);
+		std::cout << "start: interrupt fn_3()" << std::endl;
+
+		for (;;)
+		{
+			while ( sched.run() );
+			if ( sched.empty() ) break;
+		}
+
+		std::cout << "finish: value3 == " << value3 << 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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -116,21 +116,22 @@
 {
         if ( ! info_) throw fiber_moved();
         info_->attrs.priority( prio);
-	if ( is_alive() ) scheduler::re_schedule( get_id() );
+	if ( is_alive() ) scheduler::reschedule_fiber( get_id() );
 }
 
 void
 fiber::interrupt()
 {
         if ( ! info_) throw fiber_moved();
-	info_->interrupt = true;
+	info_->interrupt &= ~detail::INTERRUPTION_DISABLED;
+	info_->interrupt |= detail::INTERRUPTION_ENABLED;
 }
 
 bool
 fiber::interruption_requested() const
 {
         if ( ! info_) throw fiber_moved();
-	return info_->interrupt;
+	return ( info_->interrupt & detail::INTERRUPTION_ENABLED) != 0;
 }
 
 void
@@ -147,7 +148,7 @@
 
 void
 fiber::join()
-{ scheduler::join( get_id() ); }
+{ scheduler::join_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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -23,7 +23,7 @@
         uctx(),
         uctx_stack(),
         state( STATE_MASTER),
-	interrupt( false)
+	interrupt( INTERRUPTION_DISABLED)
 {}
 
 fiber_info_base::fiber_info_base( attributes const& attrs_) :
@@ -32,7 +32,7 @@
         uctx(),
         uctx_stack( new char[attrs.stack_size()]),
         state( STATE_NOT_STARTED),
-	interrupt( false)
+	interrupt( INTERRUPTION_DISABLED)
 {
         BOOST_ASSERT( uctx_stack);
 
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -24,7 +24,7 @@
         attrs(),
         uctx(),
         state( STATE_MASTER),
-	interrupt( false)
+	interrupt( INTERRUPTION_DISABLED)
 {
         uctx = ::GetCurrentFiber();
         if ( ! uctx)
@@ -42,7 +42,7 @@
         attrs( attrs_),
         uctx(),
         state( STATE_NOT_STARTED),
-	interrupt( false)
+	interrupt( INTERRUPTION_DISABLED)
 {}
 
 }}}
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -21,7 +21,7 @@
 scheduler::runs_as_fiber()
 { return impl_; }
 
-fiber::id
+fiber const&
 scheduler::active_fiber()
 {
         if ( ! impl_) throw fiber_error("not a fiber");
@@ -50,6 +50,20 @@
 }
 
 void
+scheduler::interrupt_active_fiber()
+{
+	if ( ! impl_) throw fiber_error("not a fiber");
+	impl_->interrupt_active_fiber();
+}
+
+void
+scheduler::priority_active_fiber( int prio)
+{
+	if ( ! impl_) throw fiber_error("not a fiber");
+	impl_->priority_active_fiber( prio);
+}
+
+void
 scheduler::cancel_fiber( fiber::id const& id)
 {
         if ( ! impl_) throw fiber_error("not a fiber");
@@ -70,33 +84,20 @@
         impl_->resume_fiber( id);
 }
 
-int
-scheduler::priority( fiber::id const& id)
+void
+scheduler::reschedule_fiber( fiber::id const& id)
 {
         if ( ! impl_) throw fiber_error("not a fiber");
-	return impl_->priority( id);
+	impl_->reschedule_fiber( id);
 }
 
 void
-scheduler::priority( fiber::id const& id, int prio)
+scheduler::join_fiber( fiber::id const& id)
 {
         if ( ! impl_) throw fiber_error("not a fiber");
-	impl_->priority( id, prio);
-	re_schedule( id);
+	impl_->join_fiber( id);
 }
 
-void
-scheduler::re_schedule( fiber::id const& id)
-{ impl_->re_schedule( id); }
-
-void
-scheduler::join( fiber::id const& id)
-{ impl_->join( id); }
-
-void
-scheduler::interruption_point()
-{ impl_->interrupt_active_fiber(); }
-
 scheduler::scheduler()
 {
         fiber::convert_thread_to_fiber();
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -70,9 +70,9 @@
         runnable_fibers_.push_back( result.first->first);
 }
 
-fiber::id
+fiber const&
 scheduler_impl::active_fiber() const
-{ return active_.get_id(); }
+{ return active_; }
 
 void
 scheduler_impl::yield_active_fiber()
@@ -129,7 +129,18 @@
         BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
         BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
 
-	if ( active_.info_->interrupt) throw fiber_interrupted();
+	if ( INTERRUPTION_ENABLED == active_.info_->interrupt)
+		throw fiber_interrupted();
+}
+
+void
+scheduler_impl::priority_active_fiber( int prio)
+{
+	BOOST_ASSERT( ! HAS_STATE_MASTER( active_.info_->state) );
+	BOOST_ASSERT( STATE_RUNNING == active_.info_->state);
+
+	active_.priority( prio);
+	reschedule_fiber( active_.get_id() );
 }
 
 void
@@ -235,33 +246,8 @@
         }
 }
 
-int
-scheduler_impl::priority( fiber::id const& id)
-{
-	container::iterator i = fibers_.find( id);
-	if ( i == fibers_.end() ) throw scheduler_error("fiber not found");
-	fiber f( i->second.f);
-	BOOST_ASSERT( f);
-	BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
-
-	return f.info_->attrs.priority();
-}
-
-void
-scheduler_impl::priority( fiber::id const& id, int prio)
-{
-	container::iterator i = fibers_.find( id);
-	if ( i == fibers_.end() ) throw scheduler_error("fiber not found");
-	fiber f( i->second.f);
-	BOOST_ASSERT( f);
-	BOOST_ASSERT( ! HAS_STATE_MASTER( f.info_->state) );
-
-	f.info_->attrs.priority( prio);
-	re_schedule( id);
-}
-
 void
-scheduler_impl::re_schedule( fiber::id const& id)
+scheduler_impl::reschedule_fiber( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);
         if ( i == fibers_.end() ) return;
@@ -274,7 +260,7 @@
 }
 
 void
-scheduler_impl::join( fiber::id const& id)
+scheduler_impl::join_fiber( fiber::id const& id)
 {
         container::iterator i = fibers_.find( id);
         if ( i == fibers_.end() ) return;
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-16 15:51:54 EST (Mon, 16 Nov 2009)
@@ -31,22 +31,40 @@
         { interrupted = true; }
 }
 
-void fn_2( boost::fiber f)
+void fn_2()
 {
+	boost::fibers::disable_interruption disabled;
         for ( int i = 0; i < 5; ++i)
         {
-		++value2;
-		if ( i == 1) f.interrupt();
+		++value1;
+		boost::this_fiber::interruption_point();
                 boost::this_fiber::yield();
         }
 }
 
 void fn_3()
 {
+	try
+	{
+		boost::fibers::disable_interruption disabled;
+		for ( int i = 0; i < 5; ++i)
+		{
+			++value1;
+			boost::fibers::restore_interruption restored;
+			boost::this_fiber::interruption_point();
+			boost::this_fiber::yield();
+		}
+	}
+	catch ( boost::fibers::fiber_interrupted const&)
+	{ interrupted = true; }
+}
+
+void fn_5( boost::fiber f)
+{
         for ( int i = 0; i < 5; ++i)
         {
-		++value1;
-		boost::this_fiber::interruption_point();
+		++value2;
+		if ( i == 1) f.interrupt();
                 boost::this_fiber::yield();
         }
 }
@@ -61,7 +79,7 @@
 
         boost::fiber f( fn_1);
         sched.submit_fiber( f);
-	sched.make_fiber( fn_2, f);
+	sched.make_fiber( fn_5, f);
 
         BOOST_CHECK_EQUAL( 0, value1);
         BOOST_CHECK_EQUAL( 0, value2);
@@ -141,75 +159,64 @@
 {
         value1 = 0;
         value2 = 0;
+	interrupted = false;
 
         boost::fibers::scheduler sched;
 
-	boost::fiber f( fn_3);
+	boost::fiber f( fn_2);
         sched.submit_fiber( f);
-	sched.make_fiber( fn_2, f);
+	sched.make_fiber( fn_5, f);
 
         BOOST_CHECK_EQUAL( 0, value1);
         BOOST_CHECK_EQUAL( 0, value2);
-
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
-	BOOST_CHECK_EQUAL( 1, value1);
-	BOOST_CHECK_EQUAL( 0, value2);
-
-	BOOST_CHECK( sched.run() );
+	BOOST_CHECK_EQUAL( false, interrupted);
         BOOST_CHECK( ! sched.empty() );
         BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
-	BOOST_CHECK_EQUAL( 1, value1);
-	BOOST_CHECK_EQUAL( 1, value2);
 
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
-	BOOST_CHECK_EQUAL( 2, value1);
-	BOOST_CHECK_EQUAL( 1, value2);
+	for (;;)
+	{
+		while ( sched.run() );
+		if ( sched.empty() ) break;
+	}
 
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
-	BOOST_CHECK_EQUAL( 2, value1);
-	BOOST_CHECK_EQUAL( 2, value2);
+	BOOST_CHECK( ! sched.run() );
+	BOOST_CHECK( sched.empty() );
+	BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
+	BOOST_CHECK_EQUAL( 5, value1);
+	BOOST_CHECK_EQUAL( 5, value2);
+	BOOST_CHECK_EQUAL( false, interrupted);
+}
 
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
-	BOOST_CHECK_EQUAL( 3, value1);
-	BOOST_CHECK_EQUAL( 2, value2);
+void test_case_3()
+{
+	value1 = 0;
+	value2 = 0;
+	interrupted = false;
 
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
-	BOOST_CHECK_EQUAL( 3, value1);
-	BOOST_CHECK_EQUAL( 3, value2);
+	boost::fibers::scheduler sched;
 
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
-	BOOST_CHECK_EQUAL( 3, value1);
-	BOOST_CHECK_EQUAL( 4, value2);
+	boost::fiber f( fn_3);
+	sched.submit_fiber( f);
+	sched.make_fiber( fn_5, f);
 
-	BOOST_CHECK( sched.run() );
+	BOOST_CHECK_EQUAL( 0, value1);
+	BOOST_CHECK_EQUAL( 0, value2);
+	BOOST_CHECK_EQUAL( false, interrupted);
         BOOST_CHECK( ! sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 1), sched.size() );
-	BOOST_CHECK_EQUAL( 3, value1);
-	BOOST_CHECK_EQUAL( 5, value2);
+	BOOST_CHECK_EQUAL( std::size_t( 2), sched.size() );
 
-	BOOST_CHECK( sched.run() );
-	BOOST_CHECK( sched.empty() );
-	BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
-	BOOST_CHECK_EQUAL( 3, value1);
-	BOOST_CHECK_EQUAL( 5, value2);
+	for (;;)
+	{
+		while ( sched.run() );
+		if ( sched.empty() ) break;
+	}
 
         BOOST_CHECK( ! sched.run() );
         BOOST_CHECK( sched.empty() );
         BOOST_CHECK_EQUAL( std::size_t( 0), sched.size() );
         BOOST_CHECK_EQUAL( 3, value1);
         BOOST_CHECK_EQUAL( 5, value2);
+	BOOST_CHECK_EQUAL( true, interrupted);
 }
 
 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
@@ -219,6 +226,7 @@
 
         test->add( BOOST_TEST_CASE( & test_case_1) );
         test->add( BOOST_TEST_CASE( & test_case_2) );
+	test->add( BOOST_TEST_CASE( & test_case_3) );
 
         return test;
 }