?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/coroutine.zip
???????
PK ��!\E$�ZG ZG asymmetric_coroutine.hppnu �[��� // 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 <cstddef> #include <iterator> #include <memory> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/move/move.hpp> #include <boost/throw_exception.hpp> #include <boost/utility/explicit_operator_bool.hpp> #include <boost/coroutine/attributes.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/detail/coroutine_context.hpp> #include <boost/coroutine/detail/parameters.hpp> #include <boost/coroutine/exceptions.hpp> #include <boost/coroutine/stack_allocator.hpp> #include <boost/coroutine/detail/pull_coroutine_impl.hpp> #include <boost/coroutine/detail/pull_coroutine_object.hpp> #include <boost/coroutine/detail/pull_coroutine_synthesized.hpp> #include <boost/coroutine/detail/push_coroutine_impl.hpp> #include <boost/coroutine/detail/push_coroutine_object.hpp> #include <boost/coroutine/detail/push_coroutine_synthesized.hpp> #include <boost/coroutine/stack_context.hpp> #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 { private: push_coroutine< Arg > * c_; public: typedef std::output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; 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 { private: push_coroutine< Arg & > * c_; public: typedef std::output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 { 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 std::input_iterator_tag iterator_category; typedef typename remove_reference< R >::type value_type; typedef std::ptrdiff_t difference_type; typedef value_type * pointer; typedef value_type & reference; typedef pointer pointer_t; typedef 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); 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_; } }; class const_iterator { 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 std::input_iterator_tag iterator_category; typedef const typename remove_reference< R >::type value_type; typedef std::ptrdiff_t difference_type; typedef value_type * pointer; typedef value_type & reference; typedef pointer pointer_t; typedef reference reference_t; const_iterator() : c_( 0), val_( 0) {} explicit const_iterator( pull_coroutine< R > const* c) : c_( const_cast< pull_coroutine< R > * >( c) ), val_( 0) { fetch_(); } const_iterator( const_iterator const& other) : c_( other.c_), val_( other.val_) {} const_iterator & operator=( const_iterator const& other) { if ( this == & other) return * this; c_ = other.c_; val_ = other.val_; return * this; } bool operator==( const_iterator const& other) const { return other.c_ == c_ && other.val_ == val_; } bool operator!=( const_iterator const& other) const { return other.c_ != c_ || other.val_ != val_; } const_iterator & operator++() { increment_(); return * this; } const_iterator operator++( int); 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; friend class 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 { 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 std::input_iterator_tag iterator_category; typedef typename remove_reference< R >::type value_type; typedef std::ptrdiff_t difference_type; typedef value_type * pointer; typedef value_type & reference; typedef pointer pointer_t; typedef 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); 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_; } }; class const_iterator { 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 std::input_iterator_tag iterator_category; typedef const typename remove_reference< R >::type value_type; typedef std::ptrdiff_t difference_type; typedef value_type * pointer; typedef value_type & reference; typedef pointer pointer_t; typedef reference reference_t; const_iterator() : c_( 0), val_( 0) {} explicit const_iterator( pull_coroutine< R & > const* c) : c_( const_cast< pull_coroutine< R & > * >( c) ), val_( 0) { fetch_(); } const_iterator( const_iterator const& other) : c_( other.c_), val_( other.val_) {} const_iterator & operator=( const_iterator const& other) { if ( this == & other) return * this; c_ = other.c_; val_ = other.val_; return * this; } bool operator==( const_iterator const& other) const { return other.c_ == c_ && other.val_ == val_; } bool operator!=( const_iterator const& other) const { return other.c_ != c_ || other.val_ != val_; } const_iterator & operator++() { increment_(); return * this; } const_iterator operator++( int); 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; friend class 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, detail::preallocated( sp, size, 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 >::const_iterator range_begin( pull_coroutine< R > const& c) { return typename pull_coroutine< R >::const_iterator( & c); } template< typename R > typename pull_coroutine< R >::iterator range_end( pull_coroutine< R > &) { return typename pull_coroutine< R >::iterator(); } template< typename R > typename pull_coroutine< R >::const_iterator range_end( pull_coroutine< R > const&) { return typename pull_coroutine< R >::const_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 coroutines::range_begin( c); } template< typename R > typename pull_coroutine< R >::const_iterator begin( pull_coroutine< R > const& c) { return coroutines::range_begin( c); } template< typename R > typename pull_coroutine< R >::iterator end( pull_coroutine< R > & c) { return coroutines::range_end( c); } template< typename R > typename pull_coroutine< R >::const_iterator end( pull_coroutine< R > const& c) { return coroutines::range_end( c); } template< typename R > typename push_coroutine< R >::iterator begin( push_coroutine< R > & c) { return coroutines::range_begin( c); } template< typename R > typename push_coroutine< R >::iterator end( push_coroutine< R > & c) { return coroutines::range_end( c); } } // forward declaration of Boost.Range traits to break dependency on it template<typename C, typename Enabler> struct range_mutable_iterator; template<typename C, typename Enabler> struct range_const_iterator; template< typename Arg > struct range_mutable_iterator< coroutines::push_coroutine< Arg >, void > { typedef typename coroutines::push_coroutine< Arg >::iterator type; }; template< typename R > struct range_mutable_iterator< coroutines::pull_coroutine< R >, void > { typedef typename coroutines::pull_coroutine< R >::iterator type; }; } #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H PK ��!\)̉�i i symmetric_coroutine.hppnu �[��� // 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_SYMMETRIC_COROUTINE_H #define BOOST_COROUTINES_SYMMETRIC_COROUTINE_H #include <boost/config.hpp> #include <boost/coroutine/detail/symmetric_coroutine_call.hpp> #include <boost/coroutine/detail/symmetric_coroutine_yield.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { template< typename T > struct symmetric_coroutine { typedef detail::symmetric_coroutine_call< T > call_type; typedef detail::symmetric_coroutine_yield< T > yield_type; }; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_SYMMETRIC_COROUTINE_H PK ��!\�o�� � coroutine.hppnu �[��� // 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_COROUTINE_H #define BOOST_COROUTINES_COROUTINE_H #include <boost/coroutine/asymmetric_coroutine.hpp> #include <boost/coroutine/symmetric_coroutine.hpp> #endif // BOOST_COROUTINES_COROUTINE_H PK ��!\���� � stack_traits.hppnu �[��� // 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_STACK_TRAITS_H #define BOOST_COROUTINES_STACK_TRAITS_H #include <cstddef> #include <boost/config.hpp> #include <boost/coroutine/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { struct BOOST_COROUTINES_DECL stack_traits { static bool is_unbounded() BOOST_NOEXCEPT; static std::size_t page_size() BOOST_NOEXCEPT; static std::size_t default_size() BOOST_NOEXCEPT; static std::size_t minimum_size() BOOST_NOEXCEPT; static std::size_t maximum_size() BOOST_NOEXCEPT; }; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_STACK_TRAITS_H PK ��!\e���+ + attributes.hppnu �[��� // 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_ATTRIBUTES_H #define BOOST_COROUTINES_ATTRIBUTES_H #include <cstddef> #include <boost/config.hpp> #include <boost/coroutine/flags.hpp> #include <boost/coroutine/stack_allocator.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { struct attributes { std::size_t size; flag_unwind_t do_unwind; attributes() BOOST_NOEXCEPT : size( stack_allocator::traits_type::default_size() ), do_unwind( stack_unwind) {} explicit attributes( std::size_t size_) BOOST_NOEXCEPT : size( size_), do_unwind( stack_unwind) {} explicit attributes( flag_unwind_t do_unwind_) BOOST_NOEXCEPT : size( stack_allocator::traits_type::default_size() ), do_unwind( do_unwind_) {} explicit attributes( std::size_t size_, flag_unwind_t do_unwind_) BOOST_NOEXCEPT : size( size_), do_unwind( do_unwind_) {} }; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_ATTRIBUTES_H PK ��!\��:T{ { exceptions.hppnu �[��� // 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_EXCEPTIONS_H #define BOOST_COROUTINES_EXCEPTIONS_H #include <stdexcept> #include <string> #include <boost/config.hpp> #include <boost/core/scoped_enum.hpp> #include <boost/system/error_code.hpp> #include <boost/system/system_error.hpp> #include <boost/type_traits/integral_constant.hpp> #include <boost/coroutine/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { namespace detail { struct forced_unwind {}; } BOOST_SCOPED_ENUM_DECLARE_BEGIN(coroutine_errc) { no_data = 1 } BOOST_SCOPED_ENUM_DECLARE_END(coroutine_errc) BOOST_COROUTINES_DECL system::error_category const& coroutine_category() BOOST_NOEXCEPT; } namespace system { template<> struct is_error_code_enum< coroutines::coroutine_errc > : public true_type {}; #ifdef BOOST_NO_CXX11_SCOPED_ENUMS template<> struct is_error_code_enum< coroutines::coroutine_errc::enum_type > : public true_type {}; #endif inline error_code make_error_code( coroutines::coroutine_errc e) //BOOST_NOEXCEPT { return error_code( underlying_cast< int >( e), coroutines::coroutine_category() ); } inline error_condition make_error_condition( coroutines::coroutine_errc e) //BOOST_NOEXCEPT { return error_condition( underlying_cast< int >( e), coroutines::coroutine_category() ); } } namespace coroutines { class coroutine_error : public std::logic_error { private: system::error_code ec_; public: coroutine_error( system::error_code ec) : logic_error( ec.message() ), ec_( ec) {} system::error_code const& code() const BOOST_NOEXCEPT { return ec_; } }; class invalid_result : public coroutine_error { public: invalid_result() : coroutine_error( system::make_error_code( coroutine_errc::no_data) ) {} }; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_EXCEPTIONS_H PK ��!\܇�w w stack_allocator.hppnu �[��� // 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_STACK_ALLOCATOR_H #define BOOST_COROUTINES_STACK_ALLOCATOR_H #include <cstddef> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #include <boost/coroutine/segmented_stack_allocator.hpp> #include <boost/coroutine/standard_stack_allocator.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { #if defined(BOOST_USE_SEGMENTED_STACKS) typedef segmented_stack_allocator stack_allocator; #else typedef standard_stack_allocator stack_allocator; #endif }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_STACK_ALLOCATOR_H PK ��!\"/� all.hppnu �[��� // 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_ALL_H #define BOOST_COROUTINES_ALL_H #include <boost/coroutine/attributes.hpp> #include <boost/coroutine/coroutine.hpp> #include <boost/coroutine/exceptions.hpp> #include <boost/coroutine/flags.hpp> #include <boost/coroutine/protected_stack_allocator.hpp> #include <boost/coroutine/segmented_stack_allocator.hpp> #include <boost/coroutine/stack_allocator.hpp> #include <boost/coroutine/stack_context.hpp> #include <boost/coroutine/stack_traits.hpp> #include <boost/coroutine/standard_stack_allocator.hpp> #endif // BOOST_COROUTINES_ALL_H PK ��!\���%� � standard_stack_allocator.hppnu �[��� // 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_STANDARD_STACK_ALLOCATOR_H #define BOOST_COROUTINES_STANDARD_STACK_ALLOCATOR_H #if defined(BOOST_USE_VALGRIND) #include <valgrind/valgrind.h> #endif #include <cstddef> #include <cstdlib> #include <new> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/stack_context.hpp> #include <boost/coroutine/stack_traits.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { template< typename traitsT > struct basic_standard_stack_allocator { typedef traitsT traits_type; void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() ) { BOOST_ASSERT( traits_type::minimum_size() <= size); BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) ); void * limit = std::malloc( size); if ( ! limit) throw std::bad_alloc(); ctx.size = size; ctx.sp = static_cast< char * >( limit) + ctx.size; #if defined(BOOST_USE_VALGRIND) ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( ctx.sp, limit); #endif } void deallocate( stack_context & ctx) { BOOST_ASSERT( ctx.sp); BOOST_ASSERT( traits_type::minimum_size() <= ctx.size); BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) ); #if defined(BOOST_USE_VALGRIND) VALGRIND_STACK_DEREGISTER( ctx.valgrind_stack_id); #endif void * limit = static_cast< char * >( ctx.sp) - ctx.size; std::free( limit); } }; typedef basic_standard_stack_allocator< stack_traits > standard_stack_allocator; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_STANDARD_STACK_ALLOCATOR_H PK ��!\0~j� � # posix/segmented_stack_allocator.hppnu �[��� // 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_SEGMENTED_STACK_ALLOCATOR_H #define BOOST_COROUTINES_SEGMENTED_STACK_ALLOCATOR_H #include <cstddef> #include <new> #include <boost/config.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/stack_context.hpp> #include <boost/coroutine/stack_traits.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif // forward declaration for splitstack-functions defined in libgcc extern "C" { void *__splitstack_makecontext( std::size_t, void * [BOOST_CONTEXT_SEGMENTS], std::size_t *); void __splitstack_releasecontext( void * [BOOST_CONTEXT_SEGMENTS]); void __splitstack_resetcontext( void * [BOOST_CONTEXT_SEGMENTS]); void __splitstack_block_signals_context( void * [BOOST_CONTEXT_SEGMENTS], int * new_value, int * old_value); } namespace boost { namespace coroutines { template< typename traitsT > struct basic_segmented_stack_allocator { typedef traitsT traits_type; void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() ) { void * limit = __splitstack_makecontext( size, ctx.segments_ctx, & ctx.size); if ( ! limit) throw std::bad_alloc(); // ctx.size is already filled by __splitstack_makecontext ctx.sp = static_cast< char * >( limit) + ctx.size; int off = 0; __splitstack_block_signals_context( ctx.segments_ctx, & off, 0); } void deallocate( stack_context & ctx) { __splitstack_releasecontext( ctx.segments_ctx); } }; typedef basic_segmented_stack_allocator< stack_traits > segmented_stack_allocator; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_SEGMENTED_STACK_ALLOCATOR_H PK ��!\s�� � # posix/protected_stack_allocator.hppnu �[��� // 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_PROTECTED_STACK_ALLOCATOR_H #define BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H extern "C" { #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> } #if defined(BOOST_USE_VALGRIND) #include <valgrind/valgrind.h> #endif #include <cmath> #include <cstddef> #include <new> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/stack_context.hpp> #include <boost/coroutine/stack_traits.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { template< typename traitsT > struct basic_protected_stack_allocator { typedef traitsT traits_type; void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() ) { BOOST_ASSERT( traits_type::minimum_size() <= size); BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) ); // page at bottom will be used as guard-page const std::size_t pages( static_cast< std::size_t >( std::floor( static_cast< float >( size) / traits_type::page_size() ) ) ); BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)"); const std::size_t size_( pages * traits_type::page_size() ); BOOST_ASSERT( 0 != size && 0 != size_); BOOST_ASSERT( size_ <= size); // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L) #if defined(MAP_ANON) void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); #else void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif if ( MAP_FAILED == limit) throw std::bad_alloc(); // conforming to POSIX.1-2001 #if defined(BOOST_DISABLE_ASSERTS) ::mprotect( limit, traits_type::page_size(), PROT_NONE); #else const int result( ::mprotect( limit, traits_type::page_size(), PROT_NONE) ); BOOST_ASSERT( 0 == result); #endif ctx.size = size_; ctx.sp = static_cast< char * >( limit) + ctx.size; #if defined(BOOST_USE_VALGRIND) ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( ctx.sp, limit); #endif } void deallocate( stack_context & ctx) { BOOST_ASSERT( ctx.sp); BOOST_ASSERT( traits_type::minimum_size() <= ctx.size); BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) ); #if defined(BOOST_USE_VALGRIND) VALGRIND_STACK_DEREGISTER( ctx.valgrind_stack_id); #endif void * limit = static_cast< char * >( ctx.sp) - ctx.size; // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L) ::munmap( limit, ctx.size); } }; typedef basic_protected_stack_allocator< stack_traits > protected_stack_allocator; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H PK ��!\D�l� � flags.hppnu �[��� // 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_FLAGS_H #define BOOST_COROUTINES_FLAGS_H namespace boost { namespace coroutines { enum flag_unwind_t { stack_unwind = 0, no_stack_unwind }; }} #endif // BOOST_COROUTINES_FLAGS_H PK ��!\�섻 % detail/symmetric_coroutine_object.hppnu �[��� // 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_SYMMETRIC_COROUTINE_OBJECT_H #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/move/move.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/detail/flags.hpp> #include <boost/coroutine/detail/preallocated.hpp> #include <boost/coroutine/detail/symmetric_coroutine_impl.hpp> #include <boost/coroutine/detail/symmetric_coroutine_yield.hpp> #include <boost/coroutine/exceptions.hpp> #include <boost/coroutine/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { struct stack_context; namespace detail { template< typename R, typename Fn, typename StackAllocator > class symmetric_coroutine_object : public symmetric_coroutine_impl< R > { private: typedef symmetric_coroutine_impl< R > impl_t; typedef symmetric_coroutine_object< R, Fn, StackAllocator > obj_t; Fn fn_; stack_context stack_ctx_; StackAllocator stack_alloc_; static void deallocate_( obj_t * obj) { stack_context stack_ctx( obj->stack_ctx_); StackAllocator stack_alloc( obj->stack_alloc_); obj->unwind_stack(); obj->~obj_t(); stack_alloc.deallocate( stack_ctx); } public: #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES symmetric_coroutine_object( Fn fn, attributes const& attrs, preallocated const& palloc, StackAllocator const& stack_alloc) BOOST_NOEXCEPT : impl_t( palloc, stack_unwind == attrs.do_unwind), fn_( fn), stack_ctx_( palloc.sctx), stack_alloc_( stack_alloc) {} #endif symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs, preallocated const& palloc, StackAllocator const& stack_alloc) BOOST_NOEXCEPT : impl_t( palloc, stack_unwind == attrs.do_unwind), #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES fn_( fn), #else fn_( boost::forward< Fn >( fn) ), #endif stack_ctx_( palloc.sctx), stack_alloc_( stack_alloc) {} void run( R * r) BOOST_NOEXCEPT { BOOST_ASSERT( ! impl_t::unwind_requested() ); impl_t::flags_ |= flag_started; impl_t::flags_ |= flag_running; try { symmetric_coroutine_yield< R > yc( this, r); fn_( yc); } catch ( forced_unwind const&) {} catch (...) { std::terminate(); } impl_t::flags_ |= flag_complete; impl_t::flags_ &= ~flag_running; typename impl_t::param_type to; impl_t::callee_.jump( impl_t::caller_, & to); BOOST_ASSERT_MSG( false, "coroutine is complete"); } void destroy() { deallocate_( this); } }; template< typename R, typename Fn, typename StackAllocator > class symmetric_coroutine_object< R &, Fn, StackAllocator > : public symmetric_coroutine_impl< R & > { private: typedef symmetric_coroutine_impl< R & > impl_t; typedef symmetric_coroutine_object< R &, Fn, StackAllocator > obj_t; Fn fn_; stack_context stack_ctx_; StackAllocator stack_alloc_; static void deallocate_( obj_t * obj) { stack_context stack_ctx( obj->stack_ctx_); StackAllocator stack_alloc( obj->stack_alloc_); obj->unwind_stack(); obj->~obj_t(); stack_alloc.deallocate( stack_ctx); } public: #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES symmetric_coroutine_object( Fn fn, attributes const& attrs, preallocated const& palloc, StackAllocator const& stack_alloc) BOOST_NOEXCEPT : impl_t( palloc, stack_unwind == attrs.do_unwind), fn_( fn), stack_ctx_( palloc.sctx), stack_alloc_( stack_alloc) {} #endif symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs, preallocated const& palloc, StackAllocator const& stack_alloc) BOOST_NOEXCEPT : impl_t( palloc, stack_unwind == attrs.do_unwind), #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES fn_( fn), #else fn_( boost::forward< Fn >( fn) ), #endif stack_ctx_( palloc.sctx), stack_alloc_( stack_alloc) {} void run( R * r) BOOST_NOEXCEPT { BOOST_ASSERT( ! impl_t::unwind_requested() ); impl_t::flags_ |= flag_started; impl_t::flags_ |= flag_running; try { symmetric_coroutine_yield< R & > yc( this, r); fn_( yc); } catch ( forced_unwind const&) {} catch (...) { std::terminate(); } impl_t::flags_ |= flag_complete; impl_t::flags_ &= ~flag_running; typename impl_t::param_type to; impl_t::callee_.jump( impl_t::caller_, & to); BOOST_ASSERT_MSG( false, "coroutine is complete"); } void destroy() { deallocate_( this); } }; template< typename Fn, typename StackAllocator > class symmetric_coroutine_object< void, Fn, StackAllocator > : public symmetric_coroutine_impl< void > { private: typedef symmetric_coroutine_impl< void > impl_t; typedef symmetric_coroutine_object< void, Fn, StackAllocator > obj_t; Fn fn_; stack_context stack_ctx_; StackAllocator stack_alloc_; static void deallocate_( obj_t * obj) { stack_context stack_ctx( obj->stack_ctx_); StackAllocator stack_alloc( obj->stack_alloc_); obj->unwind_stack(); obj->~obj_t(); stack_alloc.deallocate( stack_ctx); } public: #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES symmetric_coroutine_object( Fn fn, attributes const& attrs, preallocated const& palloc, StackAllocator const& stack_alloc) BOOST_NOEXCEPT : impl_t( palloc, stack_unwind == attrs.do_unwind), fn_( fn), stack_ctx_( palloc.sctx), stack_alloc_( stack_alloc) {} #endif symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs, preallocated const& palloc, StackAllocator const& stack_alloc) BOOST_NOEXCEPT : impl_t( palloc, stack_unwind == attrs.do_unwind), #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES fn_( fn), #else fn_( boost::forward< Fn >( fn) ), #endif stack_ctx_( palloc.sctx), stack_alloc_( stack_alloc) {} void run() BOOST_NOEXCEPT { BOOST_ASSERT( ! impl_t::unwind_requested() ); impl_t::flags_ |= flag_started; impl_t::flags_ |= flag_running; try { symmetric_coroutine_yield< void > yc( this); fn_( yc); } catch ( forced_unwind const&) {} catch (...) { std::terminate(); } impl_t::flags_ |= flag_complete; impl_t::flags_ &= ~flag_running; typename impl_t::param_type to; impl_t::callee_.jump( impl_t::caller_, & to); BOOST_ASSERT_MSG( false, "coroutine is complete"); } void destroy() { deallocate_( this); } }; }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H PK ��!\M�� # detail/symmetric_coroutine_call.hppnu �[��� // 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_SYMMETRIC_COROUTINE_CALL_H #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/move/move.hpp> #include <boost/utility/explicit_operator_bool.hpp> #include <boost/coroutine/attributes.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/detail/preallocated.hpp> #include <boost/coroutine/detail/symmetric_coroutine_impl.hpp> #include <boost/coroutine/detail/symmetric_coroutine_object.hpp> #include <boost/coroutine/detail/symmetric_coroutine_yield.hpp> #include <boost/coroutine/stack_allocator.hpp> #include <boost/coroutine/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { namespace detail { template< typename Arg > class symmetric_coroutine_call { private: template< typename X > friend class symmetric_coroutine_yield; typedef symmetric_coroutine_impl< Arg > impl_type; BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call) struct dummy {}; impl_type * impl_; public: typedef Arg value_type; typedef symmetric_coroutine_yield< Arg > yield_type; symmetric_coroutine_call() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( yield_type &); explicit symmetric_coroutine_call( coroutine_fn fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } # endif template< typename Fn > explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } #else template< typename Fn > explicit symmetric_coroutine_call( Fn fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn > explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } #endif ~symmetric_coroutine_call() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT { symmetric_coroutine_call tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } symmetric_coroutine_call & operator()( Arg arg) BOOST_NOEXCEPT { BOOST_ASSERT( * this); impl_->resume( arg); return * this; } }; template< typename Arg > class symmetric_coroutine_call< Arg & > { private: template< typename X > friend class symmetric_coroutine_yield; typedef symmetric_coroutine_impl< Arg & > impl_type; BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call) struct dummy {}; impl_type * impl_; public: typedef Arg value_type; typedef symmetric_coroutine_yield< Arg & > yield_type; symmetric_coroutine_call() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( yield_type &); explicit symmetric_coroutine_call( coroutine_fn fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg &, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg &, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } # endif template< typename Fn > explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } #else template< typename Fn > explicit symmetric_coroutine_call( Fn fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn > explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } #endif ~symmetric_coroutine_call() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT { symmetric_coroutine_call tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } symmetric_coroutine_call & operator()( Arg & arg) BOOST_NOEXCEPT { BOOST_ASSERT( * this); impl_->resume( arg); return * this; } }; template<> class symmetric_coroutine_call< void > { private: template< typename X > friend class symmetric_coroutine_yield; typedef symmetric_coroutine_impl< void > impl_type; BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call) struct dummy {}; impl_type * impl_; public: typedef void value_type; typedef symmetric_coroutine_yield< void > yield_type; symmetric_coroutine_call() BOOST_NOEXCEPT : impl_( 0) {} #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # ifdef BOOST_MSVC typedef void ( * coroutine_fn)( yield_type &); explicit symmetric_coroutine_call( coroutine_fn fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< void, coroutine_fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< void, coroutine_fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } # endif template< typename Fn > explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } #else template< typename Fn > explicit symmetric_coroutine_call( Fn fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn > explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, attributes const& attrs = attributes(), stack_allocator stack_alloc = stack_allocator() ) : 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 symmetric_coroutine_object< void, Fn, stack_allocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } template< typename Fn, typename StackAllocator > explicit symmetric_coroutine_call( 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 symmetric_coroutine_object< void, Fn, StackAllocator > object_t; // reserve space on top of coroutine-stack for internal coroutine-type std::size_t size = stack_ctx.size - sizeof( object_t); BOOST_ASSERT( 0 != size); void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); BOOST_ASSERT( 0 != sp); // placement new for internal coroutine impl_ = new ( sp) object_t( fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc); BOOST_ASSERT( impl_); } #endif ~symmetric_coroutine_call() { if ( 0 != impl_) { impl_->destroy(); impl_ = 0; } } inline symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } inline symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT { symmetric_coroutine_call tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); inline bool operator!() const BOOST_NOEXCEPT { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } inline void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } inline symmetric_coroutine_call & operator()() BOOST_NOEXCEPT { BOOST_ASSERT( * this); impl_->resume(); return * this; } }; template< typename Arg > void swap( symmetric_coroutine_call< Arg > & l, symmetric_coroutine_call< Arg > & r) { l.swap( r); } }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H PK ��!\�47�; ; detail/coroutine_context.hppnu �[��� // 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_COROUTINE_CONTEXT_H #define BOOST_COROUTINES_DETAIL_COROUTINE_CONTEXT_H #include <cstddef> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/detail/fcontext.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/detail/preallocated.hpp> #include <boost/coroutine/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { namespace detail { // class hold stack-context and coroutines execution-context class BOOST_COROUTINES_DECL coroutine_context { private: template< typename Coro > friend void trampoline( context::detail::transfer_t); template< typename Coro > friend void trampoline_void( context::detail::transfer_t); template< typename Coro > friend void trampoline_pull( context::detail::transfer_t); template< typename Coro > friend void trampoline_push( context::detail::transfer_t); template< typename Coro > friend void trampoline_push_void( context::detail::transfer_t); preallocated palloc_; context::detail::fcontext_t ctx_; public: typedef void( * ctx_fn)( context::detail::transfer_t); // default ctor represents the current execution-context coroutine_context(); // ctor creates a new execution-context running coroutine-fn `fn` // `ctx_` will be allocated on top of the stack managed by parameter // `stack_ctx` coroutine_context( ctx_fn fn, preallocated const& palloc); coroutine_context( coroutine_context const&); coroutine_context& operator=( coroutine_context const&); void * jump( coroutine_context &, void * = 0); stack_context & stack_ctx() { return palloc_.sctx; } }; }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_DETAIL_COROUTINE_CONTEXT_H PK ��!\ߝ�� � detail/data.hppnu �[��� // 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_DATA_H #define BOOST_COROUTINES_DETAIL_DATA_H #include <boost/config.hpp> #include <boost/coroutine/detail/coroutine_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { namespace detail { struct data_t { coroutine_context * from; void * data; }; }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_DETAIL_DATA_H PK ��!\H] �! ! $ detail/symmetric_coroutine_yield.hppnu �[��� // 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_SYMMETRIC_COROUTINE_YIELD_H #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H #include <algorithm> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/move/move.hpp> #include <boost/throw_exception.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/utility/enable_if.hpp> #include <boost/utility/explicit_operator_bool.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/exceptions.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { namespace detail { template< typename R > class symmetric_coroutine_yield { private: template< typename X, typename Y, typename Z > friend class symmetric_coroutine_object; typedef symmetric_coroutine_impl< R > impl_type; struct dummy {}; BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield) impl_type * impl_; R * result_; symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT : impl_( impl), result_( result) { BOOST_ASSERT( 0 != impl_); BOOST_ASSERT( 0 != result_); } public: symmetric_coroutine_yield() BOOST_NOEXCEPT : impl_( 0), result_( 0) {} symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT : impl_( 0), result_( 0) { swap( other); } symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT { symmetric_coroutine_yield tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_; } void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); std::swap( result_, other.result_); } symmetric_coroutine_yield & operator()() { result_ = impl_->yield(); return * this; } template< typename Coro > symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type x, typename disable_if< is_same< typename Coro::value_type, void >, dummy* >::type = 0) { BOOST_ASSERT( other); result_ = impl_->yield_to( other.impl_, x); return * this; } template< typename Coro > symmetric_coroutine_yield & operator()( Coro & other, typename enable_if< is_same< typename Coro::value_type, void >, dummy* >::type = 0) { BOOST_ASSERT( other); result_ = impl_->yield_to( other.impl_); return * this; } R get() const { if ( 0 == result_) boost::throw_exception( invalid_result() ); return * result_; } }; template< typename R > class symmetric_coroutine_yield< R & > { private: template< typename X, typename Y, typename Z > friend class symmetric_coroutine_object; typedef symmetric_coroutine_impl< R & > impl_type; struct dummy {}; BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield) impl_type * impl_; R * result_; symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT : impl_( impl), result_( result) { BOOST_ASSERT( 0 != impl_); BOOST_ASSERT( 0 != result_); } public: symmetric_coroutine_yield() BOOST_NOEXCEPT : impl_( 0), result_( 0) {} symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT : impl_( 0), result_( 0) { swap( other); } symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT { symmetric_coroutine_yield tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT { return 0 == impl_; } void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); std::swap( result_, other.result_); } symmetric_coroutine_yield & operator()() { result_ = impl_->yield(); return * this; } template< typename Coro > symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x, typename disable_if< is_same< typename Coro::value_type, void >, dummy* >::type = 0) { BOOST_ASSERT( other); result_ = impl_->yield_to( other.impl_, x); return * this; } template< typename Coro > symmetric_coroutine_yield & operator()( Coro & other, typename enable_if< is_same< typename Coro::value_type, void >, dummy* >::type = 0) { BOOST_ASSERT( other); result_ = impl_->yield_to( other.impl_); return * this; } R & get() const { if ( 0 == result_) boost::throw_exception( invalid_result() ); return * result_; } }; template<> class symmetric_coroutine_yield< void > { private: template< typename X, typename Y, typename Z > friend class symmetric_coroutine_object; typedef symmetric_coroutine_impl< void > impl_type; struct dummy {}; BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield) impl_type * impl_; symmetric_coroutine_yield( impl_type * impl) BOOST_NOEXCEPT : impl_( impl) { BOOST_ASSERT( 0 != impl_); } public: symmetric_coroutine_yield() BOOST_NOEXCEPT : impl_( 0) {} symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT : impl_( 0) { swap( other); } symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT { symmetric_coroutine_yield tmp( boost::move( other) ); swap( tmp); return * this; } BOOST_EXPLICIT_OPERATOR_BOOL(); inline bool operator!() const BOOST_NOEXCEPT { return 0 == impl_; } inline void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT { std::swap( impl_, other.impl_); } inline symmetric_coroutine_yield & operator()() { impl_->yield(); return * this; } template< typename Coro > symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x, typename disable_if< is_same< typename Coro::value_type, void >, dummy* >::type = 0) { BOOST_ASSERT( other); impl_->yield_to( other.impl_, x); return * this; } template< typename Coro > symmetric_coroutine_yield & operator()( Coro & other, typename enable_if< is_same< typename Coro::value_type, void >, dummy* >::type = 0) { BOOST_ASSERT( other); impl_->yield_to( other.impl_); return * this; } }; template< typename R > void swap( symmetric_coroutine_yield< R > & l, symmetric_coroutine_yield< R > & r) { l.swap( r); } }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H PK ��!\��.�0 �0 # detail/symmetric_coroutine_impl.hppnu �[��� // 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_SYMMETRIC_COROUTINE_IMPL_H #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/cstdint.hpp> #include <boost/utility.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/detail/coroutine_context.hpp> #include <boost/coroutine/detail/flags.hpp> #include <boost/coroutine/detail/parameters.hpp> #include <boost/coroutine/detail/preallocated.hpp> #include <boost/coroutine/detail/trampoline.hpp> #include <boost/coroutine/exceptions.hpp> #include <boost/coroutine/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { namespace detail { template< typename R > class symmetric_coroutine_impl : private noncopyable { public: typedef parameters< R > param_type; symmetric_coroutine_impl( preallocated const& palloc, bool unwind) BOOST_NOEXCEPT : flags_( 0), caller_(), callee_( trampoline< symmetric_coroutine_impl< R > >, palloc) { if ( unwind) flags_ |= flag_force_unwind; } virtual ~symmetric_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_force_unwind); } bool unwind_requested() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_unwind_stack); } bool is_started() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_started); } bool is_running() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_running); } bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } void unwind_stack() BOOST_NOEXCEPT { if ( is_started() && ! is_complete() && force_unwind() ) { flags_ |= flag_unwind_stack; flags_ |= flag_running; param_type to( unwind_t::force_unwind); caller_.jump( callee_, & to); flags_ &= ~flag_running; flags_ &= ~flag_unwind_stack; BOOST_ASSERT( is_complete() ); } } void resume( R r) BOOST_NOEXCEPT { param_type to( const_cast< R * >( & r), this); resume_( & to); } R * yield() { BOOST_ASSERT( is_running() ); BOOST_ASSERT( ! is_complete() ); flags_ &= ~flag_running; param_type to; param_type * from( static_cast< param_type * >( callee_.jump( caller_, & to) ) ); flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; } template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other, X x) { typename symmetric_coroutine_impl< X >::param_type to( & x, other); return yield_to_( other, & to); } template< typename X > R * yield_to( symmetric_coroutine_impl< X & > * other, X & x) { typename symmetric_coroutine_impl< X & >::param_type to( & x, other); return yield_to_( other, & to); } template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other) { typename symmetric_coroutine_impl< X >::param_type to( other); return yield_to_( other, & to); } virtual void run( R *) BOOST_NOEXCEPT = 0; virtual void destroy() = 0; protected: template< typename X > friend class symmetric_coroutine_impl; int flags_; coroutine_context caller_; coroutine_context callee_; void resume_( param_type * to) BOOST_NOEXCEPT { BOOST_ASSERT( ! is_running() ); BOOST_ASSERT( ! is_complete() ); flags_ |= flag_running; caller_.jump( callee_, to); flags_ &= ~flag_running; } template< typename Other > R * yield_to_( Other * other, typename Other::param_type * to) { BOOST_ASSERT( is_running() ); BOOST_ASSERT( ! is_complete() ); BOOST_ASSERT( ! other->is_running() ); BOOST_ASSERT( ! other->is_complete() ); other->caller_ = caller_; flags_ &= ~flag_running; param_type * from( static_cast< param_type * >( callee_.jump( other->callee_, to) ) ); flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; } }; template< typename R > class symmetric_coroutine_impl< R & > : private noncopyable { public: typedef parameters< R & > param_type; symmetric_coroutine_impl( preallocated const& palloc, bool unwind) BOOST_NOEXCEPT : flags_( 0), caller_(), callee_( trampoline< symmetric_coroutine_impl< R > >, palloc) { if ( unwind) flags_ |= flag_force_unwind; } virtual ~symmetric_coroutine_impl() {} bool force_unwind() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_force_unwind); } bool unwind_requested() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_unwind_stack); } bool is_started() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_started); } bool is_running() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_running); } bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } void unwind_stack() BOOST_NOEXCEPT { if ( is_started() && ! is_complete() && force_unwind() ) { flags_ |= flag_unwind_stack; flags_ |= flag_running; param_type to( unwind_t::force_unwind); caller_.jump( callee_, & to); flags_ &= ~flag_running; flags_ &= ~flag_unwind_stack; BOOST_ASSERT( is_complete() ); } } void resume( R & arg) BOOST_NOEXCEPT { param_type to( & arg, this); resume_( & to); } R * yield() { BOOST_ASSERT( is_running() ); BOOST_ASSERT( ! is_complete() ); flags_ &= ~flag_running; param_type to; param_type * from( static_cast< param_type * >( callee_.jump( caller_, & to) ) ); flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; } template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other, X x) { typename symmetric_coroutine_impl< X >::param_type to( & x, other); return yield_to_( other, & to); } template< typename X > R * yield_to( symmetric_coroutine_impl< X & > * other, X & x) { typename symmetric_coroutine_impl< X & >::param_type to( & x, other); return yield_to_( other, & to); } template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other) { typename symmetric_coroutine_impl< X >::param_type to( other); return yield_to_( other, & to); } virtual void run( R *) BOOST_NOEXCEPT = 0; virtual void destroy() = 0; protected: template< typename X > friend class symmetric_coroutine_impl; int flags_; coroutine_context caller_; coroutine_context callee_; void resume_( param_type * to) BOOST_NOEXCEPT { BOOST_ASSERT( ! is_running() ); BOOST_ASSERT( ! is_complete() ); flags_ |= flag_running; caller_.jump( callee_, to); flags_ &= ~flag_running; } template< typename Other > R * yield_to_( Other * other, typename Other::param_type * to) { BOOST_ASSERT( is_running() ); BOOST_ASSERT( ! is_complete() ); BOOST_ASSERT( ! other->is_running() ); BOOST_ASSERT( ! other->is_complete() ); other->caller_ = caller_; flags_ &= ~flag_running; param_type * from( static_cast< param_type * >( callee_.jump( other->callee_, to) ) ); flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; } }; template<> class symmetric_coroutine_impl< void > : private noncopyable { public: typedef parameters< void > param_type; symmetric_coroutine_impl( preallocated const& palloc, bool unwind) BOOST_NOEXCEPT : flags_( 0), caller_(), callee_( trampoline_void< symmetric_coroutine_impl< void > >, palloc) { if ( unwind) flags_ |= flag_force_unwind; } virtual ~symmetric_coroutine_impl() {} inline bool force_unwind() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_force_unwind); } inline bool unwind_requested() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_unwind_stack); } inline bool is_started() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_started); } inline bool is_running() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_running); } inline bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } inline void unwind_stack() BOOST_NOEXCEPT { if ( is_started() && ! is_complete() && force_unwind() ) { flags_ |= flag_unwind_stack; flags_ |= flag_running; param_type to( unwind_t::force_unwind); caller_.jump( callee_, & to); flags_ &= ~flag_running; flags_ &= ~flag_unwind_stack; BOOST_ASSERT( is_complete() ); } } inline void resume() BOOST_NOEXCEPT { BOOST_ASSERT( ! is_running() ); BOOST_ASSERT( ! is_complete() ); param_type to( this); flags_ |= flag_running; caller_.jump( callee_, & to); flags_ &= ~flag_running; } inline void yield() { BOOST_ASSERT( is_running() ); BOOST_ASSERT( ! is_complete() ); flags_ &= ~flag_running; param_type to; param_type * from( static_cast< param_type * >( callee_.jump( caller_, & to) ) ); flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); } template< typename X > void yield_to( symmetric_coroutine_impl< X > * other, X x) { typename symmetric_coroutine_impl< X >::param_type to( & x, other); yield_to_( other, & to); } template< typename X > void yield_to( symmetric_coroutine_impl< X & > * other, X & x) { typename symmetric_coroutine_impl< X & >::param_type to( & x, other); yield_to_( other, & to); } template< typename X > void yield_to( symmetric_coroutine_impl< X > * other) { typename symmetric_coroutine_impl< X >::param_type to( other); yield_to_( other, & to); } virtual void run() BOOST_NOEXCEPT = 0; virtual void destroy() = 0; protected: template< typename X > friend class symmetric_coroutine_impl; int flags_; coroutine_context caller_; coroutine_context callee_; template< typename Other > void yield_to_( Other * other, typename Other::param_type * to) { BOOST_ASSERT( is_running() ); BOOST_ASSERT( ! is_complete() ); BOOST_ASSERT( ! other->is_running() ); BOOST_ASSERT( ! other->is_complete() ); other->caller_ = caller_; flags_ &= ~flag_running; param_type * from( static_cast< param_type * >( callee_.jump( other->callee_, to) ) ); flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); } }; }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H PK ��!\���� � detail/config.hppnu �[��� // 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_CONFIG_H #define BOOST_COROUTINES_DETAIL_CONFIG_H #include <boost/config.hpp> #include <boost/detail/workaround.hpp> #ifdef BOOST_COROUTINES_DECL # undef BOOST_COROUTINES_DECL #endif #if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES_DYN_LINK) ) && ! defined(BOOST_COROUTINES_STATIC_LINK) # if defined(BOOST_COROUTINES_SOURCE) # define BOOST_COROUTINES_DECL BOOST_SYMBOL_EXPORT # define BOOST_COROUTINES_BUILD_DLL # else # define BOOST_COROUTINES_DECL BOOST_SYMBOL_IMPORT # endif #endif #if ! defined(BOOST_COROUTINES_DECL) # define BOOST_COROUTINES_DECL #endif #if ! defined(BOOST_COROUTINES_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_COROUTINES_NO_LIB) # define BOOST_LIB_NAME boost_coroutine # if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES_DYN_LINK) # define BOOST_DYN_LINK # endif # include <boost/config/auto_link.hpp> #endif #define BOOST_COROUTINES_UNIDIRECT #define BOOST_COROUTINES_SYMMETRIC #endif // BOOST_COROUTINES_DETAIL_CONFIG_H PK ��!\#��^"