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