// 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_ASYMMETRIC_COROUTINE_H #define BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H #include #include #include #include #include #include #include #include #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 { template< typename R > class pull_coroutine; template< typename Arg > class push_coroutine { private: template< typename V, typename X, typename Y, typename Z > friend class detail::pull_coroutine_object; typedef detail::push_coroutine_impl< Arg > impl_type; typedef detail::push_coroutine_synthesized< Arg > synth_type; typedef detail::parameters< Arg > param_type; struct dummy {}; impl_type * impl_; BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine) explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) : impl_( & impl) { BOOST_ASSERT( impl_); } public: push_coroutine() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( pull_coroutine< Arg > &); explicit push_coroutine( coroutine_fn, attributes const& = attributes() ); template< typename StackAllocator > explicit push_coroutine( coroutine_fn, attributes const&, StackAllocator); # endif template< typename Fn > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const&, StackAllocator); #else template< typename Fn > explicit push_coroutine( Fn fn, attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( Fn fn, attributes const&, StackAllocator); template< typename Fn > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const&, StackAllocator); #endif ~push_coroutine() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT { push_coroutine tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete(); } void swap( push_coroutine & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } push_coroutine & operator()( Arg arg) { BOOST_ASSERT( * this); impl_->push( arg); return * this; } class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > { private: push_coroutine< Arg > * c_; public: iterator() : c_( 0) {} explicit iterator( push_coroutine< Arg > * c) : c_( c) {} iterator & operator=( Arg a) { BOOST_ASSERT( c_); if ( ! ( * c_)( a) ) c_ = 0; return * this; } bool operator==( iterator const& other) const { return other.c_ == c_; } bool operator!=( iterator const& other) const { return other.c_ != c_; } iterator & operator*() { return * this; } iterator & operator++() { return * this; } }; struct const_iterator; }; template< typename Arg > class push_coroutine< Arg & > { private: template< typename V, typename X, typename Y, typename Z > friend class detail::pull_coroutine_object; typedef detail::push_coroutine_impl< Arg & > impl_type; typedef detail::push_coroutine_synthesized< Arg & > synth_type; typedef detail::parameters< Arg & > param_type; struct dummy {}; impl_type * impl_; BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine) explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) : impl_( & impl) { BOOST_ASSERT( impl_); } public: push_coroutine() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( pull_coroutine< Arg & > &); explicit push_coroutine( coroutine_fn, attributes const& = attributes() ); template< typename StackAllocator > explicit push_coroutine( coroutine_fn, attributes const&, StackAllocator); # endif template< typename Fn > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const&, StackAllocator); #else template< typename Fn > explicit push_coroutine( Fn, attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( Fn, attributes const&, StackAllocator); template< typename Fn > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const&, StackAllocator); #endif ~push_coroutine() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT { push_coroutine tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete(); } void swap( push_coroutine & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } push_coroutine & operator()( Arg & arg) { BOOST_ASSERT( * this); impl_->push( arg); return * this; } class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > { private: push_coroutine< Arg & > * c_; public: iterator() : c_( 0) {} explicit iterator( push_coroutine< Arg & > * c) : c_( c) {} iterator & operator=( Arg & a) { BOOST_ASSERT( c_); if ( ! ( * c_)( a) ) c_ = 0; return * this; } bool operator==( iterator const& other) const { return other.c_ == c_; } bool operator!=( iterator const& other) const { return other.c_ != c_; } iterator & operator*() { return * this; } iterator & operator++() { return * this; } }; struct const_iterator; }; template<> class push_coroutine< void > { private: template< typename V, typename X, typename Y, typename Z > friend class detail::pull_coroutine_object; typedef detail::push_coroutine_impl< void > impl_type; typedef detail::push_coroutine_synthesized< void > synth_type; typedef detail::parameters< void > param_type; struct dummy {}; impl_type * impl_; BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine) explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) : impl_( & impl) { BOOST_ASSERT( impl_); } public: push_coroutine() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( pull_coroutine< void > &); explicit push_coroutine( coroutine_fn, attributes const& = attributes() ); template< typename StackAllocator > explicit push_coroutine( coroutine_fn, attributes const&, StackAllocator); # endif template< typename Fn > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const&, StackAllocator); #else template< typename Fn > explicit push_coroutine( Fn, attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( Fn, attributes const&, StackAllocator); template< typename Fn > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const& = attributes() ); template< typename Fn, typename StackAllocator > explicit push_coroutine( BOOST_RV_REF( Fn), attributes const&, StackAllocator); #endif ~push_coroutine() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } inline push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } inline push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT { push_coroutine tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); inline bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete(); } inline void swap( push_coroutine & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } inline push_coroutine & operator()() { BOOST_ASSERT( * this); impl_->push(); return * this; } struct iterator; struct const_iterator; }; template< typename R > class pull_coroutine { private: template< typename V, typename X, typename Y, typename Z > friend class detail::push_coroutine_object; typedef detail::pull_coroutine_impl< R > impl_type; typedef detail::pull_coroutine_synthesized< R > synth_type; typedef detail::parameters< R > param_type; struct dummy {}; impl_type * impl_; BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) : impl_( & impl) { BOOST_ASSERT( impl_); } public: pull_coroutine() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( push_coroutine< R > &); explicit pull_coroutine( coroutine_fn fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename StackAllocator > explicit pull_coroutine( coroutine_fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } # endif template< typename Fn > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } #else template< typename Fn > explicit pull_coroutine( Fn fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( Fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R >, R, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } #endif ~pull_coroutine() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT { pull_coroutine tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete(); } void swap( pull_coroutine & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } pull_coroutine & operator()() { BOOST_ASSERT( * this); impl_->pull(); return * this; } R get() const { BOOST_ASSERT( 0 != impl_); return impl_->get(); } class iterator : public std::iterator< std::input_iterator_tag, typename remove_reference< R >::type > { private: pull_coroutine< R > * c_; R * val_; void fetch_() { BOOST_ASSERT( c_); if ( ! ( * c_) ) { c_ = 0; val_ = 0; return; } val_ = c_->impl_->get_pointer(); } void increment_() { BOOST_ASSERT( c_); BOOST_ASSERT( * c_); ( * c_)(); fetch_(); } public: typedef typename iterator::pointer pointer_t; typedef typename iterator::reference reference_t; iterator() : c_( 0), val_( 0) {} explicit iterator( pull_coroutine< R > * c) : c_( c), val_( 0) { fetch_(); } iterator( iterator const& other) : c_( other.c_), val_( other.val_) {} iterator & operator=( iterator const& other) { if ( this == & other) return * this; c_ = other.c_; val_ = other.val_; return * this; } bool operator==( iterator const& other) const { return other.c_ == c_ && other.val_ == val_; } bool operator!=( iterator const& other) const { return other.c_ != c_ || other.val_ != val_; } iterator & operator++() { increment_(); return * this; } iterator operator++( int) { iterator tmp( * this); ++*this; return tmp; } reference_t operator*() const { if ( ! val_) boost::throw_exception( invalid_result() ); return * val_; } pointer_t operator->() const { if ( ! val_) boost::throw_exception( invalid_result() ); return val_; } }; friend class iterator; struct const_iterator; }; template< typename R > class pull_coroutine< R & > { private: template< typename V, typename X, typename Y, typename Z > friend class detail::push_coroutine_object; typedef detail::pull_coroutine_impl< R & > impl_type; typedef detail::pull_coroutine_synthesized< R & > synth_type; typedef detail::parameters< R & > param_type; struct dummy {}; impl_type * impl_; BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) : impl_( & impl) { BOOST_ASSERT( impl_); } public: pull_coroutine() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( push_coroutine< R & > &); explicit pull_coroutine( coroutine_fn fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename StackAllocator > explicit pull_coroutine( coroutine_fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } # endif template< typename Fn > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } #else template< typename Fn > explicit pull_coroutine( Fn fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( Fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< R & >, R &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } #endif ~pull_coroutine() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT { pull_coroutine tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete(); } void swap( pull_coroutine & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } pull_coroutine & operator()() { BOOST_ASSERT( * this); impl_->pull(); return * this; } R & get() const { return impl_->get(); } class iterator : public std::iterator< std::input_iterator_tag, R > { private: pull_coroutine< R & > * c_; R * val_; void fetch_() { BOOST_ASSERT( c_); if ( ! ( * c_) ) { c_ = 0; val_ = 0; return; } val_ = c_->impl_->get_pointer(); } void increment_() { BOOST_ASSERT( c_); BOOST_ASSERT( * c_); ( * c_)(); fetch_(); } public: typedef typename iterator::pointer pointer_t; typedef typename iterator::reference reference_t; iterator() : c_( 0), val_( 0) {} explicit iterator( pull_coroutine< R & > * c) : c_( c), val_( 0) { fetch_(); } iterator( iterator const& other) : c_( other.c_), val_( other.val_) {} iterator & operator=( iterator const& other) { if ( this == & other) return * this; c_ = other.c_; val_ = other.val_; return * this; } bool operator==( iterator const& other) const { return other.c_ == c_ && other.val_ == val_; } bool operator!=( iterator const& other) const { return other.c_ != c_ || other.val_ != val_; } iterator & operator++() { increment_(); return * this; } iterator operator++( int) { iterator tmp( * this); ++*this; return tmp; } reference_t operator*() const { if ( ! val_) boost::throw_exception( invalid_result() ); return * val_; } pointer_t operator->() const { if ( ! val_) boost::throw_exception( invalid_result() ); return val_; } }; friend class iterator; struct const_iterator; }; template<> class pull_coroutine< void > { private: template< typename V, typename X, typename Y, typename Z > friend class detail::push_coroutine_object; typedef detail::pull_coroutine_impl< void > impl_type; typedef detail::pull_coroutine_synthesized< void > synth_type; typedef detail::parameters< void > param_type; struct dummy {}; impl_type * impl_; BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) : impl_( & impl) { BOOST_ASSERT( impl_); } public: pull_coroutine() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( push_coroutine< void > &); explicit pull_coroutine( coroutine_fn fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename StackAllocator > explicit pull_coroutine( coroutine_fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } # endif template< typename Fn > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } #else template< typename Fn > explicit pull_coroutine( Fn fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( Fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes() ) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } template< typename Fn, typename StackAllocator > explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::pull_coroutine_object< push_coroutine< void >, void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); impl_->pull(); } #endif ~pull_coroutine() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } inline pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } inline pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT { pull_coroutine tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); inline bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete(); } inline void swap( pull_coroutine & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } inline pull_coroutine & operator()() { BOOST_ASSERT( * this); impl_->pull(); return * this; } struct iterator; struct const_iterator; }; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC template< typename Arg > push_coroutine< Arg >::push_coroutine( coroutine_fn fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename StackAllocator > push_coroutine< Arg >::push_coroutine( coroutine_fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename StackAllocator > push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } inline push_coroutine< void >::push_coroutine( coroutine_fn fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename StackAllocator > push_coroutine< void >::push_coroutine( coroutine_fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } # endif template< typename Arg > template< typename Fn > push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn, typename StackAllocator > push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn > push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn, typename StackAllocator > push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn > push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } #else template< typename Arg > template< typename Fn > push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn, typename StackAllocator > push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn > push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn, typename StackAllocator > push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn > push_coroutine< void >::push_coroutine( Fn fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > push_coroutine< void >::push_coroutine( Fn fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn > push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn, typename StackAllocator > push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg >, Arg, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn > push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Arg > template< typename Fn, typename StackAllocator > push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< Arg & >, Arg &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn > push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs) : impl_( 0) { // create a stack-context stack_context stack_ctx; stack_allocator stack_alloc; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attrs, StackAllocator stack_alloc) : impl_( 0) { // create a stack-context stack_context stack_ctx; // allocate the coroutine-stack stack_alloc.allocate( stack_ctx, attrs.size); BOOST_ASSERT( 0 < stack_ctx.sp); // typedef of internal coroutine-type typedef detail::push_coroutine_object< pull_coroutine< void >, void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type stack_context internal_stack_ctx; internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.sp); internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 < internal_stack_ctx.size); // placement new for internal coroutine impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); BOOST_ASSERT( impl_); } #endif template< typename R > void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT { l.swap( r); } template< typename Arg > void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT { l.swap( r); } template< typename R > typename pull_coroutine< R >::iterator range_begin( pull_coroutine< R > & c) { return typename pull_coroutine< R >::iterator( & c); } template< typename R > typename pull_coroutine< R >::iterator range_end( pull_coroutine< R > &) { return typename pull_coroutine< R >::iterator(); } template< typename Arg > typename push_coroutine< Arg >::iterator range_begin( push_coroutine< Arg > & c) { return typename push_coroutine< Arg >::iterator( & c); } template< typename Arg > typename push_coroutine< Arg >::iterator range_end( push_coroutine< Arg > &) { return typename push_coroutine< Arg >::iterator(); } template< typename T > struct asymmetric_coroutine { typedef push_coroutine< T > push_type; typedef pull_coroutine< T > pull_type; }; // deprecated template< typename T > struct coroutine { typedef push_coroutine< T > push_type; typedef pull_coroutine< T > pull_type; }; template< typename R > typename pull_coroutine< R >::iterator begin( pull_coroutine< R > & c) { return boost::begin( c); } template< typename R > typename pull_coroutine< R >::iterator end( pull_coroutine< R > & c) { return boost::end( c); } template< typename R > typename push_coroutine< R >::iterator begin( push_coroutine< R > & c) { return boost::begin( c); } template< typename R > typename push_coroutine< R >::iterator end( push_coroutine< R > & c) { return boost::end( c); } } template< typename Arg > struct range_mutable_iterator< coroutines::push_coroutine< Arg > > { typedef typename coroutines::push_coroutine< Arg >::iterator type; }; template< typename R > struct range_mutable_iterator< coroutines::pull_coroutine< R > > { typedef typename coroutines::pull_coroutine< R >::iterator type; }; } #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H