diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 57818ec..8684cb7 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -20,6 +20,8 @@ project boost/coroutine gcc-4.7,on:"-static-libgcc" gcc-4.8,on:-fsplit-stack gcc-4.8,on:"-static-libgcc" + gcc-4.9,on:-fsplit-stack + gcc-4.9,on:"-static-libgcc" shared:BOOST_COROUTINES_DYN_LINK=1 BOOST_COROUTINES_SOURCE : usage-requirements diff --git a/doc/old.qbk b/doc/old.qbk deleted file mode 100644 index dee5921..0000000 --- a/doc/old.qbk +++ /dev/null @@ -1,809 +0,0 @@ -[/ - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt -] - -[section:old Bidirectional coroutine (['deprecated])] - -[note This interface is deprecated but can be used by compiling the code with -compiler flag BOOST_COROUTINES_OLD.] - -Each instance of __coro__ has its own context of execution (CPU registers and -stack space) or represents __not_a_coro__ (similar to __thread__). -Objects of type __coro__ are moveable but not copyable and can be returned by a -function. - - boost::coroutines::coroutine< void() > f(); - - void g() - { - boost::coroutines::coroutine< void() > c( f() ); - c(); - } - -[note __boost_move__ is used to emulate rvalue references.] - - -[heading Creating a coroutine] - -A new __coro__ is created from a __coro_fn__ (function or functor) which will be -executed in a new __ctx__ (CPU registers and stack space). - -[note __coro_fn__ is required to return ['void] and accept a reference of type -__coro_caller__.] - -The template argument __signature__ determines the data-types transferred to -__coro_fn__ and from __coro_fn__ by calling __coro_op__ and __coro_get__. - - typedef boost::coroutines::coroutine< int( std::string const&) > coro_t; - - // void f( boost::coroutine< std::string const&( int) > & ca) - void f( coro_t::caller_type & ca) - { - ... - // access argument - std::string str( ca.get() ); - ... - ca( 7); - ... - } - - std::string str; - ... - coro_t c( f); - // pass argument - c( str); - // returned value - int res = c.get(); - - -The __coro_fn__ is started at __coro__ construction (similar to __thread__) -in a newly created __coro__ complete with registers, flags, stack and -instruction pointer. -If __coro_fn__ requires some arguments (types defined by __signature__) -on start-up those parameters must be applied to the __coro__ constructor. -A single arguments can be passed as it is: - - typedef boost::coroutines::coroutine< int( std::string const&) > coro_t; - - // void f( boost::coroutine< std::string const&( int) > & ca) - void f( coro_t::caller_type & ca); - - std::string str("abc"); - coro_t c( f, str); - - -For multiple arguments __args__ must be used (it is a typedef of __tuple__): - - typedef boost::coroutines::coroutine< int( int, std::string const&) > coro_t; - - // void f( boost::coroutine< boost::tuple< int, std::string const& >( int) > & ca) - void f( coro_t::caller_type & ca); - - std::string str("abc"); - coro_t c( f, coro_t::arguments( 7, str) ); - - -[note The maximum number of arguments is limited to 10 (limit defined by -__boost_tuple__).] - -[note Parameters bound with __bind__ to __coro_fn__ will not be part of the -__coro_op__ signature.] - -__attrs__, an additional constructor argument of __coro__, defines the stack -size, stack unwinding and floating-point preserving behaviour used for __ctx__ -construction. - -The __coro__ constructor uses the __stack_allocator_concept__ to allocate an -associated stack, and the destructor uses the same __stack_allocator_concept__ -to deallocate the stack. The default __stack_allocator_concept__ is -__stack_allocator__, but a custom stack-allocator can be passed to the -constructor. - - -[heading Calling a coroutine] - -The execution control is transferred to __coro__ at construction (__coro_fn__ -entered) - when control should be returned to the original calling routine, -invoke __coro_op__ on the first argument of type __coro_caller__ inside -__coro_fn__. __coro_caller__ is a typedef of __coro__ with an inverted -__signature__. Inverted __signature__ means that the return type becomes an -argument and vice versa. Multiple arguments are wrapped into __tuple__. - - void f( boost::coroutines::coroutine< std::string const&( int) & ca); - boost::coroutines::coroutine< int( std::string const&) > c1( f); - - void g( boost::coroutines::coroutine< boost::tuple< X, Y >( int) & ca); - boost::coroutines::coroutine< int( X, X) > c2( g); - - -The current coroutine information (registers, flags, and stack and instruction -pointer) is saved and the original context information is restored. Calling -__coro_op__ resumes execution in the coroutine after saving the new state of the -original routine. - - typedef boost::coroutines::coroutine< void() > coro_t; - - // void fn( boost::coroutines::coroutine< void() > & ca, int j) - void fn( coro_t::caller_type & ca, int j) - { - for( int i = 0; i < j; ++i) - { - std::cout << "fn(): local variable i == " << i << std::endl; - - // save current coroutine - // value of local variable is preserved - // transfer execution control back to main() - ca(); - - // coroutine<>::operator()() was called - // execution control transferred back from main() - } - } - - int main( int argc, char * argv[]) - { - // bind parameter '7' to coroutine-fn - coro_t c( boost::bind( fn, _1, 7) ); - - std::cout << "main() starts coroutine c" << std::endl; - - while ( c) - { - std::cout << "main() calls coroutine c" << std::endl; - // execution control is transferred to c - c(); - } - - std::cout << "Done" << std::endl; - - return EXIT_SUCCESS; - } - - output: - main() starts coroutine c - fn(): local variable i == 0 - main() calls coroutine c - fn(): local variable i == 1 - main() calls coroutine c - fn(): local variable i == 2 - main() calls coroutine c - fn(): local variable i == 3 - main() calls coroutine c - fn(): local variable i == 4 - main() calls coroutine c - fn(): local variable i == 5 - main() calls coroutine c - fn(): local variable i == 6 - main() calls coroutine c - Done - -[warning Calling __coro_op__ from inside the [_same] coroutine results in -undefined behaviour.] - - -[heading Transfer of data] - -__signature__, the template argument of __coro__, defines the types transferred -to and returned from the __coro_fn__, e.g. it determines the signature of -__coro_op__ and the return-type of __coro_get__. - -[note __coro_caller__ is not part of __signature__ and __coro_fn__ is required -to return void and accept __coro_caller__ as argument.] - -__coro_op__ accepts arguments as defined in __signature__ and returns a -reference to __coro__. The arguments passed to __coro_op__, in one coroutine, -is returned (as a __tuple__) by __coro_get__ in the other coroutine. -If __coro__ is constructed and arguments are passed to the constructor, the -__coro_fn__ will be entered and the arguments are accessed thorough __coro_get__ -in __coro_fn__ on entry. - -The value given to __coro_op__ of __coro_caller__, in one coroutine, is returned by -__coro_get__ in the other routine. - - typedef boost::coroutines::coroutine< int( int) > coro_t; - - // void fn( boost::coroutines::coroutine< int( int) > & ca) - void fn( coro_t::caller_type & ca) - { - // access the integer argument given to coroutine ctor - int i = ca.get(); - std::cout << "fn(): local variable i == " << i << std::endl; - - // save current coroutine context and - // transfer execution control back to caller - // pass content of variable 'i' to caller - // after execution control is returned back coroutine<>::operator() - // returns and the transferred integer s accessed via coroutine<>::get() - i = ca( i).get(); - - // i == 10 because c( 10) in main() - std::cout << "fn(): local variable i == " << i << std::endl; - ca( i); - } - - int main( int argc, char * argv[]) - { - std::cout << "main(): call coroutine c" << std::endl; - coro_t c( fn, 7); - - int x = c.get(); - std::cout << "main(): transferred value: " << x << std::endl; - - x = c( 10).get(); - std::cout << "main(): transferred value: " << x << std::endl; - - std::cout << "Done" << std::endl; - - return EXIT_SUCCESS; - } - - output: - main(): call coroutine c - fn(): local variable i == 7 - main(): transferred value: 7 - fn(): local variable i == 10 - main(): transferred value: 10 - Done - - -[heading __coro_fn__ with multiple arguments] - -If __coro_fn__ has more than one argument __coro_op__ has the same size of -arguments and __coro_get__ from __coro_caller__ returns a __tuple__ corresponding -to the arguments of __signature__. __tie__ helps to access the values stored in -the __tuple__ returned by __coro_get__. - - typedef boost::coroutines::coroutine< int(int,int) > coro_t; - - // void fn( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca) - void fn( coro_t::caller_type & ca) - { - int a, b; - boost::tie( a, b) = ca.get(); - boost::tie( a, b) = ca( a + b).get(); - ca( a + b); - } - - int main( int argc, char * argv[]) - { - std::cout << "main(): call coroutine c" << std::endl; - coro_t coro( fn, coro_t::arguments( 3, 7) ); - - int res = coro.get(); - std::cout << "main(): 3 + 7 == " << res << std::endl; - - res = coro( 5, 7).get(); - std::cout << "main(): 5 + 7 == " << res << std::endl; - - std::cout << "Done" << std::endl; - - return EXIT_SUCCESS; - } - - output: - main(): call coroutine c - main(): 3 + 7 == 10 - main(): 5 + 7 == 12 - Done - - -[heading Transfer of pointers and references] - -You can transfer references and pointers from and to coroutines but as usual -you must take care (scope, no re-assignment of const references etc.). -In the following code `x` points to `local` which is allocated on stack of -`c`. When `c` goes out of scope the stack becomes deallocated. Using `x` -after `c` is gone will fail! - - struct X - { - void g(); - }; - - typedef boost::coroutines::coroutine< X*() > coro_t; - - // void fn( boost::coroutines::coroutine< void( X*) > & ca) - void fn( coro_t::caller_t & ca) { - X local; - ca( & local); - } - - int main() { - X * x = 0; - { - coro_t c( fn); - x = c.get(); // let x point to X on stack owned by c - // stack gets unwound -> X will be destructed - } - x->g(); // segmentation fault! - return EXIT_SUCCESS; - } - - -[heading Range iterators] - -__boost_coroutine__ provides output- and input-iterators using __boost_range__. -`coroutine< T() >` can be used via output-iterators using __begin__ and __end__. - - typedef boost::coroutines::coroutine< int() > coro_t; - typedef boost::range_iterator< coro_t >::type iterator_t; - - // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent) - void power( coro_t::caller_type & ca, int number, int exponent) - { - int counter = 0; - int result = 1; - while ( counter++ < exponent) - { - result = result * number; - ca( result); - } - } - - int main() - { - coro_t c( boost::bind( power, _1, 2, 8) ); - iterator_t e( boost::end( c) ); - for ( iterator_t i( boost::begin( c) ); i != e; ++i) - std::cout << * i << " "; - - std::cout << "\nDone" << std::endl; - - return EXIT_SUCCESS; - } - - output: - 2 4 8 16 32 64 128 256 - Done - -`BOOST_FOREACH` can be used to iterate over the coroutine range too. - - typedef boost::coroutines::coroutine< int() > coro_t; - typedef boost::range_iterator< coro_t >::type iterator_t; - - // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent) - void power( coro_t::caller_type & ca, int number, int exponent) - { - int counter = 0; - int result = 1; - while ( counter++ < exponent) - { - result = result * number; - ca( result); - } - } - - int main() - { - coro_t c( boost::bind( power, _1, 2, 8) ); - BOOST_FOREACH( int i, c) - { std::cout << i << " "; } - - std::cout << "\nDone" << std::endl; - - return EXIT_SUCCESS; - } - - output: - 2 4 8 16 32 64 128 256 - Done - - -Input iterators are created from coroutines of type `coroutine< void( T) >`. - - - -[heading Exit a __coro_fn__] - -__coro_fn__ is exited with a simple return statement jumping back to the calling -routine. The __coro__ becomes complete, e.g. __coro_bool__ will return 'false'. - - typedef boost::coroutines::coroutine< int(int,int) > coro_t; - - // void power( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca, int number, int exponent) - void fn( coro_t::caller_type & ca) - { - int a, b; - boost::tie( a, b) = ca.get(); - boost::tie( a, b) = ca( a + b).get(); - ca( a + b); - } - - int main( int argc, char * argv[]) - { - std::cout << "main(): call coroutine c" << std::endl; - coro_t coro( fn, coro_t::arguments( 3, 7) ); - - BOOST_ASSERT( coro); - int res = coro.get(); - std::cout << "main(): 3 + 7 == " << res << std::endl; - - res = coro( 5, 7).get(); - BOOST_ASSERT( ! coro); - std::cout << "main(): 5 + 7 == " << res << std::endl; - - std::cout << "Done" << std::endl; - - return EXIT_SUCCESS; - } - - output: - main(): call coroutine c - main(): 3 + 7 == 10 - main(): 5 + 7 == 12 - Done - -[important After returning from __coro_fn__ the __coro__ is complete (can not -resumed with __coro_op__).] - - -[heading Exceptions in __coro_fn__] - -An exception thrown inside __coro_fn__ will transferred via exception-pointer -(see __boost_exception__ for details) and re-thrown by constructor or -__coro_op__. - - typedef boost::coroutines::coroutine< void() > coro_t; - - // void fn( boost::coroutines::coroutine< void() > & ca) - void fn( coro_t::caller_type & ca) - { - ca(); - throw std::runtime_error("abc"); - } - - int main( int argc, char * argv[]) - { - coro_t c( f); - try - { - c(); - } - catch ( std::exception const& e) - { - std::cout << "exception catched:" << e.what() << std::endl; - return EXIT_FAILURE; - } - - std::cout << "Done" << std::endl; - - return EXIT_SUCCESS; - } - - output: - exception catched: abc - -[important Code executed by coroutine must not prevent the propagation of the -__forced_unwind__ exception. Absorbing that exception will cause stack -unwinding to fail. Thus, any code that catches all exceptions must re-throw the -pending exception.] - - try - { - // code that might throw - } - catch( forced_unwind) - { - throw; - } - catch(...) - { - // possibly not re-throw pending exception - } - - -[heading Stack unwinding] - -Sometimes it is necessary to unwind the stack of an unfinished coroutine to -destroy local stack variables so they can release allocated resources (RAII -pattern). The third argument of the coroutine constructor, `do_unwind`, -indicates whether the destructor should unwind the stack (stack is unwound by -default). - -Stack unwinding assumes the following preconditions: - -* The coroutine is not __not_a_coro__ -* The coroutine is not complete -* The coroutine is not running -* The coroutine owns a stack - -After unwinding, a __coro__ is complete. - - - typedef boost::coroutines::coroutine< void() > coro_t; - - struct X - { - X() - { std::cout << "X()" << std::endl; } - - ~X() - { std::cout << "~X()" << std::endl; } - }; - - // void fn( boost::coroutines::coroutine< void() > & ca) - void fn( coro_t::caller_type & ca) - { - X x; - - for ( int = 0;; ++i) - { - std::cout << "fn(): " << i << std::endl; - // transfer execution control back to main() - ca(); - } - } - - int main( int argc, char * argv[]) - { - { - coro_t c( fn, - boost::coroutines::attributes( - boost::context::default_stacksize(), - boost::coroutines::stack_unwind) ); - - c(); - c(); - c(); - c(); - c(); - - std::cout << "c is complete: " << std::boolalpha << c.is_complete() << "\n"; - } - - std::cout << "Done" << std::endl; - - return EXIT_SUCCESS; - } - - output: - X() - fn(): 0 - fn(): 1 - fn(): 2 - fn(): 3 - fn(): 4 - fn(): 5 - c is complete: false - ~X() - Done - -[important You must not swallow __forced_unwind__ exceptions!] - - -[heading FPU preserving] - -Some applications do not use floating-point registers and can disable preserving -fpu registers for performance reasons. - -[note According to the calling convention the FPU registers are preserved by default.] - - -[section:coroutine Class `coroutine`] - - #include - - template< typename Signature > - class coroutine; - - template< - typename R, - typename ArgTypes... - > - class coroutine< R ( ArgTypes...) > - { - public: - typedef unspec-type caller_type; - typedef unspec-type arguments; - - coroutine(); - - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > - coroutine( Fn fn, attributes const& attr = attributes(), - StackAllocator const& stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); - - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > - coroutine( Fn fn, arguments const& args, - attributes const& attr = attributes(), - StackAllocator const& stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); - - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > - coroutine( Fn && fn, attributes const& attr = attributes(), - StackAllocator stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); - - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > - coroutine( Fn && fn arguments const& args, - attributes const& attr = attributes(), - StackAllocator stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); - - coroutine( coroutine && other); - - coroutine & operator=( coroutine && other); - - operator unspecified-bool-type() const; - - bool operator!() const; - - void swap( coroutine & other); - - bool empty() const; - - coroutine & operator()(A0 a0, ..., A9 a9); - - R get() const; - }; - - template< typename Signature > - void swap( coroutine< Signature > & l, coroutine< Signature > & r); - - template< typename T > - range_iterator< coroutine< T() > >::type begin( coroutine< T() > &); - template< typename T > - range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &); - - template< typename T > - range_iterator< coroutine< T() > >::type end( coroutine< T() > &); - template< typename T > - range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &); - -[heading `coroutine()`] -[variablelist -[[Effects:] [Creates a coroutine representing __not_a_coro__.]] -[[Throws:] [Nothing.]] -] - -[heading `template< typename Fn, typename StackAllocator, typename Allocator > - coroutine( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`] -[variablelist -[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() -when ! is_stack_unbound().]] -[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr` -determines stack clean-up and preserving floating-point registers. -For allocating/deallocating the stack `stack_alloc` is used and internal -data are allocated by Allocator.]] -] - -[heading `template< typename Fn, typename StackAllocator, typename Allocator > - coroutine( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`] -[variablelist -[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() -when ! is_stack_unbound().]] -[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr` -determines stack clean-up and preserving floating-point registers. -For allocating/deallocating the stack `stack_alloc` is used and internal -data are allocated by Allocator.]] -] - -[heading `coroutine( coroutine && other)`] -[variablelist -[[Effects:] [Moves the internal data of `other` to `*this`. -`other` becomes __not_a_coro__.]] -[[Throws:] [Nothing.]] -] - -[heading `coroutine & operator=( coroutine && other)`] -[variablelist -[[Effects:] [Destroys the internal data of `*this` and moves the -internal data of `other` to `*this`. `other` becomes __not_a_coro__.]] -[[Throws:] [Nothing.]] -] - -[heading `operator unspecified-bool-type() const`] -[variablelist -[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function -has returned (completed), the function returns false. Otherwise true.]] -[[Throws:] [Nothing.]] -] - -[heading `bool operator!() const`] -[variablelist -[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function -has returned (completed), the function returns true. Otherwise false.]] -[[Throws:] [Nothing.]] -] - -[heading `bool empty()`] -[variablelist -[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true. -Otherwise false.]] -[[Throws:] [Nothing.]] -] - -[heading `coroutine<> & operator()(A0 a0, A9 a9)`] -[variablelist -[[Preconditions:] [operator unspecified-bool-type() returns true for `*this`.] -[[Effects:] [Execution control is transferred to __coro_fn__ and the arguments -`a0`,..., are passed to the coroutine-function.]] -[[Throws:] [Exceptions thrown inside __coro_fn__.]] -] - -[heading `R get()()`] -[variablelist -[[Preconditions:] [`*this` is not a __not_a_coro__, `! is_complete()`.]] -[[Returns:] [Returns data transferred from coroutine-function via __coro_op__ -of __coro_caller__.]] -[[Throws:] [Nothing.]] -] - -[heading `void swap( coroutine & other)`] -[variablelist -[[Effects:] [Swaps the internal data from `*this` with the values -of `other`.]] -[[Throws:] [Nothing.]] -] - -[heading `T caller_type::operator()( R)`] -[variablelist -[[Effects:] [Gives execution control back to calling context by returning -a value of type R. The return type of this function is a __tuple__ containing -the arguments passed to __coro_op__.]] -[[Throws:] [Nothing.]] -] - -[heading Non-member function `swap()`] - - template< typename Signature > - void swap( coroutine< Signature > & l, coroutine< Signature > & r); - -[variablelist -[[Effects:] [As if 'l.swap( r)'.]] -] - -[heading Non-member function `begin( coroutine< T() > &)`] - template< typename T > - range_iterator< coroutine< T() > >::type begin( coroutine< T() > &); - -[variablelist -[[Returns:] [Returns a range-iterator (input-iterator).]] -] - -[heading Non-member function `begin( coroutine< void(T) > &)`] - template< typename T > - range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &); - -[variablelist -[[Returns:] [Returns a range-iterator (output-iterator).]] -] - -[heading Non-member function `end( coroutine< T() > &)`] - template< typename T > - range_iterator< coroutine< T() > >::type end( coroutine< T() > &); - -[variablelist -[[Returns:] [Returns a end range-iterator (input-iterator).]] -] - -[heading Non-member function `end( coroutine< void(T) > &)`] - template< typename T > - range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &); - -[variablelist -[[Returns:] [Returns a end range-iterator (output-iterator).]] -] - -[endsect] - -[endsect] diff --git a/doc/unidirect.qbk b/doc/unidirect.qbk index 16051e0..090e6db 100644 --- a/doc/unidirect.qbk +++ b/doc/unidirect.qbk @@ -428,29 +428,18 @@ resumed with __coro_op__).] #include - template< typename R > + template< typename R, typename StackAllocator = standard_stack_allocator > class coroutine<>::pull_type { public: pull_type(); - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > - pull_type( Fn fn, attributes const& attr = attributes(), - StackAllocator const& stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); + template< typename Fn > + pull_type( Fn fn, attributes const& attr = attributes() ); - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > + template< typename Fn > pull_type( Fn && fn, attributes const& attr = attributes(), - StackAllocator stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); + StackAllocator stack_alloc = StackAllocator() ); pull_type( pull_type && other); @@ -486,27 +475,24 @@ resumed with __coro_op__).] [[Throws:] [Nothing.]] ] -[heading `template< typename Fn, typename StackAllocator, typename Allocator > - pull_type( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`] +[heading `template< typename Fn > + pull_type( Fn fn, attributes const& attr)`] [variablelist [[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() when ! is_stack_unbound().]] [[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr` -determines stack clean-up and preserving floating-point registers. -For allocating/deallocating the stack `stack_alloc` is used and internal -data are allocated by Allocator.]] +determines stack clean-up and preserving floating-point registers.]] [[Throws:] [Exceptions thrown inside __coro_fn__.]] ] -[heading `template< typename Fn, typename StackAllocator, typename Allocator > - pull_type( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`] +[heading `template< typename Fn > + pull_type( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc)`] [variablelist [[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() when ! is_stack_unbound().]] [[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr` determines stack clean-up and preserving floating-point registers. -For allocating/deallocating the stack `stack_alloc` is used and internal -data are allocated by Allocator.]] +For allocating/deallocating the stack `stack_alloc` is used.]] [[Throws:] [Exceptions thrown inside __coro_fn__.]] ] @@ -612,29 +598,18 @@ of `other`.]] #include - template< typename Arg > + template< typename Arg, typename StackAllocator = standard_stack_allocator > class coroutine<>::push_type { public: push_type(); - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > - push_type( Fn fn, attributes const& attr = attributes(), - StackAllocator const& stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); + template< typename Fn > + push_type( Fn fn, attributes const& attr = attributes() ); - template< - typename Fn, - typename StackAllocator = stack_allocator, - typename Allocator = std::allocator< coroutine > - > + template< typename Fn > push_type( Fn && fn, attributes const& attr = attributes(), - StackAllocator stack_alloc = StackAllocator(), - Allocator const& alloc = Allocator() ); + StackAllocator stack_alloc = StackAllocator() ); push_type( push_type && other); diff --git a/example/cpp03/Jamfile.v2 b/example/cpp03/Jamfile.v2 index ac23140..4bc4880 100644 --- a/example/cpp03/Jamfile.v2 +++ b/example/cpp03/Jamfile.v2 @@ -20,7 +20,11 @@ project boost/coroutine/example /boost/program_options//boost_program_options /boost/thread//boost_thread gcc-4.7,on:-fsplit-stack + gcc-4.7,on:-DBOOST_USE_SEGMENTED_STACKS gcc-4.8,on:-fsplit-stack + gcc-4.8,on:-DBOOST_USE_SEGMENTED_STACKS + gcc-4.9,on:-fsplit-stack + gcc-4.9,on:-DBOOST_USE_SEGMENTED_STACKS static multi ; diff --git a/example/cpp03/simple.cpp b/example/cpp03/simple.cpp index 612dc96..7c00079 100644 --- a/example/cpp03/simple.cpp +++ b/example/cpp03/simple.cpp @@ -19,21 +19,23 @@ struct X {} }; -typedef boost::coroutines::coroutine< void >::pull_type pull_coro_t; -typedef boost::coroutines::coroutine< void >::push_type push_coro_t; +typedef boost::coroutines::coroutine< X& >::pull_type pull_coro_t; +typedef boost::coroutines::coroutine< X& >::push_type push_coro_t; void fn1( push_coro_t & sink) { for ( int i = 0; i < 10; ++i) { - sink(); + X x( i); + sink( x); } } void fn2( pull_coro_t & source) { while ( source) { - std::cout << "i = " << std::endl; + X & x = source.get(); + std::cout << "i = " << x.i << std::endl; source(); } } @@ -43,8 +45,8 @@ int main( int argc, char * argv[]) { pull_coro_t source( fn1); while ( source) { -// X * x = source.get(); - std::cout << "i = " << std::endl; + X & x = source.get(); + std::cout << "i = " << x.i << std::endl; source(); } } @@ -52,7 +54,8 @@ int main( int argc, char * argv[]) push_coro_t sink( fn2); for ( int i = 0; i < 10; ++i) { - sink(); + X x( i); + sink( x); } } std::cout << "Done" << std::endl; diff --git a/example/cpp11/Jamfile.v2 b/example/cpp11/Jamfile.v2 index 64ddc1b..aff2101 100644 --- a/example/cpp11/Jamfile.v2 +++ b/example/cpp11/Jamfile.v2 @@ -35,7 +35,11 @@ project boost/coroutine/example /boost/program_options//boost_program_options /boost/thread//boost_thread gcc-4.7,on:-fsplit-stack + gcc-4.7,on:-DBOOST_USE_SEGMENTED_STACKS gcc-4.8,on:-fsplit-stack + gcc-4.8,on:-DBOOST_USE_SEGMENTED_STACKS + gcc-4.9,on:-fsplit-stack + gcc-4.9,on:-DBOOST_USE_SEGMENTED_STACKS static multi ; diff --git a/include/boost/coroutine/coroutine.hpp b/include/boost/coroutine/coroutine.hpp index 24498a6..b00cd0c 100644 --- a/include/boost/coroutine/coroutine.hpp +++ b/include/boost/coroutine/coroutine.hpp @@ -27,13 +27,12 @@ #include #include #include -#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -52,13 +51,14 @@ private: template< typename X, typename Y, typename Z > - friend class detail::pull_coroutine_object; + friend void detail::trampoline_pull( intptr_t); - typedef detail::push_coroutine_base< Arg > base_t; + typedef detail::push_coroutine_impl< Arg > impl_type; + typedef detail::parameters< Arg > param_type; struct dummy {}; - base_t * impl_; + impl_type * impl_; StackAllocator stack_alloc_; stack_context stack_ctx_; detail::coroutine_context caller_; @@ -66,7 +66,7 @@ private: BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine) - push_coroutine( base_t * impl) : + push_coroutine( impl_type * impl) : impl_( impl), stack_alloc_(), stack_ctx_(), @@ -240,13 +240,14 @@ private: template< typename X, typename Y, typename Z > - friend class detail::pull_coroutine_object; + friend void detail::trampoline_pull( intptr_t); - typedef detail::push_coroutine_base< Arg & > base_t; + typedef detail::push_coroutine_impl< Arg & > impl_type; + typedef detail::parameters< Arg & > param_type; struct dummy {}; - base_t * impl_; + impl_type * impl_; StackAllocator stack_alloc_; stack_context stack_ctx_; detail::coroutine_context caller_; @@ -254,7 +255,7 @@ private: BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine) - push_coroutine( base_t * impl) : + push_coroutine( impl_type * impl) : impl_( impl), stack_alloc_(), stack_ctx_(), @@ -421,17 +422,14 @@ private: template< typename X, typename Y, typename Z > - friend class detail::pull_coroutine_object; - template< - typename X, typename Y, typename Z - > - friend void detail::trampoline_void( intptr_t); + friend void detail::trampoline_pull_void( intptr_t); - typedef detail::push_coroutine_base< void > base_t; + typedef detail::push_coroutine_impl< void > impl_type; + typedef detail::parameters< void > param_type; struct dummy {}; - base_t * impl_; + impl_type * impl_; StackAllocator stack_alloc_; stack_context stack_ctx_; detail::coroutine_context caller_; @@ -439,7 +437,7 @@ private: BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine) - push_coroutine( base_t * impl) : + push_coroutine( impl_type * impl) : impl_( impl), stack_alloc_(), stack_ctx_(), @@ -574,13 +572,14 @@ private: template< typename X, typename Y, typename Z > - friend class detail::push_coroutine_object; + friend void detail::trampoline_push( intptr_t); - typedef detail::pull_coroutine_base< R > base_t; + typedef detail::pull_coroutine_impl< R > impl_type; + typedef detail::parameters< R > param_type; struct dummy {}; - base_t * impl_; + impl_type * impl_; StackAllocator stack_alloc_; stack_context stack_ctx_; detail::coroutine_context caller_; @@ -588,7 +587,7 @@ private: BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) - pull_coroutine( base_t * impl) : + pull_coroutine( impl_type * impl) : impl_( impl), stack_alloc_(), stack_ctx_(), @@ -617,16 +616,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, coroutine_fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< coroutine_fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -644,16 +640,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, coroutine_fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< coroutine_fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -671,16 +664,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, Fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -699,16 +689,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, Fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -730,15 +717,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, Fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -761,15 +746,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, Fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -791,15 +774,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, Fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -822,15 +803,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R, Fn, push_coroutine< R, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1005,13 +984,14 @@ private: template< typename X, typename Y, typename Z > - friend class detail::push_coroutine_object; + friend void detail::trampoline_push( intptr_t); - typedef detail::pull_coroutine_base< R & > base_t; + typedef detail::pull_coroutine_impl< R & > impl_type; + typedef detail::parameters< R & > param_type; struct dummy {}; - base_t * impl_; + impl_type * impl_; StackAllocator stack_alloc_; stack_context stack_ctx_; detail::coroutine_context caller_; @@ -1019,7 +999,7 @@ private: BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) - pull_coroutine( base_t * impl) : + pull_coroutine( impl_type * impl) : impl_( impl), stack_alloc_(), stack_ctx_(), @@ -1048,16 +1028,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, coroutine_fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< coroutine_fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutien_fn, impl_type > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1075,16 +1052,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, coroutine_fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< coroutine_fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutien_fn, impl_type > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1102,16 +1076,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, Fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1130,16 +1101,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, Fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1161,15 +1129,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, Fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1192,15 +1158,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, Fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1222,15 +1186,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, Fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1253,15 +1215,13 @@ public: caller_(), callee_() { - typedef detail::pull_coroutine_object< - R &, Fn, push_coroutine< R &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_pull< Fn, impl_type, push_coroutine< R &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1432,17 +1392,14 @@ private: template< typename X, typename Y, typename Z > - friend class detail::push_coroutine_object; - template< - typename X, typename Y, typename Z - > - friend void detail::trampoline_void( intptr_t); + friend void detail::trampoline_push_void( intptr_t); - typedef detail::pull_coroutine_base< void > base_t; + typedef detail::pull_coroutine_impl< void > impl_type; + typedef detail::parameters< void > param_type; struct dummy {}; - base_t * impl_; + impl_type * impl_; StackAllocator stack_alloc_; stack_context stack_ctx_; detail::coroutine_context caller_; @@ -1450,7 +1407,7 @@ private: BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) - pull_coroutine( base_t * impl) : + pull_coroutine( impl_type * impl) : impl_( impl), stack_alloc_(), stack_ctx_(), @@ -1481,13 +1438,13 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - coroutine_fn, base_t, push_corotuine< void, StackAllocator > + detail::trampoline_pull_void< + coroutine_fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< coroutine_fn, base_t > to( forward< coroutine_fn >( fn), + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1507,13 +1464,13 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - coroutine_fn, base_t, push_coroutine< void, StackAllocator > + detail::trampoline_pull_void< + coroutine_fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< coroutine_fn, base_t > to( forward< coroutine_fn >( fn), + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1533,13 +1490,13 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, push_coroutine< void, StackAllocator > + detail::trampoline_pull_void< + Fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( forward< Fn >( fn), + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1560,13 +1517,13 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, push_coroutine< void, StackAllocator > + detail::trampoline_pull_void< + Fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( forward< Fn >( fn), + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1589,12 +1546,12 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline_void< - Fn, base_t, push_coroutine< void, StackAllocator > + detail::trampoline_pull_void< + Fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1618,12 +1575,12 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline_void< - Fn, base_t, push_coroutine< void, StackAllocator > + detail::trampoline_pull_void< + Fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1647,12 +1604,12 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, push_coroutine< void, StackAllocator > + detail::trampoline_pull_void< + Fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1677,12 +1634,12 @@ public: { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, push_coroutine< void, StackAllocator > + detail::trampoline_pull_void< + Fn, impl_type, push_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1758,16 +1715,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( coroutine_fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, coroutine_fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + coroutine_fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1785,16 +1740,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( coroutine_fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, coroutine_fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + coroutine_fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1811,16 +1764,14 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( coroutine_fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, coroutine_fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + coroutine_fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1838,16 +1789,15 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( coroutine_fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, coroutine_fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< coroutine_fn, object_t >, - & stack_ctx_); - detail::setup< coroutine_fn, object_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + coroutine_fn, impl_type, pull_coroutine< Arg &, StackAllocator > + coroutine_fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1866,13 +1816,12 @@ push_coroutine< void, StackAllocator >::push_coroutine( coroutine_fn fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - coroutine_fn, base_t, pull_corotuine< void, StackAllocator > + detail::trampoline_push_void< + coroutine_fn, impl_type, pull_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< coroutine_fn, base_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1892,13 +1841,12 @@ push_coroutine< void, StackAllocator >::push_coroutine( coroutine_fn fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - coroutine_fn, base_t, pull_corotuine< void, StackAllocator > - >, - & stack_ctx_); - detail::setup< coroutine_fn, base_t > to( forward< coroutine_fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::trampoline_push_void< + coroutine_fn, impl_type, pull_coroutine< void, StackAllocator > + >, + & stack_ctx_); + detail::setup< coroutine_fn > to( forward< coroutine_fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1916,16 +1864,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, Fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1944,16 +1890,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, Fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1971,16 +1915,14 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, Fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -1999,16 +1941,14 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, Fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( forward< Fn >( fn), - & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2028,13 +1968,13 @@ push_coroutine< void, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, pull_coroutine< void, StackAllocator > + detail::trampoline_push_void< + Fn, impl_type, pull_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( forward< Fn >( fn), + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2055,13 +1995,13 @@ push_coroutine< void, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, pull_coroutine< void, StackAllocator > + detail::trampoline_push_void< + Fn, impl_type, pull_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( forward< Fn >( fn), + detail::setup< Fn > to( forward< Fn >( fn), & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2083,15 +2023,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( Fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, Fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2114,15 +2053,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( Fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, Fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2144,15 +2082,14 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( Fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, Fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2175,15 +2112,14 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( Fn fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, Fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2207,12 +2143,12 @@ push_coroutine< void, StackAllocator >::push_coroutine( Fn fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline_void< - Fn, base_t, pull_coroutine< void, StackAllocator > + detail::trampoline_push_void< + Fn, impl_type, pull_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2237,12 +2173,12 @@ push_coroutine< void, StackAllocator >::push_coroutine( Fn fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline_void< - Fn, base_t, pull_coroutine< void, StackAllocator > + detail::trampoline_push_void< + Fn, impl_type, pull_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2264,15 +2200,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, Fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2295,15 +2230,14 @@ push_coroutine< Arg, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg, Fn, pull_coroutine< Arg, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2325,15 +2259,14 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, Fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2356,15 +2289,14 @@ push_coroutine< Arg &, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, caller_(), callee_() { - typedef detail::push_coroutine_object< - Arg &, Fn, pull_coroutine< Arg &, StackAllocator > - > object_t; - stack_alloc_.allocate( stack_ctx_, attr.size); - callee_ = detail::coroutine_context( detail::trampoline< Fn, object_t >, - & stack_ctx_); - detail::setup< Fn, object_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + callee_ = detail::coroutine_context( + detail::trampoline_push< + Fn, impl_type, pull_coroutine< Arg &, StackAllocator > + >, + & stack_ctx_); + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2388,12 +2320,12 @@ push_coroutine< void, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, pull_coroutine< void, StackAllocator > + detail::trampoline_push_void< + Fn, impl_type, pull_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), @@ -2418,12 +2350,12 @@ push_coroutine< void, StackAllocator >::push_coroutine( BOOST_RV_REF( Fn) fn, { stack_alloc_.allocate( stack_ctx_, attr.size); callee_ = detail::coroutine_context( - detail::trampoline< - Fn, base_t, pull_coroutine< void, StackAllocator > + detail::trampoline_push_void< + Fn, impl_type, pull_coroutine< void, StackAllocator > >, & stack_ctx_); - detail::setup< Fn, base_t > to( fn, & caller_, & callee_, attr); - impl_ = reinterpret_cast< base_t * >( + detail::setup< Fn > to( fn, & caller_, & callee_, attr); + impl_ = reinterpret_cast< impl_type * >( caller_.jump( callee_, reinterpret_cast< intptr_t >( & to), diff --git a/include/boost/coroutine/detail/pull_coroutine_base.hpp b/include/boost/coroutine/detail/pull_coroutine_impl.hpp similarity index 89% rename from include/boost/coroutine/detail/pull_coroutine_base.hpp rename to include/boost/coroutine/detail/pull_coroutine_impl.hpp index 0d96c2d..3ac4d10 100644 --- a/include/boost/coroutine/detail/pull_coroutine_base.hpp +++ b/include/boost/coroutine/detail/pull_coroutine_impl.hpp @@ -4,8 +4,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_COROUTINES_DETAIL_PULL_COROUTINE_BASE_H -#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_BASE_H +#ifndef BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H +#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H #include #include @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #ifdef BOOST_HAS_ABI_HEADERS @@ -32,17 +32,16 @@ struct stack_context; namespace detail { template< typename R > -class pull_coroutine_base : private noncopyable +class pull_coroutine_impl : private noncopyable { private: template< typename X, typename Y, typename Z > - friend class push_coroutine_object; + friend void trampoline_pull( intptr_t); typedef parameters< R > param_type; -protected: int flags_; exception_ptr except_; coroutine_context * caller_; @@ -50,7 +49,7 @@ protected: R * result_; public: - pull_coroutine_base( coroutine_context * caller, + pull_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu) : flags_( 0), @@ -63,7 +62,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - pull_coroutine_base( coroutine_context * caller, + pull_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu, R * result) : @@ -77,7 +76,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - virtual ~pull_coroutine_base() + virtual ~pull_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT @@ -145,17 +144,16 @@ public: }; template< typename R > -class pull_coroutine_base< R & > : private noncopyable +class pull_coroutine_impl< R & > : private noncopyable { private: template< typename X, typename Y, typename Z > - friend class push_coroutine_object; + friend void trampoline_pull( intptr_t); typedef parameters< R & > param_type; -protected: int flags_; exception_ptr except_; coroutine_context * caller_; @@ -163,7 +161,7 @@ protected: R * result_; public: - pull_coroutine_base( coroutine_context * caller, + pull_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu) : flags_( 0), @@ -176,7 +174,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - pull_coroutine_base( coroutine_context * caller, + pull_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu, R * result) : @@ -190,7 +188,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - virtual ~pull_coroutine_base() + virtual ~pull_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT @@ -258,15 +256,13 @@ public: }; template<> -class pull_coroutine_base< void > : private noncopyable +class pull_coroutine_impl< void > : private noncopyable { private: - template< typename X, typename Y, typename Z > - friend class push_coroutine_object; template< typename X, typename Y, typename Z > - friend void trampoline_void( intptr_t); + friend void trampoline_pull_void( intptr_t); typedef parameters< void > param_type; @@ -276,7 +272,7 @@ private: coroutine_context * callee_; public: - pull_coroutine_base( coroutine_context * caller, + pull_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu) : flags_( 0), @@ -288,7 +284,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - virtual ~pull_coroutine_base() + virtual ~pull_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT @@ -341,4 +337,4 @@ public: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_BASE_H +#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H diff --git a/include/boost/coroutine/detail/pull_coroutine_object.hpp b/include/boost/coroutine/detail/pull_coroutine_object.hpp deleted file mode 100644 index b1245ef..0000000 --- a/include/boost/coroutine/detail/pull_coroutine_object.hpp +++ /dev/null @@ -1,191 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H -#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_MSVC - #pragma warning (push) - #pragma warning (disable: 4355) // using 'this' in initializer list -#endif - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace coroutines { -namespace detail { - -template< typename R, typename Fn, typename Caller > -class pull_coroutine_object : public pull_coroutine_base< R > -{ -private: - typedef pull_coroutine_base< R > base_type; - typedef parameters< R > param_type; - - Fn fn_; - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - -public: -#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES - pull_coroutine_object( Fn fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn) - {} -#endif - pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), -#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES - fn_( fn) -#else - fn_( forward< Fn >( fn) ) -#endif - {} - - void run() - { - { - param_type * from( - reinterpret_cast< param_type * >( - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->result_ = from->data; - - // create push_coroutine - typename Caller::base_t b( this->callee_, this->caller_, false, this->preserve_fpu() ); - Caller c( & b); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - } - - this->flags_ |= flag_complete; - param_type to; - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } -}; - -template< typename R, typename Fn, typename Caller > -class pull_coroutine_object< R &, Fn, Caller > : public pull_coroutine_base< R & > -{ -private: - typedef pull_coroutine_base< R & > base_type; - typedef parameters< R & > param_type; - - Fn fn_; - - pull_coroutine_object( pull_coroutine_object &); - pull_coroutine_object & operator=( pull_coroutine_object const&); - -public: -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( forward< Fn >( fn) ) - {} -#else - pull_coroutine_object( Fn fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn) - {} - - pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn) - {} -#endif - - void run() - { - { - param_type * from( - reinterpret_cast< param_type * >( - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - this->result_ = from->data; - - // create push_coroutine - typename Caller::base_t b( this->callee_, this->caller_, false, this->preserve_fpu() ); - Caller c( & b); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - } - - this->flags_ |= flag_complete; - param_type to; - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#ifdef BOOST_MSVC - #pragma warning (pop) -#endif - -#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H diff --git a/include/boost/coroutine/detail/push_coroutine_base.hpp b/include/boost/coroutine/detail/push_coroutine_impl.hpp similarity index 89% rename from include/boost/coroutine/detail/push_coroutine_base.hpp rename to include/boost/coroutine/detail/push_coroutine_impl.hpp index 767dba0..3ee52e3 100644 --- a/include/boost/coroutine/detail/push_coroutine_base.hpp +++ b/include/boost/coroutine/detail/push_coroutine_impl.hpp @@ -4,8 +4,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_BASE_H -#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_BASE_H +#ifndef BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H +#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H #include #include @@ -17,6 +17,7 @@ #include #include #include +#include #include #ifdef BOOST_HAS_ABI_HEADERS @@ -31,24 +32,23 @@ struct stack_context; namespace detail { template< typename Arg > -class push_coroutine_base : private noncopyable +class push_coroutine_impl : private noncopyable { private: template< typename X, typename Y, typename Z > - friend class pull_coroutine_object; + friend void trampoline_push( intptr_t); typedef parameters< Arg > param_type; -protected: int flags_; exception_ptr except_; coroutine_context * caller_; coroutine_context * callee_; public: - push_coroutine_base( coroutine_context * caller, + push_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu) : flags_( 0), @@ -60,7 +60,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - virtual ~push_coroutine_base() + virtual ~push_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT @@ -123,24 +123,23 @@ public: }; template< typename Arg > -class push_coroutine_base< Arg & > : private noncopyable +class push_coroutine_impl< Arg & > : private noncopyable { private: template< typename X, typename Y, typename Z > - friend class pull_coroutine_object; + friend void trampoline_push( intptr_t); typedef parameters< Arg & > param_type; -protected: int flags_; exception_ptr except_; coroutine_context * caller_; coroutine_context * callee_; public: - push_coroutine_base( coroutine_context * caller, + push_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu) : flags_( 0), @@ -152,7 +151,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - virtual ~push_coroutine_base() + virtual ~push_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT @@ -200,17 +199,13 @@ public: }; template<> -class push_coroutine_base< void > : private noncopyable +class push_coroutine_impl< void > : private noncopyable { private: template< typename X, typename Y, typename Z > - friend class pull_coroutine_object; - template< - typename X, typename Y, typename Z - > - friend void trampoline_void( intptr_t); + friend void trampoline_push_void( intptr_t); typedef parameters< void > param_type; @@ -220,7 +215,7 @@ private: coroutine_context * callee_; public: - push_coroutine_base( coroutine_context * caller, + push_coroutine_impl( coroutine_context * caller, coroutine_context * callee, bool unwind, bool preserve_fpu) : flags_( 0), @@ -232,7 +227,7 @@ public: if ( preserve_fpu) flags_ |= flag_preserve_fpu; } - virtual ~push_coroutine_base() + virtual ~push_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT @@ -285,4 +280,4 @@ public: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_BASE_H +#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H diff --git a/include/boost/coroutine/detail/push_coroutine_object.hpp b/include/boost/coroutine/detail/push_coroutine_object.hpp deleted file mode 100644 index 76d6199..0000000 --- a/include/boost/coroutine/detail/push_coroutine_object.hpp +++ /dev/null @@ -1,192 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H -#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_MSVC - #pragma warning (push) - #pragma warning (disable: 4355) // using 'this' in initializer list -#endif - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace coroutines { -namespace detail { - -template< typename Arg, typename Fn, typename Caller > -class push_coroutine_object : public push_coroutine_base< Arg > -{ -private: - typedef push_coroutine_base< Arg > base_type; - typedef parameters< Arg > param_type; - - Fn fn_; - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - -public: -#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES - push_coroutine_object( Fn fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn) - {} -#endif - push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), -#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES - fn_( fn) -#else - fn_( forward< Fn >( fn) ) -#endif - {} - - void run() - { - { - param_type * from( - reinterpret_cast< param_type * >( - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->data); - - // create pull_coroutine - typename Caller::base_t b( this->callee_, this->caller_, false, this->preserve_fpu(), from->data); - Caller c( & b); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - } - - this->flags_ |= flag_complete; - param_type to; - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } -}; - -template< typename Arg, typename Fn, typename Caller > -class push_coroutine_object< Arg &, Fn, Caller > : public push_coroutine_base< Arg & > -{ -private: - typedef push_coroutine_base< Arg & > base_type; - typedef parameters< Arg & > param_type; - - Fn fn_; - - push_coroutine_object( push_coroutine_object &); - push_coroutine_object & operator=( push_coroutine_object const&); - -public: -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( forward< Fn >( fn) ) - {} -#else - push_coroutine_object( Fn fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn) - {} - - push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, - coroutine_context * caller, - coroutine_context * callee) : - base_type( caller, callee, - stack_unwind == attr.do_unwind, - fpu_preserved == attr.preserve_fpu), - fn_( fn) - {} -#endif - - void run() - { - { - param_type * from( - reinterpret_cast< param_type * >( - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( this), - this->preserve_fpu() ) ) ); - BOOST_ASSERT( from->data); - - // create pull_coroutine - typename Caller::base_t b( this->callee_, this->caller_, false, this->preserve_fpu(), from->data); - Caller c( & b); - try - { fn_( c); } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - } - - this->flags_ |= flag_complete; - param_type to; - this->callee_->jump( - * this->caller_, - reinterpret_cast< intptr_t >( & to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "push_coroutine is complete"); - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#ifdef BOOST_MSVC - #pragma warning (pop) -#endif - -#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H diff --git a/include/boost/coroutine/detail/setup.hpp b/include/boost/coroutine/detail/setup.hpp index 61b5e3d..4f002f1 100644 --- a/include/boost/coroutine/detail/setup.hpp +++ b/include/boost/coroutine/detail/setup.hpp @@ -25,7 +25,7 @@ namespace boost { namespace coroutines { namespace detail { -template< typename Fn, typename Coro > +template< typename Fn > struct setup { struct dummy {}; diff --git a/include/boost/coroutine/detail/trampoline.hpp b/include/boost/coroutine/detail/trampoline_pull.hpp similarity index 54% rename from include/boost/coroutine/detail/trampoline.hpp rename to include/boost/coroutine/detail/trampoline_pull.hpp index b0b72ee..8babd9d 100644 --- a/include/boost/coroutine/detail/trampoline.hpp +++ b/include/boost/coroutine/detail/trampoline_pull.hpp @@ -4,8 +4,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_COROUTINES_DETAIL_TRAMPOLINE_H -#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_H +#ifndef BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H +#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H #include @@ -31,32 +31,64 @@ namespace boost { namespace coroutines { namespace detail { -template< typename Fn, typename Coro > -void trampoline( intptr_t vp) +template< typename Fn, typename Coro, typename Self > +void trampoline_pull( intptr_t vp) { + typedef typename Coro::param_type param_type; + BOOST_ASSERT( vp); - setup< Fn, Coro > * from( - reinterpret_cast< setup< Fn, Coro > * >( vp) ); + setup< Fn > * from( + reinterpret_cast< setup< Fn > * >( vp) ); #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - Coro c( forward< Fn >( from->fn), from->attr, from->caller, from->callee); + Fn fn( forward< Fn >( from->fn) ); #else - Coro c( move( from->fn), from->attr, from->caller, from->callee); + Fn fn( move( from->fn) ); #endif + Coro c( from->caller, from->callee, + stack_unwind == from->attr.do_unwind, + fpu_preserved == from->attr.preserve_fpu); from = 0; - c.run(); + + { + param_type * from( + reinterpret_cast< param_type * >( + 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() ); + Self self( & b); + try + { fn( self); } + catch ( forced_unwind const&) + {} + catch (...) + { c.except_ = current_exception(); } + } + + c.flags_ |= flag_complete; + param_type to; + c.callee_->jump( + * c.caller_, + reinterpret_cast< intptr_t >( & to), + c.preserve_fpu() ); + BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); } template< typename Fn, typename Coro, typename Self > -void trampoline_void( intptr_t vp) +void trampoline_pull_void( intptr_t vp) { - typedef parameters< void > param_type; + typedef typename Coro::param_type param_type; BOOST_ASSERT( vp); - setup< Fn, Coro > * from( - reinterpret_cast< setup< Fn, Coro > * >( vp) ); + setup< Fn > * from( + reinterpret_cast< setup< Fn > * >( vp) ); #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Fn fn( forward< Fn >( from->fn) ); @@ -75,7 +107,7 @@ void trampoline_void( intptr_t vp) c.preserve_fpu() ); // create push_coroutine - typename Self::base_t b( c.callee_, c.caller_, false, c.preserve_fpu() ); + typename Self::impl_type b( c.callee_, c.caller_, false, c.preserve_fpu() ); Self self( & b); try { fn( self); } @@ -100,4 +132,4 @@ void trampoline_void( intptr_t vp) # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_H +#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H diff --git a/include/boost/coroutine/detail/trampoline_push.hpp b/include/boost/coroutine/detail/trampoline_push.hpp new file mode 100644 index 0000000..86cf375 --- /dev/null +++ b/include/boost/coroutine/detail/trampoline_push.hpp @@ -0,0 +1,135 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H +#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace coroutines { +namespace detail { + +template< typename Fn, typename Coro, typename Self > +void trampoline_push( intptr_t vp) +{ + typedef typename Coro::param_type param_type; + + BOOST_ASSERT( vp); + + setup< Fn > * from( + reinterpret_cast< setup< Fn > * >( vp) ); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + Fn fn( forward< Fn >( from->fn) ); +#else + Fn fn( move( from->fn) ); +#endif + Coro c( from->caller, from->callee, + stack_unwind == from->attr.do_unwind, + fpu_preserved == from->attr.preserve_fpu); + from = 0; + + { + param_type * from( + reinterpret_cast< param_type * >( + c.callee_->jump( + * c.caller_, + reinterpret_cast< intptr_t >( & c), + c.preserve_fpu() ) ) ); + BOOST_ASSERT( from->data); + + // create push_coroutine + typename Self::impl_type b( c.callee_, c.caller_, false, c.preserve_fpu(), from->data); + Self self( & b); + try + { fn( self); } + catch ( forced_unwind const&) + {} + catch (...) + { c.except_ = current_exception(); } + } + + c.flags_ |= flag_complete; + param_type to; + c.callee_->jump( + * c.caller_, + reinterpret_cast< intptr_t >( & to), + c.preserve_fpu() ); + BOOST_ASSERT_MSG( false, "push_coroutine is complete"); +} + +template< typename Fn, typename Coro, typename Self > +void trampoline_push_void( intptr_t vp) +{ + typedef typename Coro::param_type param_type; + + BOOST_ASSERT( vp); + + setup< Fn > * from( + reinterpret_cast< setup< Fn > * >( vp) ); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + Fn fn( forward< Fn >( from->fn) ); +#else + Fn fn( move( from->fn) ); +#endif + Coro c( from->caller, from->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 self( & b); + try + { fn( self); } + catch ( forced_unwind const&) + {} + catch (...) + { c.except_ = current_exception(); } + } + + c.flags_ |= flag_complete; + param_type to; + c.callee_->jump( + * c.caller_, + reinterpret_cast< intptr_t >( & to), + c.preserve_fpu() ); + BOOST_ASSERT_MSG( false, "push_coroutine is complete"); +} + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H diff --git a/performance/segmented/Jamfile.v2 b/performance/segmented/Jamfile.v2 index f7eb81f..7cad210 100644 --- a/performance/segmented/Jamfile.v2 +++ b/performance/segmented/Jamfile.v2 @@ -18,14 +18,15 @@ project boost/coroutine/performance/segmented /boost/chrono//boost_chrono /boost/coroutine//boost_coroutine /boost/program_options//boost_program_options - gcc-4.7:-fsplit-stack - gcc-4.7:-DBOOST_USE_SEGMENTED_STACKS - gcc-4.8:-fsplit-stack - gcc-4.8:-DBOOST_USE_SEGMENTED_STACKS on "-lrt" + gcc-4.7,on:-fsplit-stack + gcc-4.7,on:-DBOOST_USE_SEGMENTED_STACKS + gcc-4.8,on:-fsplit-stack + gcc-4.8,on:-DBOOST_USE_SEGMENTED_STACKS + gcc-4.9,on:-fsplit-stack + gcc-4.9,on:-DBOOST_USE_SEGMENTED_STACKS static - multi ; alias sources diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b3e7b09..631e690 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -18,7 +18,11 @@ project boost/coroutine/test ../../test/build//boost_unit_test_framework /boost/coroutine//boost_coroutine gcc-4.7,on:-fsplit-stack + gcc-4.7,on:-DBOOST_USE_SEGMENTED_STACKS gcc-4.8,on:-fsplit-stack + gcc-4.8,on:-DBOOST_USE_SEGMENTED_STACKS + gcc-4.9,on:-fsplit-stack + gcc-4.9,on:-DBOOST_USE_SEGMENTED_STACKS static ;