From a6e5fe64da6c37ddd1aad9439ca7bca88bfa5ec0 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Wed, 12 Mar 2014 17:39:45 +0100 Subject: [PATCH] fix unwinding symmetric coroutine --- example/cpp03/asymmetric/Jamfile.v2 | 34 ++++++++++- example/cpp03/symmetric/Jamfile.v2 | 4 ++ example/cpp03/symmetric/unwind.cpp | 50 ++++++++++++++++ include/boost/coroutine/detail/trampoline.hpp | 57 ++++++++++--------- test/test_symmetric_coroutine.cpp | 11 ++-- 5 files changed, 124 insertions(+), 32 deletions(-) create mode 100644 example/cpp03/symmetric/unwind.cpp diff --git a/example/cpp03/asymmetric/Jamfile.v2 b/example/cpp03/asymmetric/Jamfile.v2 index 0033d96..1a7f39c 100644 --- a/example/cpp03/asymmetric/Jamfile.v2 +++ b/example/cpp03/asymmetric/Jamfile.v2 @@ -29,6 +29,36 @@ project boost/coroutine/example multi ; -exe test_case - : test_case.cpp +exe chaining + : chaining.cpp + ; +exe echo + : echo.cpp + ; +exe exception + : exception.cpp + ; +exe fibonacci + : fibonacci.cpp + ; +exe layout + : layout.cpp + ; +exe parallel + : parallel.cpp + ; +exe power + : power.cpp + ; +exe same_fringe + : same_fringe.cpp + ; +exe segmented_stack + : segmented_stack.cpp + ; +exe simple + : simple.cpp + ; +exe unwind + : unwind.cpp ; diff --git a/example/cpp03/symmetric/Jamfile.v2 b/example/cpp03/symmetric/Jamfile.v2 index 2ea1fd7..c659ada 100644 --- a/example/cpp03/symmetric/Jamfile.v2 +++ b/example/cpp03/symmetric/Jamfile.v2 @@ -41,3 +41,7 @@ exe dice_game exe merge_arrays : merge_arrays.cpp ; + +exe unwind + : unwind.cpp + ; diff --git a/example/cpp03/symmetric/unwind.cpp b/example/cpp03/symmetric/unwind.cpp new file mode 100644 index 0000000..18042e7 --- /dev/null +++ b/example/cpp03/symmetric/unwind.cpp @@ -0,0 +1,50 @@ + +// 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 + +struct X : private boost::noncopyable +{ + X() { std::cout << "X()" << std::endl; } + ~X() { std::cout << "~X()" << std::endl; } +}; + +typedef boost::coroutines::symmetric_coroutine< void > coro_t; + +coro_t::call_type * c1 = 0; +coro_t::call_type * c2 = 0; + +void foo( coro_t::yield_type & yield) +{ + X x; + std::cout << "foo() entered" << std::endl; + yield( * c2); + yield( * c2); + std::cout << "foo() finished" << std::endl; +} + +void bar( coro_t::yield_type & yield) +{ + std::cout << "bar() entered" << std::endl; + yield( * c1); + std::cout << "bar() finished" << std::endl; +} + +int main( int argc, char * argv[]) +{ + coro_t::call_type coro1( foo); + coro_t::call_type coro2( bar); + c1 = & coro1; + c2 = & coro2; + coro1(); + std::cout << "Done" << std::endl; + + return EXIT_SUCCESS; +} diff --git a/include/boost/coroutine/detail/trampoline.hpp b/include/boost/coroutine/detail/trampoline.hpp index 52fe972..ed1e73b 100644 --- a/include/boost/coroutine/detail/trampoline.hpp +++ b/include/boost/coroutine/detail/trampoline.hpp @@ -57,19 +57,20 @@ void trampoline( intptr_t vp) reinterpret_cast< param_type * >( c.callee_.jump( c.caller_, - reinterpret_cast< intptr_t >( & c), + reinterpret_cast< intptr_t >( & c), c.preserve_fpu() ) ) ); - c.flags_ |= flag_running; - - // create yield_type - Self yield( & c, from->data); - c.flags_ |= flag_running; - try - { fn( yield); } - catch ( forced_unwind const&) - {} - catch (...) - { std::terminate(); } + if ( ! from->do_unwind) + { + // create yield_type + Self yield( & c, from->data); + c.flags_ |= flag_running; + try + { fn( yield); } + catch ( forced_unwind const&) + {} + catch (...) + { std::terminate(); } + } } c.flags_ |= flag_complete; @@ -99,20 +100,24 @@ void trampoline_void( intptr_t vp) from = 0; { - c.callee_.jump( - c.caller_, - reinterpret_cast< intptr_t >( & c), - c.preserve_fpu() ); - c.flags_ |= flag_running; - - // create yield_type - Self yield( & c); - try - { fn( yield); } - catch ( forced_unwind const&) - {} - catch (...) - { std::terminate(); } + param_type * from( + reinterpret_cast< param_type * >( + c.callee_.jump( + c.caller_, + reinterpret_cast< intptr_t >( & c), + c.preserve_fpu() ) ) ); + if ( ! from->do_unwind) + { + // create yield_type + Self yield( & c); + c.flags_ |= flag_running; + try + { fn( yield); } + catch ( forced_unwind const&) + {} + catch (...) + { std::terminate(); } + } } c.flags_ |= flag_complete; diff --git a/test/test_symmetric_coroutine.cpp b/test/test_symmetric_coroutine.cpp index cafe61f..741a65f 100644 --- a/test/test_symmetric_coroutine.cpp +++ b/test/test_symmetric_coroutine.cpp @@ -130,8 +130,11 @@ public: state( true) {} - void operator()( coro::symmetric_coroutine< int >::yield_type &) - { value1 = state; } + void operator()( coro::symmetric_coroutine< bool >::yield_type & yield) + { + if ( yield) + value1 = yield.get(); + } }; class moveable @@ -290,8 +293,8 @@ void test_move() copyable cp( 3); BOOST_CHECK( cp.state); BOOST_CHECK( ! value1); - coro::symmetric_coroutine< int >::call_type coro( cp); - coro( 3); + coro::symmetric_coroutine< bool >::call_type coro( cp); + coro( true); BOOST_CHECK( cp.state); BOOST_CHECK( value1); }