diff --git a/doc/performance.qbk b/doc/performance.qbk index 11cd0a1..2428196 100644 --- a/doc/performance.qbk +++ b/doc/performance.qbk @@ -24,14 +24,14 @@ build options, 'variant = release cxxflags = -DBOOST_DISABLE_ASSERTS'. ] [ [i386 [footnote AMD Athlon 64 DualCore 4400+]] - [62 ns / 77 cycles] + [78 ns / 77 cycles] [188868 ns / 245093 cycles] [31860 ns / 31812 cycles] [13127 ns / 19764 cycles] ] [ [x86_64 [footnote Intel Core2 Q6700]] - [17 ns / 47 cycles] + [28 ns / 74 cycles] [46916 ns / 109569 cycles] [14368 ns / 22705 cycles] [6114 ns / 16728 cycles] diff --git a/include/boost/coroutine/coroutine.hpp b/include/boost/coroutine/coroutine.hpp index 4eca6a4..2419db8 100644 --- a/include/boost/coroutine/coroutine.hpp +++ b/include/boost/coroutine/coroutine.hpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -596,7 +595,7 @@ private: pull_coroutine( detail::coroutine_context const& callee, bool unwind, bool preserve_fpu, Allocator const& alloc, - optional< R > const& result) : + R * result) : impl_() { typedef detail::pull_coroutine_caller< @@ -870,7 +869,7 @@ public: { private: pull_coroutine< R > * c_; - optional< R > val_; + R * val_; void fetch_() { @@ -879,7 +878,7 @@ public: if ( ! c_->has_result() ) { c_ = 0; - val_ = none; + val_ = 0; return; } val_ = c_->get(); @@ -899,11 +898,11 @@ public: typedef typename iterator::reference reference_t; iterator() : - c_( 0), val_() + c_( 0), val_( 0) {} explicit iterator( pull_coroutine< R > * c) : - c_( c), val_() + c_( c), val_( 0) { fetch_(); } iterator( iterator const& other) : @@ -942,7 +941,7 @@ public: if ( ! val_) boost::throw_exception( invalid_result() ); - return const_cast< optional< R > & >( val_).get(); + return * val_; } pointer_t operator->() const @@ -950,7 +949,387 @@ public: if ( ! val_) boost::throw_exception( invalid_result() ); - return const_cast< optional< R > & >( val_).get_ptr(); + return val_; + } + }; + + struct const_iterator; +}; + +template< typename R > +class pull_coroutine< R * > +{ +private: + template< + typename X, typename Y, typename Z, typename V, typename W + > + friend class detail::push_coroutine_object; + + typedef detail::pull_coroutine_base< R * > base_t; + typedef typename base_t::ptr_t ptr_t; + + struct dummy + { void nonnull() {} }; + + ptr_t impl_; + + BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) + + template< typename Allocator > + pull_coroutine( detail::coroutine_context const& callee, + bool unwind, bool preserve_fpu, + Allocator const& alloc, + R ** result) : + impl_() + { + typedef detail::pull_coroutine_caller< + R *, Allocator + > caller_t; + typename caller_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) caller_t( + callee, unwind, preserve_fpu, a, result) ); + } + +public: + pull_coroutine() BOOST_NOEXCEPT : + impl_() + {} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +# ifdef BOOST_MSVC + typedef void ( * coroutine_fn)( push_coroutine< R * > &); + + explicit pull_coroutine( coroutine_fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = stack_allocator(), + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >() ) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, coroutine_fn, stack_allocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } + + template< typename StackAllocator > + explicit pull_coroutine( coroutine_fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >() ) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, coroutine_fn, StackAllocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } + + template< typename StackAllocator, typename Allocator > + explicit pull_coroutine( coroutine_fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, coroutine_fn, StackAllocator, Allocator, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } +# endif + template< typename Fn > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = stack_allocator(), + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >() ) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, stack_allocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >() ) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, StackAllocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, StackAllocator, Allocator, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } +#else + template< typename Fn > + explicit pull_coroutine( Fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = stack_allocator(), + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >(), + typename disable_if< is_convertible< Fn &, BOOST_RV_REF(Fn) >, dummy* >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, stack_allocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit pull_coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >(), + typename disable_if< is_convertible< Fn &, BOOST_RV_REF(Fn) >, dummy* >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, StackAllocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit pull_coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< is_convertible< Fn &, BOOST_RV_REF(Fn) >, dummy* >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, StackAllocator, Allocator, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = stack_allocator(), + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, dummy* + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, stack_allocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< pull_coroutine > const& alloc = std::allocator< pull_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, dummy* + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, StackAllocator, std::allocator< pull_coroutine >, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, dummy* + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R *, Fn, StackAllocator, Allocator, + push_coroutine< R * > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } +#endif + + pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT : + impl_() + { swap( other); } + + pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT + { + pull_coroutine tmp( boost::move( other) ); + swap( tmp); + return * this; + } + + bool empty() const BOOST_NOEXCEPT + { return ! impl_; } + + BOOST_EXPLICIT_OPERATOR_BOOL(); + + bool operator!() const BOOST_NOEXCEPT + { return empty() || impl_->is_complete(); } + + void swap( pull_coroutine & other) BOOST_NOEXCEPT + { impl_.swap( other.impl_); } + + pull_coroutine & operator()() + { + BOOST_ASSERT( * this); + + impl_->pull(); + return * this; + } + + bool has_result() const + { + BOOST_ASSERT( ! empty() ); + + return impl_->has_result(); + } + + R * get() const + { return impl_->get(); } + + class iterator : public std::iterator< std::input_iterator_tag, R > + { + private: + pull_coroutine< R * > * c_; + R ** val_; + + void fetch_() + { + BOOST_ASSERT( c_); + + if ( ! c_->has_result() ) + { + c_ = 0; + val_ = 0; + return; + } + val_ = c_->get(); + } + + void increment_() + { + BOOST_ASSERT( c_); + BOOST_ASSERT( * c_); + + ( * c_)(); + fetch_(); + } + + public: + typedef typename iterator::pointer pointer_t; + typedef typename iterator::reference reference_t; + + iterator() : + c_( 0), val_( 0) + {} + + explicit iterator( pull_coroutine< R * > * c) : + c_( c), val_( 0) + { fetch_(); } + + iterator( iterator const& other) : + c_( other.c_), val_( other.val_) + {} + + iterator & operator=( iterator const& other) + { + if ( this == & other) return * this; + c_ = other.c_; + val_ = other.val_; + return * this; + } + + bool operator==( iterator const& other) + { return other.c_ == c_ && other.val_ == val_; } + + bool operator!=( iterator const& other) + { return other.c_ != c_ || other.val_ != val_; } + + iterator & operator++() + { + increment_(); + return * this; + } + + iterator operator++( int) + { + iterator tmp( * this); + ++*this; + return tmp; + } + + reference_t operator*() const + { + if ( ! val_) + boost::throw_exception( + invalid_result() ); + return * val_; + } + + pointer_t operator->() const + { + if ( ! val_) + boost::throw_exception( + invalid_result() ); + return val_; } }; @@ -980,7 +1359,7 @@ private: pull_coroutine( detail::coroutine_context const& callee, bool unwind, bool preserve_fpu, Allocator const& alloc, - optional< R * > const& result) : + R * result) : impl_() { typedef detail::pull_coroutine_caller< @@ -1249,8 +1628,8 @@ public: class iterator : public std::iterator< std::input_iterator_tag, R > { private: - pull_coroutine< R & > * c_; - optional< R & > val_; + pull_coroutine< R & > * c_; + R * val_; void fetch_() { @@ -1259,7 +1638,7 @@ public: if ( ! c_->has_result() ) { c_ = 0; - val_ = none; + val_ = 0; return; } val_ = c_->get(); @@ -1279,11 +1658,11 @@ public: typedef typename iterator::reference reference_t; iterator() : - c_( 0), val_() + c_( 0), val_( 0) {} explicit iterator( pull_coroutine< R & > * c) : - c_( c), val_() + c_( c), val_( 0) { fetch_(); } iterator( iterator const& other) : @@ -1322,7 +1701,7 @@ public: if ( ! val_) boost::throw_exception( invalid_result() ); - return const_cast< optional< R & > & >( val_).get(); + return * val_; } pointer_t operator->() const @@ -1330,7 +1709,7 @@ public: if ( ! val_) boost::throw_exception( invalid_result() ); - return const_cast< optional< R & > & >( val_).get_ptr(); + return val_; } }; diff --git a/include/boost/coroutine/detail/flags.hpp b/include/boost/coroutine/detail/flags.hpp index 33f2142..21ed18e 100644 --- a/include/boost/coroutine/detail/flags.hpp +++ b/include/boost/coroutine/detail/flags.hpp @@ -25,6 +25,12 @@ enum flag_t flag_preserve_fpu = 1 << 4 }; +struct unwind_t +{ + enum flag_t + { force_unwind = 1 }; +}; + }}} #ifdef BOOST_HAS_ABI_HEADERS diff --git a/include/boost/coroutine/detail/parameters.hpp b/include/boost/coroutine/detail/parameters.hpp index b615519..34c4562 100644 --- a/include/boost/coroutine/detail/parameters.hpp +++ b/include/boost/coroutine/detail/parameters.hpp @@ -11,6 +11,7 @@ #include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -24,27 +25,27 @@ template< typename Data > struct parameters { coroutine_context * ctx; - Data const* data; - bool force_unwind; + Data * data; + bool do_unwind; explicit parameters( coroutine_context * ctx_) : - ctx( ctx_), data( 0), force_unwind( false) + ctx( ctx_), data( 0), do_unwind( false) { BOOST_ASSERT( ctx); } - explicit parameters( coroutine_context * ctx_, Data const* data_) : - ctx( ctx_), data( data_), force_unwind( false) + explicit parameters( coroutine_context * ctx_, Data * data_) : + ctx( ctx_), data( data_), do_unwind( false) { BOOST_ASSERT( ctx); } - explicit parameters( coroutine_context * ctx_, bool force_unwind_) : - ctx( ctx_), data( 0), force_unwind( force_unwind_) + explicit parameters( coroutine_context * ctx_, unwind_t::flag_t) : + ctx( ctx_), data( 0), do_unwind( true) { BOOST_ASSERT( ctx); - BOOST_ASSERT( force_unwind); + BOOST_ASSERT( do_unwind); } parameters( parameters const& other) : ctx( other.ctx), data( other.data), - force_unwind( other.force_unwind) + do_unwind( other.do_unwind) {} parameters & operator=( parameters const& other) @@ -52,7 +53,7 @@ struct parameters if ( this == & other) return * this; ctx = other.ctx; data = other.data; - force_unwind = other.force_unwind; + do_unwind = other.do_unwind; return * this; } }; @@ -61,27 +62,27 @@ template< typename Data > struct parameters< Data & > { coroutine_context * ctx; - Data const* data; - bool force_unwind; + Data * data; + bool do_unwind; explicit parameters( coroutine_context * ctx_) : - ctx( ctx_), data( 0), force_unwind( false) + ctx( ctx_), data( 0), do_unwind( false) { BOOST_ASSERT( ctx); } - explicit parameters( coroutine_context * ctx_, Data const* data_) : - ctx( ctx_), data( data_), force_unwind( false) + explicit parameters( coroutine_context * ctx_, Data * data_) : + ctx( ctx_), data( data_), do_unwind( false) { BOOST_ASSERT( ctx); } - explicit parameters( coroutine_context * ctx_, bool force_unwind_) : - ctx( ctx_), data( 0), force_unwind( force_unwind_) + explicit parameters( coroutine_context * ctx_, unwind_t::flag_t) : + ctx( ctx_), data( 0), do_unwind( true) { BOOST_ASSERT( ctx); - BOOST_ASSERT( force_unwind); + BOOST_ASSERT( do_unwind); } parameters( parameters const& other) : ctx( other.ctx), data( other.data), - force_unwind( other.force_unwind) + do_unwind( other.do_unwind) {} parameters & operator=( parameters const& other) @@ -89,7 +90,7 @@ struct parameters< Data & > if ( this == & other) return * this; ctx = other.ctx; data = other.data; - force_unwind = other.force_unwind; + do_unwind = other.do_unwind; return * this; } }; @@ -98,27 +99,27 @@ template< typename Data > struct parameters< Data * > { coroutine_context * ctx; - Data const* data; - bool force_unwind; + Data ** data; + bool do_unwind; explicit parameters( coroutine_context * ctx_) : - ctx( ctx_), data( 0), force_unwind( false) + ctx( ctx_), data( 0), do_unwind( false) { BOOST_ASSERT( ctx); } - explicit parameters( coroutine_context * ctx_, Data const* data_) : - ctx( ctx_), data( data_), force_unwind( false) + explicit parameters( coroutine_context * ctx_, Data ** data_) : + ctx( ctx_), data( data_), do_unwind( false) { BOOST_ASSERT( ctx); } - explicit parameters( coroutine_context * ctx_, bool force_unwind_) : - ctx( ctx_), data( 0), force_unwind( force_unwind_) + explicit parameters( coroutine_context * ctx_, unwind_t::flag_t) : + ctx( ctx_), data( 0), do_unwind( true) { BOOST_ASSERT( ctx); - BOOST_ASSERT( force_unwind); + BOOST_ASSERT( do_unwind); } parameters( parameters const& other) : ctx( other.ctx), data( other.data), - force_unwind( other.force_unwind) + do_unwind( other.do_unwind) {} parameters & operator=( parameters const& other) @@ -126,7 +127,7 @@ struct parameters< Data * > if ( this == & other) return * this; ctx = other.ctx; data = other.data; - force_unwind = other.force_unwind; + do_unwind = other.do_unwind; return * this; } }; @@ -134,22 +135,26 @@ struct parameters< Data * > template<> struct parameters< void > { - coroutine_context * ctx; - bool force_unwind; + coroutine_context * ctx; + bool do_unwind; - explicit parameters( coroutine_context * ctx_, bool force_unwind_ = false) : - ctx( ctx_), force_unwind( force_unwind_) + explicit parameters( coroutine_context * ctx_) : + ctx( ctx_), do_unwind( false) + { BOOST_ASSERT( ctx); } + + explicit parameters( coroutine_context * ctx_, unwind_t::flag_t) : + ctx( ctx_), do_unwind( true) { BOOST_ASSERT( ctx); } parameters( parameters const& other) : - ctx( other.ctx), force_unwind( other.force_unwind) + ctx( other.ctx), do_unwind( other.do_unwind) {} parameters & operator=( parameters const& other) { if ( this == & other) return * this; ctx = other.ctx; - force_unwind = other.force_unwind; + do_unwind = other.do_unwind; return * this; } }; diff --git a/include/boost/coroutine/detail/pull_coroutine_base.hpp b/include/boost/coroutine/detail/pull_coroutine_base.hpp index 7595c63..f391f4c 100644 --- a/include/boost/coroutine/detail/pull_coroutine_base.hpp +++ b/include/boost/coroutine/detail/pull_coroutine_base.hpp @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include #include @@ -47,6 +45,8 @@ private: > friend class push_coroutine_object; + typedef parameters< R > param_type; + unsigned int use_count_; protected: @@ -54,7 +54,7 @@ protected: exception_ptr except_; coroutine_context caller_; coroutine_context callee_; - optional< R > result_; + R * result_; virtual void deallocate_object() = 0; @@ -67,7 +67,7 @@ public: except_(), caller_(), callee_( fn, stack_ctx), - result_() + result_( 0) { if ( unwind) flags_ |= flag_force_unwind; if ( preserve_fpu) flags_ |= flag_preserve_fpu; @@ -75,7 +75,7 @@ public: pull_coroutine_base( coroutine_context const& callee, bool unwind, bool preserve_fpu, - optional< R > const& result) : + R * result) : use_count_( 0), flags_( 0), except_(), @@ -102,48 +102,47 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void pull() { BOOST_ASSERT( ! is_complete() ); - parameters< R > to( & caller_); - parameters< R > * from( - reinterpret_cast< parameters< R > * >( + param_type to( & caller_); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->data) result_ = * from->data; - else result_ = none; - if ( from->force_unwind) throw forced_unwind(); + result_ = from->data; + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } bool has_result() const - { return result_; } + { return 0 != result_; } R get() const { if ( ! has_result() ) boost::throw_exception( invalid_result() ); - return result_.get(); + return * result_; } + + friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; template< typename R > class pull_coroutine_base< R * > : private noncopyable { public: - typedef intrusive_ptr< pull_coroutine_base > ptr_t; + typedef intrusive_ptr< pull_coroutine_base > ptr_t; private: template< @@ -151,6 +150,8 @@ private: > friend class push_coroutine_object; + typedef parameters< R * > param_type; + unsigned int use_count_; protected: @@ -158,7 +159,7 @@ protected: exception_ptr except_; coroutine_context caller_; coroutine_context callee_; - optional< R * > result_; + R ** result_; virtual void deallocate_object() = 0; @@ -171,7 +172,7 @@ public: except_(), caller_(), callee_( fn, stack_ctx), - result_() + result_( 0) { if ( unwind) flags_ |= flag_force_unwind; if ( preserve_fpu) flags_ |= flag_preserve_fpu; @@ -179,7 +180,7 @@ public: pull_coroutine_base( coroutine_context const& callee, bool unwind, bool preserve_fpu, - optional< R * > const& result) : + R ** result) : use_count_( 0), flags_( 0), except_(), @@ -206,48 +207,47 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void pull() { BOOST_ASSERT( ! is_complete() ); - parameters< R * > to( & caller_); - parameters< R * > * from( - reinterpret_cast< parameters< R * > * >( + param_type to( & caller_); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->data) result_ = const_cast< R * >( from->data); - else this->result_ = none; - if ( from->force_unwind) throw forced_unwind(); + result_ = from->data; + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } bool has_result() const - { return result_; } + { return 0 != result_; } R * get() const { if ( ! has_result() ) boost::throw_exception( invalid_result() ); - return result_.get(); + return * result_; } + + friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; template< typename R > class pull_coroutine_base< R & > : private noncopyable { public: - typedef intrusive_ptr< pull_coroutine_base > ptr_t; + typedef intrusive_ptr< pull_coroutine_base > ptr_t; private: template< @@ -255,6 +255,8 @@ private: > friend class push_coroutine_object; + typedef parameters< R & > param_type; + unsigned int use_count_; protected: @@ -262,7 +264,7 @@ protected: exception_ptr except_; coroutine_context caller_; coroutine_context callee_; - optional< R * > result_; + R * result_; virtual void deallocate_object() = 0; @@ -275,7 +277,7 @@ public: except_(), caller_(), callee_( fn, stack_ctx), - result_() + result_( 0) { if ( unwind) flags_ |= flag_force_unwind; if ( preserve_fpu) flags_ |= flag_preserve_fpu; @@ -283,7 +285,7 @@ public: pull_coroutine_base( coroutine_context const& callee, bool unwind, bool preserve_fpu, - optional< R * > const& result) : + R * result) : use_count_( 0), flags_( 0), except_(), @@ -310,48 +312,47 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void pull() { BOOST_ASSERT( ! is_complete() ); - parameters< R & > to( & caller_); - parameters< R & > * from( - reinterpret_cast< parameters< R & > * >( + param_type to( & caller_); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->data) result_ = const_cast< R * >( from->data); - else this->result_ = none; - if ( from->force_unwind) throw forced_unwind(); + result_ = from->data; + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } bool has_result() const - { return result_; } + { return 0 != result_; } R & get() const { if ( ! has_result() ) boost::throw_exception( invalid_result() ); - return * result_.get(); + return * result_; } + + friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; template<> class pull_coroutine_base< void > : private noncopyable { public: - typedef intrusive_ptr< pull_coroutine_base > ptr_t; + typedef intrusive_ptr< pull_coroutine_base > ptr_t; private: template< @@ -359,6 +360,8 @@ private: > friend class push_coroutine_object; + typedef parameters< void > param_type; + unsigned int use_count_; protected: @@ -410,28 +413,28 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void pull() { BOOST_ASSERT( ! is_complete() ); - parameters< void > to( & caller_); - parameters< void > * from( - reinterpret_cast< parameters< void > * >( + param_type to( & caller_); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->force_unwind) throw forced_unwind(); + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } + + friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; }}} diff --git a/include/boost/coroutine/detail/pull_coroutine_caller.hpp b/include/boost/coroutine/detail/pull_coroutine_caller.hpp index 8c66215..d2da8c6 100644 --- a/include/boost/coroutine/detail/pull_coroutine_caller.hpp +++ b/include/boost/coroutine/detail/pull_coroutine_caller.hpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -30,7 +29,7 @@ public: >::other allocator_t; pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu, - allocator_t const& alloc, optional< R > const& data) BOOST_NOEXCEPT : + allocator_t const& alloc, R * data) BOOST_NOEXCEPT : pull_coroutine_base< R >( callee, unwind, preserve_fpu, data), alloc_( alloc) {} @@ -48,6 +47,33 @@ private: } }; +template< typename R, typename Allocator > +class pull_coroutine_caller< R *, Allocator > : public pull_coroutine_base< R * > +{ +public: + typedef typename Allocator::template rebind< + pull_coroutine_caller< R *, Allocator > + >::other allocator_t; + + pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu, + allocator_t const& alloc, R ** data) BOOST_NOEXCEPT : + pull_coroutine_base< R * >( callee, unwind, preserve_fpu, data), + alloc_( alloc) + {} + + void deallocate_object() + { destroy_( alloc_, this); } + +private: + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, pull_coroutine_caller * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } +}; + template< typename R, typename Allocator > class pull_coroutine_caller< R &, Allocator > : public pull_coroutine_base< R & > { @@ -57,7 +83,7 @@ public: >::other allocator_t; pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu, - allocator_t const& alloc, optional< R * > const& data) BOOST_NOEXCEPT : + allocator_t const& alloc, R * data) BOOST_NOEXCEPT : pull_coroutine_base< R & >( callee, unwind, preserve_fpu, data), alloc_( alloc) {} diff --git a/include/boost/coroutine/detail/pull_coroutine_object.hpp b/include/boost/coroutine/detail/pull_coroutine_object.hpp index 1d1ba37..b377610 100644 --- a/include/boost/coroutine/detail/pull_coroutine_object.hpp +++ b/include/boost/coroutine/detail/pull_coroutine_object.hpp @@ -14,10 +14,6 @@ #include #include #include -#include -#include -#include -#include #include #include @@ -62,6 +58,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef pull_coroutine_base< R > base_type; + typedef parameters< R > param_type; Fn fn_; allocator_t alloc_; @@ -77,15 +74,14 @@ private: void enter_() { - parameters< R > * from( - reinterpret_cast< parameters< R > * >( + param_type * from( + reinterpret_cast< param_type * >( this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( this), this->preserve_fpu() ) ) ); this->callee_ = * from->ctx; - if ( from->data) this->result_ = * from->data; - else this->result_ = none; + this->result_ = from->data; if ( this->except_) rethrow_exception( this->except_); } @@ -94,7 +90,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< R > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -160,225 +156,7 @@ public: } this->flags_ |= flag_complete; - parameters< R > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename R, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< R, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< R > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - R, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< R > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< R > * from( - reinterpret_cast< parameters< R > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< R > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< R > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename R, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< R, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< R > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - R, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< R > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< R > * from( - reinterpret_cast< parameters< R > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< R > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< R > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to), @@ -409,6 +187,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef pull_coroutine_base< R * > base_type; + typedef parameters< R * > param_type; Fn fn_; allocator_t alloc_; @@ -424,15 +203,14 @@ private: void enter_() { - parameters< R * > * from( - reinterpret_cast< parameters< R * > * >( + param_type * from( + reinterpret_cast< param_type * >( this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( this), this->preserve_fpu() ) ) ); this->callee_ = * from->ctx; - if ( from->data) this->result_ = const_cast< R * >( from->data); - else this->result_ = none; + this->result_ = from->data; if ( this->except_) rethrow_exception( this->except_); } @@ -441,7 +219,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< R * > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -517,225 +295,7 @@ public: } this->flags_ |= flag_complete; - parameters< R * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename R, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< R *, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< R * > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - R *, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< R * > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< R * > * from( - reinterpret_cast< parameters< R * > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< R * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< R * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename R, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< R *, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< R * > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - R *, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< R * > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< R * > * from( - reinterpret_cast< parameters< R * > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< R * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< R * > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to), @@ -766,6 +326,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef pull_coroutine_base< R & > base_type; + typedef parameters< R & > param_type; Fn fn_; allocator_t alloc_; @@ -781,15 +342,14 @@ private: void enter_() { - parameters< R * > * from( - reinterpret_cast< parameters< R * > * >( + param_type * from( + reinterpret_cast< param_type * >( this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( this), this->preserve_fpu() ) ) ); this->callee_ = * from->ctx; - if ( from->data) this->result_ = from->data; - else this->result_ = none; + this->result_ = from->data; if ( this->except_) rethrow_exception( this->except_); } @@ -798,7 +358,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< R * > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -874,225 +434,7 @@ public: } this->flags_ |= flag_complete; - parameters< R * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename R, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< R &, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< R & > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - R &, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< R & > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< R * > * from( - reinterpret_cast< parameters< R * > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< R * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< R * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename R, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< R &, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< R & > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - R &, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< R & > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< R * > * from( - reinterpret_cast< parameters< R * > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< R * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< R * > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to), @@ -1123,6 +465,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef pull_coroutine_base< void > base_type; + typedef parameters< void > param_type; Fn fn_; allocator_t alloc_; @@ -1138,8 +481,8 @@ private: void enter_() { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( + param_type * from( + reinterpret_cast< param_type * >( this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( this), @@ -1153,7 +496,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< void > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -1229,226 +572,7 @@ public: } this->flags_ |= flag_complete; - parameters< void > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< void, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< void > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - void, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< void > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< void > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< void > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class pull_coroutine_object< void, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public pull_coroutine_base< void > -{ -public: - typedef typename Allocator::template rebind< - pull_coroutine_object< - void, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef pull_coroutine_base< void > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, pull_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< void > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - pull_coroutine_object( const reference_wrapper< Fn > fn, - attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< pull_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~pull_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - // create pull_coroutine - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< void > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to), diff --git a/include/boost/coroutine/detail/push_coroutine_base.hpp b/include/boost/coroutine/detail/push_coroutine_base.hpp index e72ff8d..bebf294 100644 --- a/include/boost/coroutine/detail/push_coroutine_base.hpp +++ b/include/boost/coroutine/detail/push_coroutine_base.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -35,7 +34,7 @@ template< typename Arg > class push_coroutine_base : private noncopyable { public: - typedef intrusive_ptr< push_coroutine_base > ptr_t; + typedef intrusive_ptr< push_coroutine_base > ptr_t; private: template< @@ -43,6 +42,8 @@ private: > friend class pull_coroutine_object; + typedef parameters< Arg > param_type; + unsigned int use_count_; protected: @@ -94,26 +95,20 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void push( Arg const& arg) { BOOST_ASSERT( ! is_complete() ); - parameters< Arg > to( & caller_, & arg); - parameters< Arg > * from( - reinterpret_cast< parameters< Arg > * >( + param_type to( & caller_, const_cast< Arg * >( & arg) ); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->force_unwind) throw forced_unwind(); + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } @@ -121,25 +116,31 @@ public: { BOOST_ASSERT( ! is_complete() ); - parameters< Arg > to( & caller_, & arg); - parameters< Arg > * from( - reinterpret_cast< parameters< Arg > * >( + param_type to( & caller_, const_cast< Arg * >( & arg) ); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->force_unwind) throw forced_unwind(); + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } + + friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; template< typename Arg > class push_coroutine_base< Arg * > : private noncopyable { public: - typedef intrusive_ptr< push_coroutine_base > ptr_t; + typedef intrusive_ptr< push_coroutine_base > ptr_t; private: template< @@ -147,6 +148,8 @@ private: > friend class pull_coroutine_object; + typedef parameters< Arg * > param_type; + unsigned int use_count_; protected: @@ -198,35 +201,35 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void push( Arg * arg) { BOOST_ASSERT( ! is_complete() ); - parameters< Arg * > to( & caller_, arg); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( + param_type to( & caller_, & arg); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->force_unwind) throw forced_unwind(); + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } + + friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; template< typename Arg > class push_coroutine_base< Arg & > : private noncopyable { public: - typedef intrusive_ptr< push_coroutine_base > ptr_t; + typedef intrusive_ptr< push_coroutine_base > ptr_t; private: template< @@ -234,6 +237,8 @@ private: > friend class pull_coroutine_object; + typedef parameters< Arg & > param_type; + unsigned int use_count_; protected: @@ -285,35 +290,35 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void push( Arg & arg) { BOOST_ASSERT( ! is_complete() ); - parameters< Arg * > to( & caller_, & arg); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( + param_type to( & caller_, & arg); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->force_unwind) throw forced_unwind(); + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } + + friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; template<> class push_coroutine_base< void > : private noncopyable { public: - typedef intrusive_ptr< push_coroutine_base > ptr_t; + typedef intrusive_ptr< push_coroutine_base > ptr_t; private: template< @@ -321,6 +326,8 @@ private: > friend class pull_coroutine_object; + typedef parameters< void > param_type; + unsigned int use_count_; protected: @@ -372,28 +379,28 @@ public: bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } - friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT - { ++p->use_count_; } - - friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT - { if ( --p->use_count_ == 0) p->deallocate_object(); } - void push() { BOOST_ASSERT( ! is_complete() ); - parameters< void > to( & caller_); - parameters< void > * from( - reinterpret_cast< parameters< void > * >( + param_type to( & caller_); + param_type * from( + reinterpret_cast< param_type * >( to.ctx->jump( callee_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); BOOST_ASSERT( from->ctx); callee_ = * from->ctx; - if ( from->force_unwind) throw forced_unwind(); + if ( from->do_unwind) throw forced_unwind(); if ( except_) rethrow_exception( except_); } + + friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT + { ++p->use_count_; } + + friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; }}} diff --git a/include/boost/coroutine/detail/push_coroutine_object.hpp b/include/boost/coroutine/detail/push_coroutine_object.hpp index d0829df..37f1166 100644 --- a/include/boost/coroutine/detail/push_coroutine_object.hpp +++ b/include/boost/coroutine/detail/push_coroutine_object.hpp @@ -14,9 +14,6 @@ #include #include #include -#include -#include -#include #include #include @@ -62,6 +59,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef push_coroutine_base< Arg > base_type; + typedef parameters< Arg > param_type; Fn fn_; allocator_t alloc_; @@ -92,7 +90,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< Arg > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -147,8 +145,8 @@ public: { parameters< void > to( & caller); - parameters< Arg > * from( - reinterpret_cast< parameters< Arg > * >( + param_type * from( + reinterpret_cast< param_type * >( caller.jump( this->caller_, reinterpret_cast< intptr_t >( & to), @@ -157,7 +155,7 @@ public: BOOST_ASSERT( from->data); // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, * from->data); + Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, from->data); try { fn_( c); } catch ( forced_unwind const&) @@ -168,245 +166,7 @@ public: } this->flags_ |= flag_complete; - parameters< Arg > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Arg, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< Arg, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< Arg > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - Arg, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< Arg > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< Arg > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< Arg > * from( - reinterpret_cast< parameters< Arg > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - BOOST_ASSERT( from->data); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, * from->data); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< Arg > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Arg, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< Arg, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< Arg > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - Arg, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< Arg > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< Arg > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< Arg > * from( - reinterpret_cast< parameters< Arg > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - BOOST_ASSERT( from->data); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, * from->data); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< Arg > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to), @@ -437,6 +197,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef push_coroutine_base< Arg * > base_type; + typedef parameters< Arg * > param_type; Fn fn_; allocator_t alloc_; @@ -467,7 +228,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< Arg * > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -532,8 +293,8 @@ public: { parameters< void > to( & caller); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( + param_type * from( + reinterpret_cast< param_type * >( caller.jump( this->caller_, reinterpret_cast< intptr_t >( & to), @@ -542,7 +303,7 @@ public: BOOST_ASSERT( from->data); // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, const_cast< Arg * >( from->data) ); + Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, from->data); try { fn_( c); } catch ( forced_unwind const&) @@ -553,245 +314,7 @@ public: } this->flags_ |= flag_complete; - parameters< Arg * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Arg, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< Arg *, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< Arg * > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - Arg *, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< Arg * > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< Arg * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - BOOST_ASSERT( from->data); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, const_cast< Arg * >( from->data) ); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< Arg * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Arg, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< Arg *, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< Arg * > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - Arg, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< Arg * > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< Arg * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - BOOST_ASSERT( from->data); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, const_cast< Arg * >( from->data) ); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< Arg * > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to), @@ -822,6 +345,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef push_coroutine_base< Arg & > base_type; + typedef parameters< Arg & > param_type; Fn fn_; allocator_t alloc_; @@ -852,7 +376,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< Arg * > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -917,127 +441,8 @@ public: { parameters< void > to( & caller); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - BOOST_ASSERT( from->data); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, const_cast< Arg * >( from->data) ); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< Arg * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Arg, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< Arg &, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< Arg & > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - Arg &, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< Arg & > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< Arg * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( + param_type * from( + reinterpret_cast< param_type * >( caller.jump( this->caller_, reinterpret_cast< intptr_t >( & to), @@ -1057,126 +462,7 @@ public: } this->flags_ |= flag_complete; - parameters< Arg * > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Arg, typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< Arg &, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< Arg & > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - Arg, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< Arg & > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< Arg * > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< Arg * > * from( - reinterpret_cast< parameters< Arg * > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - BOOST_ASSERT( from->data); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_, from->data); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< Arg * > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to), @@ -1207,6 +493,7 @@ public: private: typedef stack_tuple< StackAllocator > pbase_type; typedef push_coroutine_base< void > base_type; + typedef parameters< void > param_type; Fn fn_; allocator_t alloc_; @@ -1237,7 +524,7 @@ private: BOOST_ASSERT( ! this->is_complete() ); this->flags_ |= flag_unwind_stack; - parameters< void > to( & this->caller_, true); + param_type to( & this->caller_, unwind_t::force_unwind); this->caller_.jump( this->callee_, reinterpret_cast< intptr_t >( & to), @@ -1302,8 +589,8 @@ public: { parameters< void > to( & caller); - parameters< void > * from( - reinterpret_cast< parameters< void > * >( + param_type * from( + reinterpret_cast< param_type * >( caller.jump( this->caller_, reinterpret_cast< intptr_t >( & to), @@ -1322,243 +609,7 @@ public: } this->flags_ |= flag_complete; - parameters< void > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< void, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< void > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - void, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< void > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< void > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< void > to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } - - void deallocate_object() - { destroy_( alloc_, this); } -}; - -template< - typename Fn, - typename StackAllocator, typename Allocator, - typename Caller -> -class push_coroutine_object< void, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > : - private stack_tuple< StackAllocator >, - public push_coroutine_base< void > -{ -public: - typedef typename Allocator::template rebind< - push_coroutine_object< - void, Fn, StackAllocator, Allocator, Caller - > - >::other allocator_t; - -private: - typedef stack_tuple< StackAllocator > pbase_type; - typedef push_coroutine_base< void > base_type; - - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, push_coroutine_object * p) - { - alloc.destroy( p); - alloc.deallocate( p, 1); - } - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - - void enter_() - { - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->callee_ = * from->ctx; - if ( this->except_) rethrow_exception( this->except_); - } - - void unwind_stack_() BOOST_NOEXCEPT - { - BOOST_ASSERT( ! this->is_complete() ); - - this->flags_ |= flag_unwind_stack; - parameters< void > to( & this->caller_, true); - this->caller_.jump( - this->callee_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - this->flags_ &= ~flag_unwind_stack; - - BOOST_ASSERT( this->is_complete() ); - } - -public: - push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, - StackAllocator const& stack_alloc, - allocator_t const& alloc) : - pbase_type( stack_alloc, attr.size), - base_type( - trampoline1< push_coroutine_object >, - & this->stack_ctx, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn), - alloc_( alloc) - { enter_(); } - - ~push_coroutine_object() - { - if ( ! this->is_complete() && this->force_unwind() ) - unwind_stack_(); - } - - void run() - { - coroutine_context callee; - coroutine_context caller; - - { - parameters< void > to( & caller); - parameters< void > * from( - reinterpret_cast< parameters< void > * >( - caller.jump( - this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->ctx); - - // create pull_coroutine - Caller c( * from->ctx, false, this->preserve_fpu(), alloc_); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - callee = c.impl_->callee_; - } - - this->flags_ |= flag_complete; - parameters< void > to( & caller); + param_type to( & caller); caller.jump( callee, reinterpret_cast< intptr_t >( & to),