From c913a541d1ab6fdf1426d3656d3f20e6a89d5252 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Tue, 11 Mar 2014 19:52:39 +0100 Subject: [PATCH] corrected corourine_context in asyymetric coroutine --- doc/performance.qbk | 28 +++---- example/cpp03/asymmetric/Jamfile.v2 | 34 +------- example/cpp03/asymmetric/simple.cpp | 50 ++---------- example/cpp11/asymmetric/Jamfile.v2 | 4 + .../boost/coroutine/asymmetric_coroutine.hpp | 18 +++-- .../coroutine/detail/pull_coroutine_impl.hpp | 72 ++++++++--------- .../coroutine/detail/push_coroutine_impl.hpp | 64 +++++++-------- .../detail/symmetric_coroutine_call.hpp | 1 - .../coroutine/detail/trampoline_pull.hpp | 32 +++++--- .../coroutine/detail/trampoline_push.hpp | 79 +++++++++++-------- 10 files changed, 173 insertions(+), 209 deletions(-) diff --git a/doc/performance.qbk b/doc/performance.qbk index 2c05624..f99899d 100644 --- a/doc/performance.qbk +++ b/doc/performance.qbk @@ -23,17 +23,17 @@ running thread was pinned to a single CPU. ] [ [i386 (AMD Athlon 64 DualCore 4400+, Linux 32bit)] - [53 ns / 54 cycles] - [195 \u00b5s / 216006 cycles] - [9 \u00b5s / 9691 cycles] - [629 ns / 603 cycles] + [49 ns / 50 cycles] + [53 \u00b5s / 53646 cycles] + [25 \u00b5s / 24447 cycles] + [14 \u00b5s / 15141 cycles] ] [ [x86_64 (Intel Core2 Q6700, Linux 64bit)] [12 ns / 39 cycles] - [37 \u00b5s / 101999 cycles] - [3 \u00b5s / 9719 cycles] - [248 ns / 632 cycles] + [18 \u00b5s / 40723 cycles] + [9 \u00b5s / 19462 cycles] + [6 \u00b5s / 18073 cycles] ] ] @@ -47,17 +47,17 @@ running thread was pinned to a single CPU. ] [ [i386 (AMD Athlon 64 DualCore 4400+, Linux 32bit)] - [50 ns / 52 cycles] - [221 \u00b5s / 214170 cycles] - [245 ns / 245 cycles] - [481 ns / 501 cycles] + [47 ns / 49 cycles] + [28 \u00b5s / 28671 cycles] + [317 ns / 317 cycles] + [562 ns / 534 cycles] ] [ [x86_64 (Intel Core2 Q6700, Linux 64bit)] [10 ns / 33 cycles] - [35 \u00b5s / 90504 cycles] - [95 ns / 241 cycles] - [199 ns / 508 cycles] + [13 \u00b5s / 22828 cycles] + [98 ns / 241 cycles] + [204 ns / 507 cycles] ] ] diff --git a/example/cpp03/asymmetric/Jamfile.v2 b/example/cpp03/asymmetric/Jamfile.v2 index 8a3c609..0033d96 100644 --- a/example/cpp03/asymmetric/Jamfile.v2 +++ b/example/cpp03/asymmetric/Jamfile.v2 @@ -29,36 +29,6 @@ project boost/coroutine/example multi ; -exe simple - : simple.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 unwind - : unwind.cpp +exe test_case + : test_case.cpp ; diff --git a/example/cpp03/asymmetric/simple.cpp b/example/cpp03/asymmetric/simple.cpp index 8b929bd..52147c2 100644 --- a/example/cpp03/asymmetric/simple.cpp +++ b/example/cpp03/asymmetric/simple.cpp @@ -4,61 +4,23 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include #include #include #include -struct X +void coro(boost::coroutines::coroutine::pull_type& c) { - int i; - - X( int i_) : - i( i_) - {} -}; - -typedef boost::coroutines::asymmetric_coroutine< X& >::pull_type pull_coro_t; -typedef boost::coroutines::asymmetric_coroutine< X& >::push_type push_coro_t; - -void fn1( push_coro_t & sink) -{ - for ( int i = 0; i < 10; ++i) - { - X x( i); - sink( x); - } + std::printf("in coro!\n"); } -void fn2( pull_coro_t & source) -{ - while ( source) { - X & x = source.get(); - std::cout << "i = " << x.i << std::endl; - source(); - } -} - -int main( int argc, char * argv[]) +int main() { { - pull_coro_t source( fn1); - while ( source) { - X & x = source.get(); - std::cout << "i = " << x.i << std::endl; - source(); - } + boost::coroutines::coroutine::push_type p(coro); + std::printf("after construction\n"); } - { - push_coro_t sink( fn2); - for ( int i = 0; i < 10; ++i) - { - X x( i); - sink( x); - } - } - std::cout << "Done" << std::endl; - return EXIT_SUCCESS; } diff --git a/example/cpp11/asymmetric/Jamfile.v2 b/example/cpp11/asymmetric/Jamfile.v2 index 335f780..22a0173 100644 --- a/example/cpp11/asymmetric/Jamfile.v2 +++ b/example/cpp11/asymmetric/Jamfile.v2 @@ -45,6 +45,10 @@ exe iterator_range : iterator_range.cpp ; +exe test_case + : test_case.cpp + ; + #exe await_emu # : await_emu.cpp # ; diff --git a/include/boost/coroutine/asymmetric_coroutine.hpp b/include/boost/coroutine/asymmetric_coroutine.hpp index bcbbd20..52e8592 100644 --- a/include/boost/coroutine/asymmetric_coroutine.hpp +++ b/include/boost/coroutine/asymmetric_coroutine.hpp @@ -117,8 +117,9 @@ public: ~push_coroutine() { - if ( 0 != impl_) + if ( 0 != stack_ctx_.sp) { + BOOST_ASSERT( 0 != impl_); impl_->unwind_stack(); stack_alloc_.deallocate( stack_ctx_); impl_ = 0; @@ -269,8 +270,9 @@ public: ~push_coroutine() { - if ( 0 != impl_) + if ( 0 != stack_ctx_.sp) { + BOOST_ASSERT( 0 != impl_); impl_->unwind_stack(); stack_alloc_.deallocate( stack_ctx_); impl_ = 0; @@ -420,8 +422,9 @@ public: ~push_coroutine() { - if ( 0 != impl_) + if ( 0 != stack_ctx_.sp) { + BOOST_ASSERT( 0 != impl_); impl_->unwind_stack(); stack_alloc_.deallocate( stack_ctx_); impl_ = 0; @@ -693,8 +696,9 @@ public: ~pull_coroutine() { - if ( 0 != impl_) + if ( 0 != stack_ctx_.sp) { + BOOST_ASSERT( 0 != impl_); impl_->unwind_stack(); stack_alloc_.deallocate( stack_ctx_); impl_ = 0; @@ -1060,8 +1064,9 @@ public: ~pull_coroutine() { - if ( 0 != impl_) + if ( 0 != stack_ctx_.sp) { + BOOST_ASSERT( 0 != impl_); impl_->unwind_stack(); stack_alloc_.deallocate( stack_ctx_); impl_ = 0; @@ -1435,8 +1440,9 @@ public: ~pull_coroutine() { - if ( 0 != impl_) + if ( 0 != stack_ctx_.sp) { + BOOST_ASSERT( 0 != impl_); impl_->unwind_stack(); stack_alloc_.deallocate( stack_ctx_); impl_ = 0; diff --git a/include/boost/coroutine/detail/pull_coroutine_impl.hpp b/include/boost/coroutine/detail/pull_coroutine_impl.hpp index b30b33e..35700a6 100644 --- a/include/boost/coroutine/detail/pull_coroutine_impl.hpp +++ b/include/boost/coroutine/detail/pull_coroutine_impl.hpp @@ -42,11 +42,11 @@ private: typedef parameters< R > param_type; - int flags_; - exception_ptr except_; - coroutine_context caller_; - coroutine_context callee_; - R * result_; + int flags_; + exception_ptr except_; + coroutine_context * caller_; + coroutine_context * callee_; + R * result_; public: pull_coroutine_impl( coroutine_context * caller, @@ -54,8 +54,8 @@ public: bool unwind, bool preserve_fpu) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee), + caller_( caller), + callee_( callee), result_( 0) { if ( unwind) flags_ |= flag_force_unwind; @@ -68,8 +68,8 @@ public: R * result) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee), + caller_( caller), + callee_( callee), result_( result) { if ( unwind) flags_ |= flag_force_unwind; @@ -94,8 +94,8 @@ public: { flags_ |= flag_unwind_stack; param_type to( unwind_t::force_unwind); - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ); flags_ &= ~flag_unwind_stack; @@ -111,8 +111,8 @@ public: param_type to; param_type * from( reinterpret_cast< param_type * >( - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); result_ = from->data; @@ -151,11 +151,11 @@ private: typedef parameters< R & > param_type; - int flags_; - exception_ptr except_; - coroutine_context caller_; - coroutine_context callee_; - R * result_; + int flags_; + exception_ptr except_; + coroutine_context * caller_; + coroutine_context * callee_; + R * result_; public: pull_coroutine_impl( coroutine_context * caller, @@ -163,8 +163,8 @@ public: bool unwind, bool preserve_fpu) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee), + caller_( caller), + callee_( callee), result_( 0) { if ( unwind) flags_ |= flag_force_unwind; @@ -177,8 +177,8 @@ public: R * result) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee), + caller_( caller), + callee_( callee), result_( result) { if ( unwind) flags_ |= flag_force_unwind; @@ -203,8 +203,8 @@ public: { flags_ |= flag_unwind_stack; param_type to( unwind_t::force_unwind); - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ); flags_ &= ~flag_unwind_stack; @@ -220,8 +220,8 @@ public: param_type to; param_type * from( reinterpret_cast< param_type * >( - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); result_ = from->data; @@ -260,10 +260,10 @@ private: typedef parameters< void > param_type; - int flags_; - exception_ptr except_; - coroutine_context caller_; - coroutine_context callee_; + int flags_; + exception_ptr except_; + coroutine_context * caller_; + coroutine_context * callee_; public: pull_coroutine_impl( coroutine_context * caller, @@ -271,8 +271,8 @@ public: bool unwind, bool preserve_fpu) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee) + caller_( caller), + callee_( callee) { if ( unwind) flags_ |= flag_force_unwind; if ( preserve_fpu) flags_ |= flag_preserve_fpu; @@ -296,8 +296,8 @@ public: { flags_ |= flag_unwind_stack; param_type to( unwind_t::force_unwind); - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ); flags_ &= ~flag_unwind_stack; @@ -313,8 +313,8 @@ public: param_type to; param_type * from( reinterpret_cast< param_type * >( - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); if ( from->do_unwind) throw forced_unwind(); diff --git a/include/boost/coroutine/detail/push_coroutine_impl.hpp b/include/boost/coroutine/detail/push_coroutine_impl.hpp index 687b2db..a550d11 100644 --- a/include/boost/coroutine/detail/push_coroutine_impl.hpp +++ b/include/boost/coroutine/detail/push_coroutine_impl.hpp @@ -42,10 +42,10 @@ private: typedef parameters< Arg > param_type; - int flags_; - exception_ptr except_; - coroutine_context caller_; - coroutine_context callee_; + int flags_; + exception_ptr except_; + coroutine_context * caller_; + coroutine_context * callee_; public: push_coroutine_impl( coroutine_context * caller, @@ -53,8 +53,8 @@ public: bool unwind, bool preserve_fpu) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee) + caller_( caller), + callee_( callee) { if ( unwind) flags_ |= flag_force_unwind; if ( preserve_fpu) flags_ |= flag_preserve_fpu; @@ -78,8 +78,8 @@ public: { flags_ |= flag_unwind_stack; param_type to( unwind_t::force_unwind); - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ); flags_ &= ~flag_unwind_stack; @@ -95,8 +95,8 @@ public: param_type to( const_cast< Arg * >( & arg) ); param_type * from( reinterpret_cast< param_type * >( - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); if ( from->do_unwind) throw forced_unwind(); @@ -110,8 +110,8 @@ public: param_type to( const_cast< Arg * >( & arg) ); param_type * from( reinterpret_cast< param_type * >( - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); if ( from->do_unwind) throw forced_unwind(); @@ -130,10 +130,10 @@ private: typedef parameters< Arg & > param_type; - int flags_; - exception_ptr except_; - coroutine_context caller_; - coroutine_context callee_; + int flags_; + exception_ptr except_; + coroutine_context * caller_; + coroutine_context * callee_; public: push_coroutine_impl( coroutine_context * caller, @@ -141,8 +141,8 @@ public: bool unwind, bool preserve_fpu) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee) + caller_( caller), + callee_( callee) { if ( unwind) flags_ |= flag_force_unwind; if ( preserve_fpu) flags_ |= flag_preserve_fpu; @@ -166,8 +166,8 @@ public: { flags_ |= flag_unwind_stack; param_type to( unwind_t::force_unwind); - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ); flags_ &= ~flag_unwind_stack; @@ -183,8 +183,8 @@ public: param_type to( & arg); param_type * from( reinterpret_cast< param_type * >( - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); if ( from->do_unwind) throw forced_unwind(); @@ -203,10 +203,10 @@ private: typedef parameters< void > param_type; - int flags_; - exception_ptr except_; - coroutine_context caller_; - coroutine_context callee_; + int flags_; + exception_ptr except_; + coroutine_context * caller_; + coroutine_context * callee_; public: push_coroutine_impl( coroutine_context * caller, @@ -214,8 +214,8 @@ public: bool unwind, bool preserve_fpu) : flags_( 0), except_(), - caller_( * caller), - callee_( * callee) + caller_( caller), + callee_( callee) { if ( unwind) flags_ |= flag_force_unwind; if ( preserve_fpu) flags_ |= flag_preserve_fpu; @@ -239,8 +239,8 @@ public: { flags_ |= flag_unwind_stack; param_type to( unwind_t::force_unwind); - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ); flags_ &= ~flag_unwind_stack; @@ -256,8 +256,8 @@ public: param_type to; param_type * from( reinterpret_cast< param_type * >( - caller_.jump( - callee_, + caller_->jump( + * callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); if ( from->do_unwind) throw forced_unwind(); diff --git a/include/boost/coroutine/detail/symmetric_coroutine_call.hpp b/include/boost/coroutine/detail/symmetric_coroutine_call.hpp index 054a55e..1248dcb 100644 --- a/include/boost/coroutine/detail/symmetric_coroutine_call.hpp +++ b/include/boost/coroutine/detail/symmetric_coroutine_call.hpp @@ -115,7 +115,6 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); coroutine_context callee( - trampoline< coroutine_fn, impl_type, yield_type >, trampoline< Fn, impl_type, yield_type >, stack_ctx_); coroutine_context caller; diff --git a/include/boost/coroutine/detail/trampoline_pull.hpp b/include/boost/coroutine/detail/trampoline_pull.hpp index eb4e75b..c28430b 100644 --- a/include/boost/coroutine/detail/trampoline_pull.hpp +++ b/include/boost/coroutine/detail/trampoline_pull.hpp @@ -46,7 +46,11 @@ void trampoline_pull( intptr_t vp) #else Fn fn( move( from->fn) ); #endif - Coro c( from->caller, from->callee, + + coroutine_context caller( * from->caller); + coroutine_context callee( * from->callee); + + Coro c( & caller, & callee, stack_unwind == from->attr.do_unwind, fpu_preserved == from->attr.preserve_fpu); from = 0; @@ -54,14 +58,14 @@ void trampoline_pull( intptr_t vp) { param_type * from( reinterpret_cast< param_type * >( - c.callee_.jump( - c.caller_, + c.callee_->jump( + * c.caller_, reinterpret_cast< intptr_t >( & c), c.preserve_fpu() ) ) ); c.result_ = from->data; // create push_coroutine - typename Self::impl_type b( & c.callee_, & c.caller_, false, c.preserve_fpu() ); + typename Self::impl_type b( & callee, & caller, false, c.preserve_fpu() ); Self yield( & b); try { fn( yield); } @@ -73,8 +77,8 @@ void trampoline_pull( intptr_t vp) c.flags_ |= flag_complete; param_type to; - c.callee_.jump( - c.caller_, + c.callee_->jump( + * c.caller_, reinterpret_cast< intptr_t >( & to), c.preserve_fpu() ); BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); @@ -95,19 +99,23 @@ void trampoline_pull_void( intptr_t vp) #else Fn fn( move( from->fn) ); #endif - Coro c( from->caller, from->callee, + + coroutine_context caller( * from->caller); + coroutine_context callee( * from->callee); + + Coro c( & caller, & callee, stack_unwind == from->attr.do_unwind, fpu_preserved == from->attr.preserve_fpu); from = 0; { - c.callee_.jump( - c.caller_, + c.callee_->jump( + * c.caller_, reinterpret_cast< intptr_t >( & c), c.preserve_fpu() ); // create push_coroutine - typename Self::impl_type b( & c.callee_, & c.caller_, false, c.preserve_fpu() ); + typename Self::impl_type b( & callee, & caller, false, c.preserve_fpu() ); Self yield( & b); try { fn( yield); } @@ -119,8 +127,8 @@ void trampoline_pull_void( intptr_t vp) c.flags_ |= flag_complete; param_type to; - c.callee_.jump( - c.caller_, + c.callee_->jump( + * c.caller_, reinterpret_cast< intptr_t >( & to), c.preserve_fpu() ); BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); diff --git a/include/boost/coroutine/detail/trampoline_push.hpp b/include/boost/coroutine/detail/trampoline_push.hpp index c75811c..8229237 100644 --- a/include/boost/coroutine/detail/trampoline_push.hpp +++ b/include/boost/coroutine/detail/trampoline_push.hpp @@ -46,7 +46,11 @@ void trampoline_push( intptr_t vp) #else Fn fn( move( from->fn) ); #endif - Coro c( from->caller, from->callee, + + coroutine_context caller( * from->caller); + coroutine_context callee( * from->callee); + + Coro c( & caller, & callee, stack_unwind == from->attr.do_unwind, fpu_preserved == from->attr.preserve_fpu); from = 0; @@ -54,27 +58,30 @@ void trampoline_push( intptr_t vp) { param_type * from( reinterpret_cast< param_type * >( - c.callee_.jump( - c.caller_, + c.callee_->jump( + * c.caller_, reinterpret_cast< intptr_t >( & c), c.preserve_fpu() ) ) ); - BOOST_ASSERT( from->data); + if ( ! from->do_unwind) + { + BOOST_ASSERT( from->data); - // create push_coroutine - typename Self::impl_type b( & c.callee_, & c.caller_, false, c.preserve_fpu(), from->data); - Self yield( & b); - try - { fn( yield); } - catch ( forced_unwind const&) - {} - catch (...) - { c.except_ = current_exception(); } + // create push_coroutine + typename Self::impl_type b( & callee, & caller, false, c.preserve_fpu(), from->data); + Self yield( & b); + try + { fn( yield); } + catch ( forced_unwind const&) + {} + catch (...) + { c.except_ = current_exception(); } + } } c.flags_ |= flag_complete; param_type to; - c.callee_.jump( - c.caller_, + c.callee_->jump( + * c.caller_, reinterpret_cast< intptr_t >( & to), c.preserve_fpu() ); BOOST_ASSERT_MSG( false, "push_coroutine is complete"); @@ -95,32 +102,40 @@ void trampoline_push_void( intptr_t vp) #else Fn fn( move( from->fn) ); #endif - Coro c( from->caller, from->callee, + + coroutine_context caller( * from->caller); + coroutine_context callee( * from->callee); + + Coro c( & caller, & callee, stack_unwind == from->attr.do_unwind, fpu_preserved == from->attr.preserve_fpu); from = 0; { - c.callee_.jump( - c.caller_, - reinterpret_cast< intptr_t >( & c), - c.preserve_fpu() ); - - // create push_coroutine - typename Self::impl_type b( & c.callee_, & c.caller_, false, c.preserve_fpu() ); - Self yield( & b); - try - { fn( yield); } - catch ( forced_unwind const&) - {} - catch (...) - { c.except_ = current_exception(); } + 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 push_coroutine + typename Self::impl_type b( & callee, & caller, false, c.preserve_fpu() ); + Self yield( & b); + try + { fn( yield); } + catch ( forced_unwind const&) + {} + catch (...) + { c.except_ = current_exception(); } + } } c.flags_ |= flag_complete; param_type to; - c.callee_.jump( - c.caller_, + c.callee_->jump( + * c.caller_, reinterpret_cast< intptr_t >( & to), c.preserve_fpu() ); BOOST_ASSERT_MSG( false, "push_coroutine is complete");