diff --git a/src/detail/fiber_base.cpp b/src/detail/fiber_base.cpp index d987c97b..f2940fcf 100644 --- a/src/detail/fiber_base.cpp +++ b/src/detail/fiber_base.cpp @@ -37,6 +37,8 @@ fiber_base::fiber_base( context::fcontext_t * callee, bool preserve_fpu) : void fiber_base::resume() { + BOOST_ASSERT( is_running() ); + context::jump_fcontext( & caller_, callee_, 0, preserve_fpu() ); if ( has_exception() ) rethrow(); @@ -47,6 +49,8 @@ fiber_base::suspend() { context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() ); + BOOST_ASSERT( is_running() ); + if ( unwind_requested() ) throw forced_unwind(); } diff --git a/src/round_robin.cpp b/src/round_robin.cpp index f48c2950..0cca2a58 100644 --- a/src/round_robin.cpp +++ b/src/round_robin.cpp @@ -216,6 +216,7 @@ round_robin::migrate_to( fiber const& f_) { detail::fiber_base::ptr_t f = detail::scheduler::extract( f_); BOOST_ASSERT( f); + BOOST_ASSERT( ! f->is_running() ); BOOST_ASSERT( ! f->is_terminated() ); wqueue_.push_back( f); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 600d38e0..1959e4b5 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -34,4 +34,5 @@ test-suite fibers : [ fiber-test test_futures ] [ fiber-test test_then ] [ fiber-test test_round_robin ] +# [ fiber-test test_fiber_steeling ] ; diff --git a/test/test_fiber_steeling.cpp b/test/test_fiber_steeling.cpp new file mode 100644 index 00000000..84715f2f --- /dev/null +++ b/test/test_fiber_steeling.cpp @@ -0,0 +1,124 @@ + +// 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 +#include +#include + +#include +#include +#include +#include + +#include + +#define MAXCOUNT 50 + +boost::atomic< bool > fini( false); +boost::fibers::round_robin * other_ds = 0; + +boost::fibers::shared_future< int > fibonacci( int n); + +int fibonacci_( int n) +{ + boost::this_fiber::yield(); + + int res = 1; + + if ( 0 != n && 1 != n) + { + boost::fibers::shared_future< int > f1 = fibonacci( n - 1); + boost::fibers::shared_future< int > f2 = fibonacci( n - 2); + + res = f1.get() + f2.get(); + } + + return res; +} + +boost::fibers::shared_future< int > fibonacci( int n) +{ + boost::fibers::packaged_task pt( + boost::bind( fibonacci_, n) ); + boost::fibers::shared_future f(pt.get_future()); + boost::fibers::fiber( boost::move(pt) ).detach(); + return f; +} + +void create_fibers( int n) +{ + int res = fibonacci( n).get(); + + fprintf(stderr, "fibonacci(%d) == %d\n", n, res); +} + +void fn_create_fibers( boost::fibers::round_robin * ds, boost::barrier * b, int n) +{ + boost::fibers::scheduling_algorithm( ds); + + b->wait(); + + boost::fibers::fiber f1( + boost::bind( create_fibers, n) ); + boost::fibers::fiber f2( + boost::bind( create_fibers, n) ); + + f1.join(); + f2.join(); + + fini = true; +} + +void fn_steel_fibers( boost::fibers::round_robin * other_ds, boost::barrier * b, int * count) +{ + BOOST_ASSERT( other_ds); + boost::fibers::round_robin ds; + boost::fibers::scheduling_algorithm( & ds); + + b->wait(); + + while ( ! fini) + { + boost::fibers::fiber f( other_ds->steel_from() ); + if ( f) + { + ++( * count); + ds.migrate_to( f); + while ( boost::fibers::run() ); + } + f.detach(); + } +} + +void test_migrate_fiber() +{ + for ( int i = 0; i < MAXCOUNT; ++i) { + fini = false; + int n = 10, count = 0; + + boost::fibers::round_robin * ds = new boost::fibers::round_robin(); + boost::barrier b( 2); + boost::thread t1( boost::bind( fn_create_fibers, ds, &b, n) ); + boost::thread t2( boost::bind( fn_steel_fibers, ds, &b, &count) ); + + t1.join(); + t2.join(); + + fprintf(stderr, "stolen fibers == %d\n", count); + fprintf(stderr, "%d. finished\n", i); + delete ds; + } +} + +boost::unit_test::test_suite * init_unit_test_suite( int, char* []) +{ + boost::unit_test::test_suite * test = + BOOST_TEST_SUITE("Boost.Fiber: round_robin test suite"); + + test->add( BOOST_TEST_CASE( & test_migrate_fiber) ); + + return test; +} diff --git a/test/test_round_robin.cpp b/test/test_round_robin.cpp index ae8b7968..74020239 100644 --- a/test/test_round_robin.cpp +++ b/test/test_round_robin.cpp @@ -30,7 +30,7 @@ void lazy_generate( boost::barrier * b, int * value) boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC_); - xt.nsec += 50000000 ; // 50ms + xt.nsec += 150000000 ; // 150ms //xt.sec += 1; //1 second boost::this_thread::sleep( xt); @@ -77,6 +77,7 @@ void interrupt_join_fiber( boost::barrier * b, int * value, bool * interrupted) } catch ( boost::fibers::fiber_interrupted const&) { * interrupted = true; } + //fprintf(stderr, "interrupt_join_fiber() returned\n"); } void running( boost::barrier * b, int * value) @@ -419,99 +420,6 @@ void test_two_waiter_notify_all() } } -boost::fibers::shared_future< int > fibonacci( int n); - -int fibonacci_( int n) -{ - boost::this_fiber::yield(); - - int res = 1; - - if ( 0 != n && 1 != n) - { - boost::fibers::shared_future< int > f1 = fibonacci( n - 1); - boost::fibers::shared_future< int > f2 = fibonacci( n - 2); - - res = f1.get() + f2.get(); - } - - return res; -} - -boost::fibers::shared_future< int > fibonacci( int n) -{ - boost::fibers::packaged_task pt( - boost::bind( fibonacci_, n) ); - boost::fibers::shared_future f(pt.get_future()); - boost::fibers::fiber( boost::move(pt) ).detach(); - return f; -} - -void create_fibers( int n) -{ - int res = fibonacci( n).get(); - - fprintf(stderr, "fibonacci(%d) == %d\n", n, res); -} - -void fn_create_fibers( boost::fibers::round_robin * ds, boost::barrier * b, int n) -{ - boost::fibers::scheduling_algorithm( ds); - - b->wait(); - - boost::fibers::fiber f1( - boost::bind( create_fibers, n) ); - boost::fibers::fiber f2( - boost::bind( create_fibers, n) ); - - f1.join(); - f2.join(); - - fini = true; -} - -void fn_steel_fibers( boost::fibers::round_robin * other_ds, boost::barrier * b, int * count) -{ - BOOST_ASSERT( other_ds); - boost::fibers::round_robin ds; - boost::fibers::scheduling_algorithm( & ds); - - b->wait(); - - while ( ! fini) - { - boost::fibers::fiber f( other_ds->steel_from() ); - if ( f) - { - ++( * count); - ds.migrate_to( f); - while ( boost::fibers::run() ); - } - f.detach(); - } -} - -void test_migrate_fiber() -{ - for ( int i = 0; i < MAXCOUNT; ++i) { - fini = false; - int n = 10, count = 0; - - boost::fibers::round_robin * ds = new boost::fibers::round_robin(); - boost::barrier b( 2); - boost::thread t1( boost::bind( fn_create_fibers, ds, &b, n) ); - boost::thread t2( boost::bind( fn_steel_fibers, ds, &b, &count) ); - - t1.join(); - t2.join(); - - fprintf(stderr, "stolen fibers == %d\n", count); - fprintf(stderr, "%d. finished\n", i); - delete ds; - } -} - boost::unit_test::test_suite * init_unit_test_suite( int, char* []) { boost::unit_test::test_suite * test = @@ -519,13 +427,13 @@ boost::unit_test::test_suite * init_unit_test_suite( int, char* []) #if 0 test->add( BOOST_TEST_CASE( & test_join_in_fiber_runing) ); test->add( BOOST_TEST_CASE( & test_join_in_fiber_terminated) ); +#endif test->add( BOOST_TEST_CASE( & test_join_in_fiber_interrupted_inside) ); +#if 0 test->add( BOOST_TEST_CASE( & test_join_in_fiber_interrupted_outside) ); test->add( BOOST_TEST_CASE( & test_mutex_exclusive) ); test->add( BOOST_TEST_CASE( & test_two_waiter_notify_one) ); test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) ); #endif - test->add( BOOST_TEST_CASE( & test_migrate_fiber) ); - return test; }