summaryrefslogtreecommitdiff
path: root/boost/coroutine
diff options
context:
space:
mode:
Diffstat (limited to 'boost/coroutine')
-rw-r--r--boost/coroutine/all.hpp21
-rw-r--r--boost/coroutine/asymmetric_coroutine.hpp2243
-rw-r--r--boost/coroutine/attributes.hpp94
-rw-r--r--boost/coroutine/coroutine.hpp13
-rw-r--r--boost/coroutine/detail/config.hpp49
-rw-r--r--boost/coroutine/detail/coroutine_context.hpp62
-rw-r--r--boost/coroutine/detail/flags.hpp48
-rw-r--r--boost/coroutine/detail/parameters.hpp102
-rw-r--r--boost/coroutine/detail/pull_coroutine_impl.hpp355
-rw-r--r--boost/coroutine/detail/pull_coroutine_object.hpp324
-rw-r--r--boost/coroutine/detail/pull_coroutine_synthesized.hpp80
-rw-r--r--boost/coroutine/detail/push_coroutine_impl.hpp295
-rw-r--r--boost/coroutine/detail/push_coroutine_object.hpp336
-rw-r--r--boost/coroutine/detail/push_coroutine_synthesized.hpp78
-rw-r--r--boost/coroutine/detail/setup.hpp75
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_call.hpp822
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_impl.hpp472
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_object.hpp281
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_yield.hpp307
-rw-r--r--boost/coroutine/detail/trampoline.hpp67
-rw-r--r--boost/coroutine/detail/trampoline_pull.hpp48
-rw-r--r--boost/coroutine/detail/trampoline_push.hpp77
-rw-r--r--boost/coroutine/exceptions.hpp105
-rw-r--r--boost/coroutine/flags.hpp27
-rw-r--r--boost/coroutine/posix/protected_stack_allocator.hpp105
-rw-r--r--boost/coroutine/posix/segmented_stack_allocator.hpp69
-rw-r--r--boost/coroutine/protected_stack_allocator.hpp13
-rw-r--r--boost/coroutine/segmented_stack_allocator.hpp15
-rw-r--r--boost/coroutine/stack_allocator.hpp37
-rw-r--r--boost/coroutine/stack_context.hpp66
-rw-r--r--boost/coroutine/stack_traits.hpp42
-rw-r--r--boost/coroutine/standard_stack_allocator.hpp75
-rw-r--r--boost/coroutine/symmetric_coroutine.hpp35
-rw-r--r--boost/coroutine/windows/protected_stack_allocator.hpp87
34 files changed, 6925 insertions, 0 deletions
diff --git a/boost/coroutine/all.hpp b/boost/coroutine/all.hpp
new file mode 100644
index 0000000000..42f63a0a73
--- /dev/null
+++ b/boost/coroutine/all.hpp
@@ -0,0 +1,21 @@
+
+// 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
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
diff --git a/boost/coroutine/attributes.hpp b/boost/coroutine/attributes.hpp
new file mode 100644
index 0000000000..065a4c66e3
--- /dev/null
+++ b/boost/coroutine/attributes.hpp
@@ -0,0 +1,94 @@
+
+// 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;
+ flag_fpu_t preserve_fpu;
+
+ attributes() BOOST_NOEXCEPT :
+ size( stack_allocator::traits_type::default_size() ),
+ do_unwind( stack_unwind),
+ preserve_fpu( fpu_preserved)
+ {}
+
+ explicit attributes( std::size_t size_) BOOST_NOEXCEPT :
+ size( size_),
+ do_unwind( stack_unwind),
+ preserve_fpu( fpu_preserved)
+ {}
+
+ explicit attributes( flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
+ size( stack_allocator::traits_type::default_size() ),
+ do_unwind( do_unwind_),
+ preserve_fpu( fpu_preserved)
+ {}
+
+ explicit attributes( flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
+ size( stack_allocator::traits_type::default_size() ),
+ do_unwind( stack_unwind),
+ preserve_fpu( preserve_fpu_)
+ {}
+
+ explicit attributes(
+ std::size_t size_,
+ flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
+ size( size_),
+ do_unwind( do_unwind_),
+ preserve_fpu( fpu_preserved)
+ {}
+
+ explicit attributes(
+ std::size_t size_,
+ flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
+ size( size_),
+ do_unwind( stack_unwind),
+ preserve_fpu( preserve_fpu_)
+ {}
+
+ explicit attributes(
+ flag_unwind_t do_unwind_,
+ flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
+ size( stack_allocator::traits_type::default_size() ),
+ do_unwind( do_unwind_),
+ preserve_fpu( preserve_fpu_)
+ {}
+
+ explicit attributes(
+ std::size_t size_,
+ flag_unwind_t do_unwind_,
+ flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
+ size( size_),
+ do_unwind( do_unwind_),
+ preserve_fpu( preserve_fpu_)
+ {}
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_ATTRIBUTES_H
diff --git a/boost/coroutine/coroutine.hpp b/boost/coroutine/coroutine.hpp
new file mode 100644
index 0000000000..076ffd26ea
--- /dev/null
+++ b/boost/coroutine/coroutine.hpp
@@ -0,0 +1,13 @@
+
+// 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
diff --git a/boost/coroutine/detail/config.hpp b/boost/coroutine/detail/config.hpp
new file mode 100644
index 0000000000..9a3f4bf334
--- /dev/null
+++ b/boost/coroutine/detail/config.hpp
@@ -0,0 +1,49 @@
+
+// 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
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if ! ( (defined(__GNUC__) && __GNUC__ > 3 && __GNUC_MINOR__ > 6) || \
+ (defined(__clang__) && __clang_major__ > 2 && __clang_minor__ > 3) )
+# error "compiler does not support segmented stacks"
+# endif
+# define BOOST_COROUTINES_SEGMENTS 10
+#endif
+
+#define BOOST_COROUTINES_UNIDIRECT
+#define BOOST_COROUTINES_SYMMETRIC
+
+#endif // BOOST_COROUTINES_DETAIL_CONFIG_H
diff --git a/boost/coroutine/detail/coroutine_context.hpp b/boost/coroutine/detail/coroutine_context.hpp
new file mode 100644
index 0000000000..6c4ebb68b1
--- /dev/null
+++ b/boost/coroutine/detail/coroutine_context.hpp
@@ -0,0 +1,62 @@
+
+// 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/fcontext.hpp>
+
+#include <boost/coroutine/detail/config.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:
+ stack_context stack_ctx_;
+ context::fcontext_t ctx_;
+
+public:
+ typedef void( * ctx_fn)( intptr_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, stack_context const& stack_ctx);
+
+ coroutine_context( coroutine_context const&);
+
+ coroutine_context& operator=( coroutine_context const&);
+
+ intptr_t jump( coroutine_context &, intptr_t = 0, bool = true);
+
+ stack_context & stack_ctx()
+ { return stack_ctx_; }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_COROUTINE_CONTEXT_H
diff --git a/boost/coroutine/detail/flags.hpp b/boost/coroutine/detail/flags.hpp
new file mode 100644
index 0000000000..8d19757ee8
--- /dev/null
+++ b/boost/coroutine/detail/flags.hpp
@@ -0,0 +1,48 @@
+
+// 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_FLAGS_H
+#define BOOST_COROUTINES_DETAIL_FLAGS_H
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+enum flag_t
+{
+ flag_started = 1 << 1,
+ flag_running = 1 << 2,
+ flag_complete = 1 << 3,
+ flag_unwind_stack = 1 << 4,
+ flag_force_unwind = 1 << 5,
+ flag_preserve_fpu = 1 << 6
+};
+
+struct unwind_t
+{
+ enum flag_t
+ { force_unwind = 1 };
+};
+
+struct synthesized_t
+{
+ enum flag_t
+ { syntesized = 1 };
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_FLAGS_H
diff --git a/boost/coroutine/detail/parameters.hpp b/boost/coroutine/detail/parameters.hpp
new file mode 100644
index 0000000000..8bad3910a9
--- /dev/null
+++ b/boost/coroutine/detail/parameters.hpp
@@ -0,0 +1,102 @@
+
+// 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_PARAMETERS_H
+#define BOOST_COROUTINES_DETAIL_PARAMETERS_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/coroutine/detail/flags.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Data >
+struct parameters
+{
+ Data * data;
+ bool do_unwind;
+ void * coro;
+
+ parameters() :
+ data( 0), do_unwind( false), coro( 0)
+ {}
+
+ explicit parameters( void * coro_) :
+ data( 0), do_unwind( false), coro( coro_)
+ { BOOST_ASSERT( 0 != coro); }
+
+ explicit parameters( Data * data_, void * coro_) :
+ data( data_), do_unwind( false), coro( coro_)
+ {
+ BOOST_ASSERT( 0 != data);
+ BOOST_ASSERT( 0 != coro);
+ }
+
+ explicit parameters( unwind_t::flag_t) :
+ data( 0), do_unwind( true)
+ {}
+};
+
+template< typename Data >
+struct parameters< Data & >
+{
+ Data * data;
+ bool do_unwind;
+ void * coro;
+
+ parameters() :
+ data( 0), do_unwind( false), coro( 0)
+ {}
+
+ explicit parameters( void * coro_) :
+ data( 0), do_unwind( false), coro( coro_)
+ { BOOST_ASSERT( 0 != coro); }
+
+ explicit parameters( Data * data_, void * coro_) :
+ data( data_), do_unwind( false), coro( coro_)
+ {
+ BOOST_ASSERT( 0 != data);
+ BOOST_ASSERT( 0 != coro);
+ }
+
+ explicit parameters( unwind_t::flag_t) :
+ data( 0), do_unwind( true), coro( 0)
+ {}
+};
+
+template<>
+struct parameters< void >
+{
+ bool do_unwind;
+ void * coro;
+
+ parameters() :
+ do_unwind( false), coro(0)
+ {}
+
+ parameters( void * coro_) :
+ do_unwind( false), coro( coro_)
+ { BOOST_ASSERT( 0 != coro); }
+
+ explicit parameters( unwind_t::flag_t) :
+ do_unwind( true), coro( 0)
+ {}
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_PARAMETERS_H
diff --git a/boost/coroutine/detail/pull_coroutine_impl.hpp b/boost/coroutine/detail/pull_coroutine_impl.hpp
new file mode 100644
index 0000000000..10ca597544
--- /dev/null
+++ b/boost/coroutine/detail/pull_coroutine_impl.hpp
@@ -0,0 +1,355 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
+#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/throw_exception.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/trampoline_pull.hpp>
+#include <boost/coroutine/exceptions.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+struct stack_context;
+
+namespace detail {
+
+template< typename R >
+class pull_coroutine_impl : private noncopyable
+{
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context * caller_;
+ coroutine_context * callee_;
+ R * result_;
+
+public:
+ typedef parameters< R > param_type;
+
+ pull_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee),
+ result_( 0)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu,
+ R * result) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee),
+ result_( result)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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;
+ param_type to( unwind_t::force_unwind);
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( is_complete() );
+ }
+ }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ |= flag_running;
+ param_type to( this);
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ flags_ &= ~flag_running;
+ result_ = from->data;
+ if ( from->do_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ bool has_result() const
+ { return 0 != result_; }
+
+ R get() const
+ {
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
+ return * result_;
+ }
+
+ R * get_pointer() const
+ {
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
+ return result_;
+ }
+
+ virtual void destroy() = 0;
+};
+
+template< typename R >
+class pull_coroutine_impl< R & > : private noncopyable
+{
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context * caller_;
+ coroutine_context * callee_;
+ R * result_;
+
+public:
+ typedef parameters< R & > param_type;
+
+ pull_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee),
+ result_( 0)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu,
+ R * result) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee),
+ result_( result)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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;
+ param_type to( unwind_t::force_unwind);
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( is_complete() );
+ }
+ }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ |= flag_running;
+ param_type to( this);
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ flags_ &= ~flag_running;
+ result_ = from->data;
+ if ( from->do_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ bool has_result() const
+ { return 0 != result_; }
+
+ R & get() const
+ {
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
+ return * result_;
+ }
+
+ R * get_pointer() const
+ {
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
+ return result_;
+ }
+
+ virtual void destroy() = 0;
+};
+
+template<>
+class pull_coroutine_impl< void > : private noncopyable
+{
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context * caller_;
+ coroutine_context * callee_;
+
+public:
+ typedef parameters< void > param_type;
+
+ pull_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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;
+ param_type to( unwind_t::force_unwind);
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( is_complete() );
+ }
+ }
+
+ inline void pull()
+ {
+ BOOST_ASSERT( ! is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ |= flag_running;
+ param_type to( this);
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ flags_ &= ~flag_running;
+ if ( from->do_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ virtual void destroy() = 0;
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
diff --git a/boost/coroutine/detail/pull_coroutine_object.hpp b/boost/coroutine/detail/pull_coroutine_object.hpp
new file mode 100644
index 0000000000..cfe34bd3c9
--- /dev/null
+++ b/boost/coroutine/detail/pull_coroutine_object.hpp
@@ -0,0 +1,324 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/move/move.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+#include <boost/coroutine/detail/pull_coroutine_impl.hpp>
+#include <boost/coroutine/detail/trampoline_pull.hpp>
+#include <boost/coroutine/exceptions.hpp>
+#include <boost/coroutine/flags.hpp>
+#include <boost/coroutine/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4355)
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+struct pull_coroutine_context
+{
+ coroutine_context caller;
+ coroutine_context callee;
+
+ template< typename Coro >
+ pull_coroutine_context( stack_context const& stack_ctx, Coro *) :
+ caller(),
+ callee( trampoline_pull< Coro >, stack_ctx)
+ {}
+};
+
+template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
+class pull_coroutine_object : private pull_coroutine_context,
+ public pull_coroutine_impl< R >
+{
+private:
+ typedef pull_coroutine_context ctx_t;
+ typedef pull_coroutine_impl< R > base_t;
+ typedef pull_coroutine_object< PushCoro, 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
+ pull_coroutine_object( Fn fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+
+ void run()
+ {
+ BOOST_ASSERT( ! base_t::unwind_requested() );
+
+ base_t::flags_ |= flag_started;
+ base_t::flags_ |= flag_running;
+
+ // create push_coroutine
+ typename PushCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ PushCoro push_coro( synthesized_t::syntesized, b);
+ try
+ { fn_( push_coro); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { base_t::except_ = current_exception(); }
+
+ base_t::flags_ |= flag_complete;
+ base_t::flags_ &= ~flag_running;
+ typename base_t::param_type to;
+ this->callee.jump(
+ this->caller,
+ reinterpret_cast< intptr_t >( & to),
+ base_t::preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void destroy()
+ { deallocate_( this); }
+};
+
+template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
+class pull_coroutine_object< PushCoro, R &, Fn, StackAllocator > : private pull_coroutine_context,
+ public pull_coroutine_impl< R & >
+{
+private:
+ typedef pull_coroutine_context ctx_t;
+ typedef pull_coroutine_impl< R & > base_t;
+ typedef pull_coroutine_object< PushCoro, 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
+ pull_coroutine_object( Fn fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+
+ void run()
+ {
+ BOOST_ASSERT( ! base_t::unwind_requested() );
+
+ base_t::flags_ |= flag_started;
+ base_t::flags_ |= flag_running;
+
+ // create push_coroutine
+ typename PushCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ PushCoro push_coro( synthesized_t::syntesized, b);
+ try
+ { fn_( push_coro); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { base_t::except_ = current_exception(); }
+
+ base_t::flags_ |= flag_complete;
+ base_t::flags_ &= ~flag_running;
+ typename base_t::param_type to;
+ this->callee.jump(
+ this->caller,
+ reinterpret_cast< intptr_t >( & to),
+ base_t::preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void destroy()
+ { deallocate_( this); }
+};
+
+template< typename PushCoro, typename Fn, typename StackAllocator >
+class pull_coroutine_object< PushCoro, void, Fn, StackAllocator > : private pull_coroutine_context,
+ public pull_coroutine_impl< void >
+{
+private:
+ typedef pull_coroutine_context ctx_t;
+ typedef pull_coroutine_impl< void > base_t;
+ typedef pull_coroutine_object< PushCoro, 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
+ pull_coroutine_object( Fn fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+
+ void run()
+ {
+ BOOST_ASSERT( ! base_t::unwind_requested() );
+
+ base_t::flags_ |= flag_started;
+ base_t::flags_ |= flag_running;
+
+ // create push_coroutine
+ typename PushCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ PushCoro push_coro( synthesized_t::syntesized, b);
+ try
+ { fn_( push_coro); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { base_t::except_ = current_exception(); }
+
+ base_t::flags_ |= flag_complete;
+ base_t::flags_ &= ~flag_running;
+ typename base_t::param_type to;
+ this->callee.jump(
+ this->caller,
+ reinterpret_cast< intptr_t >( & to),
+ base_t::preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void destroy()
+ { deallocate_( this); }
+};
+
+}}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
diff --git a/boost/coroutine/detail/pull_coroutine_synthesized.hpp b/boost/coroutine/detail/pull_coroutine_synthesized.hpp
new file mode 100644
index 0000000000..952d50c113
--- /dev/null
+++ b/boost/coroutine/detail/pull_coroutine_synthesized.hpp
@@ -0,0 +1,80 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
+#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
+
+#include <boost/config.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/pull_coroutine_impl.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename R >
+class pull_coroutine_synthesized : public pull_coroutine_impl< R >
+{
+private:
+ typedef pull_coroutine_impl< R > impl_t;
+
+public:
+ pull_coroutine_synthesized( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu,
+ R * result) :
+ impl_t( caller, callee, unwind, preserve_fpu, result)
+ {}
+
+ void destroy() {}
+};
+
+template< typename R >
+class pull_coroutine_synthesized< R & > : public pull_coroutine_impl< R & >
+{
+private:
+ typedef pull_coroutine_impl< R & > impl_t;
+
+public:
+ pull_coroutine_synthesized( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu,
+ R * result) :
+ impl_t( caller, callee, unwind, preserve_fpu, result)
+ {}
+
+ void destroy() {}
+};
+
+template<>
+class pull_coroutine_synthesized< void > : public pull_coroutine_impl< void >
+{
+private:
+ typedef pull_coroutine_impl< void > impl_t;
+
+public:
+ pull_coroutine_synthesized( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ impl_t( caller, callee, unwind, preserve_fpu)
+ {}
+
+ inline void destroy() {}
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
diff --git a/boost/coroutine/detail/push_coroutine_impl.hpp b/boost/coroutine/detail/push_coroutine_impl.hpp
new file mode 100644
index 0000000000..8ee2bd6f0e
--- /dev/null
+++ b/boost/coroutine/detail/push_coroutine_impl.hpp
@@ -0,0 +1,295 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
+#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/throw_exception.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/trampoline_push.hpp>
+#include <boost/coroutine/exceptions.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+struct stack_context;
+
+namespace detail {
+
+template< typename Arg >
+class push_coroutine_impl : private noncopyable
+{
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context * caller_;
+ coroutine_context * callee_;
+
+public:
+ typedef parameters< Arg > param_type;
+
+ push_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ 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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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;
+ param_type to( unwind_t::force_unwind);
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( is_complete() );
+ }
+ }
+
+ void push( Arg const& arg)
+ {
+ BOOST_ASSERT( ! is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ |= flag_running;
+ param_type to( const_cast< Arg * >( & arg), this);
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ flags_ &= ~flag_running;
+ if ( from->do_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ void push( BOOST_RV_REF( Arg) arg)
+ {
+ BOOST_ASSERT( ! is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ |= flag_running;
+ param_type to( const_cast< Arg * >( & arg), this);
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ flags_ &= ~flag_running;
+ if ( from->do_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ virtual void destroy() = 0;
+};
+
+template< typename Arg >
+class push_coroutine_impl< Arg & > : private noncopyable
+{
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context * caller_;
+ coroutine_context * callee_;
+
+public:
+ typedef parameters< Arg & > param_type;
+
+ push_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ 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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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;
+ param_type to( unwind_t::force_unwind);
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( is_complete() );
+ }
+ }
+
+ void push( Arg & arg)
+ {
+ BOOST_ASSERT( ! is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ |= flag_running;
+ param_type to( & arg, this);
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ flags_ &= ~flag_running;
+ if ( from->do_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ virtual void destroy() = 0;
+};
+
+template<>
+class push_coroutine_impl< void > : private noncopyable
+{
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context * caller_;
+ coroutine_context * callee_;
+
+public:
+ typedef parameters< void > param_type;
+
+ push_coroutine_impl( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ flags_( 0),
+ except_(),
+ caller_( caller),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ 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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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;
+ param_type to( unwind_t::force_unwind);
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( is_complete() );
+ }
+ }
+
+ inline void push()
+ {
+ BOOST_ASSERT( ! is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ |= flag_running;
+ param_type to( this);
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ caller_->jump(
+ * callee_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ flags_ &= ~flag_running;
+ if ( from->do_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ virtual void destroy() = 0;
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
diff --git a/boost/coroutine/detail/push_coroutine_object.hpp b/boost/coroutine/detail/push_coroutine_object.hpp
new file mode 100644
index 0000000000..1a39c07230
--- /dev/null
+++ b/boost/coroutine/detail/push_coroutine_object.hpp
@@ -0,0 +1,336 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/move/move.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+#include <boost/coroutine/detail/push_coroutine_impl.hpp>
+#include <boost/coroutine/detail/trampoline_push.hpp>
+#include <boost/coroutine/exceptions.hpp>
+#include <boost/coroutine/flags.hpp>
+#include <boost/coroutine/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4355)
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+struct push_coroutine_context
+{
+ coroutine_context caller;
+ coroutine_context callee;
+
+ template< typename Coro >
+ push_coroutine_context( stack_context const& stack_ctx, Coro *) :
+ caller(),
+ callee( trampoline_push< Coro >, stack_ctx)
+ {}
+};
+
+struct push_coroutine_context_void
+{
+ coroutine_context caller;
+ coroutine_context callee;
+
+ template< typename Coro >
+ push_coroutine_context_void( stack_context const& stack_ctx, Coro *) :
+ caller(),
+ callee( trampoline_push_void< Coro >, stack_ctx)
+ {}
+};
+
+template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
+class push_coroutine_object : private push_coroutine_context,
+ public push_coroutine_impl< R >
+{
+private:
+ typedef push_coroutine_context ctx_t;
+ typedef push_coroutine_impl< R > base_t;
+ typedef push_coroutine_object< PullCoro, 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
+ push_coroutine_object( Fn fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+
+ void run( R * result)
+ {
+ BOOST_ASSERT( ! base_t::unwind_requested() );
+
+ base_t::flags_ |= flag_started;
+ base_t::flags_ |= flag_running;
+
+ // create push_coroutine
+ typename PullCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu(), result);
+ PullCoro pull_coro( synthesized_t::syntesized, b);
+ try
+ { fn_( pull_coro); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { base_t::except_ = current_exception(); }
+
+ base_t::flags_ |= flag_complete;
+ base_t::flags_ &= ~flag_running;
+ typename base_t::param_type to;
+ this->callee.jump(
+ this->caller,
+ reinterpret_cast< intptr_t >( & to),
+ base_t::preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void destroy()
+ { deallocate_( this); }
+};
+
+template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
+class push_coroutine_object< PullCoro, R &, Fn, StackAllocator > : private push_coroutine_context,
+ public push_coroutine_impl< R & >
+{
+private:
+ typedef push_coroutine_context ctx_t;
+ typedef push_coroutine_impl< R & > base_t;
+ typedef push_coroutine_object< PullCoro, 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
+ push_coroutine_object( Fn fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+
+ void run( R * result)
+ {
+ BOOST_ASSERT( ! base_t::unwind_requested() );
+
+ base_t::flags_ |= flag_started;
+ base_t::flags_ |= flag_running;
+
+ // create push_coroutine
+ typename PullCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu(), result);
+ PullCoro push_coro( synthesized_t::syntesized, b);
+ try
+ { fn_( push_coro); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { base_t::except_ = current_exception(); }
+
+ base_t::flags_ |= flag_complete;
+ base_t::flags_ &= ~flag_running;
+ typename base_t::param_type to;
+ this->callee.jump(
+ this->caller,
+ reinterpret_cast< intptr_t >( & to),
+ base_t::preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void destroy()
+ { deallocate_( this); }
+};
+
+template< typename PullCoro, typename Fn, typename StackAllocator >
+class push_coroutine_object< PullCoro, void, Fn, StackAllocator > : private push_coroutine_context_void,
+ public push_coroutine_impl< void >
+{
+private:
+ typedef push_coroutine_context_void ctx_t;
+ typedef push_coroutine_impl< void > base_t;
+ typedef push_coroutine_object< PullCoro, 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
+ push_coroutine_object( Fn fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ ctx_t( internal_stack_ctx, this),
+ base_t( & this->caller,
+ & this->callee,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+
+ void run()
+ {
+ BOOST_ASSERT( ! base_t::unwind_requested() );
+
+ base_t::flags_ |= flag_started;
+ base_t::flags_ |= flag_running;
+
+ // create push_coroutine
+ typename PullCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ PullCoro push_coro( synthesized_t::syntesized, b);
+ try
+ { fn_( push_coro); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { base_t::except_ = current_exception(); }
+
+ base_t::flags_ |= flag_complete;
+ base_t::flags_ &= ~flag_running;
+ typename base_t::param_type to;
+ this->callee.jump(
+ this->caller,
+ reinterpret_cast< intptr_t >( & to),
+ base_t::preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void destroy()
+ { deallocate_( this); }
+};
+
+}}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
diff --git a/boost/coroutine/detail/push_coroutine_synthesized.hpp b/boost/coroutine/detail/push_coroutine_synthesized.hpp
new file mode 100644
index 0000000000..306a841fc0
--- /dev/null
+++ b/boost/coroutine/detail/push_coroutine_synthesized.hpp
@@ -0,0 +1,78 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
+#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
+
+#include <boost/config.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/push_coroutine_impl.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename R >
+class push_coroutine_synthesized : public push_coroutine_impl< R >
+{
+private:
+ typedef push_coroutine_impl< R > impl_t;
+
+public:
+ push_coroutine_synthesized( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ impl_t( caller, callee, unwind, preserve_fpu)
+ {}
+
+ void destroy() {}
+};
+
+template< typename R >
+class push_coroutine_synthesized< R & > : public push_coroutine_impl< R & >
+{
+private:
+ typedef push_coroutine_impl< R & > impl_t;
+
+public:
+ push_coroutine_synthesized( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ impl_t( caller, callee, unwind, preserve_fpu)
+ {}
+
+ void destroy() {}
+};
+
+template<>
+class push_coroutine_synthesized< void > : public push_coroutine_impl< void >
+{
+private:
+ typedef push_coroutine_impl< void > impl_t;
+
+public:
+ push_coroutine_synthesized( coroutine_context * caller,
+ coroutine_context * callee,
+ bool unwind, bool preserve_fpu) :
+ impl_t( caller, callee, unwind, preserve_fpu)
+ {}
+
+ inline void destroy() {}
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
diff --git a/boost/coroutine/detail/setup.hpp b/boost/coroutine/detail/setup.hpp
new file mode 100644
index 0000000000..35f601a779
--- /dev/null
+++ b/boost/coroutine/detail/setup.hpp
@@ -0,0 +1,75 @@
+
+// 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_SETUP_H
+#define BOOST_COROUTINES_DETAIL_SETUP_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/move/move.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/coroutine/attributes.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Fn >
+struct setup
+{
+ struct dummy {};
+
+ Fn fn;
+ coroutine_context * caller;
+ coroutine_context * callee;
+ attributes attr;
+
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ setup( Fn fn_,
+ coroutine_context * caller_,
+ coroutine_context * callee_,
+ attributes const& attr_) :
+ fn( boost::forward< Fn >( fn_) ),
+ caller( caller_),
+ callee( callee_),
+ attr( attr_)
+ {}
+#endif
+ setup( BOOST_RV_REF( Fn) fn_,
+ coroutine_context * caller_,
+ coroutine_context * callee_,
+ attributes const& attr_,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, setup >,
+ dummy*
+ >::type = 0) :
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn( fn_),
+#else
+ fn( boost::forward< Fn >( fn_) ),
+#endif
+ caller( caller_),
+ callee( callee_),
+ attr( attr_)
+ {}
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_SETUP_H
diff --git a/boost/coroutine/detail/symmetric_coroutine_call.hpp b/boost/coroutine/detail/symmetric_coroutine_call.hpp
new file mode 100644
index 0000000000..a499275636
--- /dev/null
+++ b/boost/coroutine/detail/symmetric_coroutine_call.hpp
@@ -0,0 +1,822 @@
+
+// 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/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
+ 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 >
+ 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
+ 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 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
+ 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 >
+ 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
+ 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 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
+ 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 >
+ 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
+ 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 >
+ 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
+ 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 >
+ 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
+ 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
+
+ ~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
+ 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 >
+ 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
+ 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 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
+ 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 >
+ 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
+ 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 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
+ 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 >
+ 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
+ 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 >
+ 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
+ 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 >
+ 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
+ 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
+
+ ~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
+ 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 >
+ 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
+ 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 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
+ 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 >
+ 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
+ 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 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
+ 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 >
+ 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
+ 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 >
+ 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
+ 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 >
+ 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
+ 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
+
+ ~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
diff --git a/boost/coroutine/detail/symmetric_coroutine_impl.hpp b/boost/coroutine/detail/symmetric_coroutine_impl.hpp
new file mode 100644
index 0000000000..0234ca7765
--- /dev/null
+++ b/boost/coroutine/detail/symmetric_coroutine_impl.hpp
@@ -0,0 +1,472 @@
+
+// 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/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( stack_context const& stack_ctx,
+ bool unwind, bool preserve_fpu) BOOST_NOEXCEPT :
+ flags_( 0),
+ caller_(),
+ callee_( trampoline< symmetric_coroutine_impl< R > >, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ 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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ 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(
+ reinterpret_cast< param_type * >(
+ callee_.jump(
+ caller_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ 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_,
+ reinterpret_cast< intptr_t >( to),
+ preserve_fpu() );
+ 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(
+ reinterpret_cast< param_type * >(
+ callee_.jump(
+ other->callee_,
+ reinterpret_cast< intptr_t >( to),
+ preserve_fpu() ) ) );
+ 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( stack_context const& stack_ctx,
+ bool unwind, bool preserve_fpu) BOOST_NOEXCEPT :
+ flags_( 0),
+ caller_(),
+ callee_( trampoline< symmetric_coroutine_impl< R > >, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ 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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ 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(
+ reinterpret_cast< param_type * >(
+ callee_.jump(
+ caller_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ 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_,
+ reinterpret_cast< intptr_t >( to),
+ preserve_fpu() );
+ 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(
+ reinterpret_cast< param_type * >(
+ callee_.jump(
+ other->callee_,
+ reinterpret_cast< intptr_t >( to),
+ preserve_fpu() ) ) );
+ 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( stack_context const& stack_ctx,
+ bool unwind, bool preserve_fpu) BOOST_NOEXCEPT :
+ flags_( 0),
+ caller_(),
+ callee_( trampoline_void< symmetric_coroutine_impl< void > >, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ 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 preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ 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_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ 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_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() );
+ flags_ &= ~flag_running;
+ }
+
+ inline void yield() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( is_running() );
+ BOOST_ASSERT( ! is_complete() );
+
+ flags_ &= ~flag_running;
+ param_type to;
+ param_type * from(
+ reinterpret_cast< param_type * >(
+ callee_.jump(
+ caller_,
+ reinterpret_cast< intptr_t >( & to),
+ preserve_fpu() ) ) );
+ 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(
+ reinterpret_cast< param_type * >(
+ callee_.jump(
+ other->callee_,
+ reinterpret_cast< intptr_t >( to),
+ preserve_fpu() ) ) );
+ 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
diff --git a/boost/coroutine/detail/symmetric_coroutine_object.hpp b/boost/coroutine/detail/symmetric_coroutine_object.hpp
new file mode 100644
index 0000000000..a1c0c052a5
--- /dev/null
+++ b/boost/coroutine/detail/symmetric_coroutine_object.hpp
@@ -0,0 +1,281 @@
+
+// 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/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,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ impl_t( internal_stack_ctx,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ impl_t( internal_stack_ctx,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ 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_,
+ reinterpret_cast< intptr_t >( & to),
+ impl_t::preserve_fpu() );
+ 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,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ impl_t( internal_stack_ctx,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ impl_t( internal_stack_ctx,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ 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_,
+ reinterpret_cast< intptr_t >( & to),
+ impl_t::preserve_fpu() );
+ 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,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ impl_t( internal_stack_ctx,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+ fn_( fn),
+ stack_ctx_( stack_ctx),
+ stack_alloc_( stack_alloc)
+ {}
+#endif
+
+ symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
+ stack_context const& stack_ctx,
+ stack_context const& internal_stack_ctx,
+ StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
+ impl_t( internal_stack_ctx,
+ stack_unwind == attrs.do_unwind,
+ fpu_preserved == attrs.preserve_fpu),
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ fn_( fn),
+#else
+ fn_( boost::forward< Fn >( fn) ),
+#endif
+ stack_ctx_( stack_ctx),
+ 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_,
+ reinterpret_cast< intptr_t >( & to),
+ impl_t::preserve_fpu() );
+ 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
diff --git a/boost/coroutine/detail/symmetric_coroutine_yield.hpp b/boost/coroutine/detail/symmetric_coroutine_yield.hpp
new file mode 100644
index 0000000000..296676b6f9
--- /dev/null
+++ b/boost/coroutine/detail/symmetric_coroutine_yield.hpp
@@ -0,0 +1,307 @@
+
+// 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
diff --git a/boost/coroutine/detail/trampoline.hpp b/boost/coroutine/detail/trampoline.hpp
new file mode 100644
index 0000000000..1cb3226d15
--- /dev/null
+++ b/boost/coroutine/detail/trampoline.hpp
@@ -0,0 +1,67 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
+#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Coro >
+void trampoline( intptr_t vp)
+{
+ typedef typename Coro::param_type param_type;
+
+ BOOST_ASSERT( 0 != vp);
+
+ param_type * param(
+ reinterpret_cast< param_type * >( vp) );
+ BOOST_ASSERT( 0 != param);
+ BOOST_ASSERT( 0 != param->data);
+
+ Coro * coro(
+ reinterpret_cast< Coro * >( param->coro) );
+ BOOST_ASSERT( 0 != coro);
+
+ coro->run( param->data);
+}
+
+template< typename Coro >
+void trampoline_void( intptr_t vp)
+{
+ typedef typename Coro::param_type param_type;
+
+ BOOST_ASSERT( 0 != vp);
+
+ param_type * param(
+ reinterpret_cast< param_type * >( vp) );
+ BOOST_ASSERT( 0 != param);
+
+ Coro * coro(
+ reinterpret_cast< Coro * >( param->coro) );
+ BOOST_ASSERT( 0 != coro);
+
+ coro->run();
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
diff --git a/boost/coroutine/detail/trampoline_pull.hpp b/boost/coroutine/detail/trampoline_pull.hpp
new file mode 100644
index 0000000000..179024529d
--- /dev/null
+++ b/boost/coroutine/detail/trampoline_pull.hpp
@@ -0,0 +1,48 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
+#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Coro >
+void trampoline_pull( intptr_t vp)
+{
+ typedef typename Coro::param_type param_type;
+
+ BOOST_ASSERT( 0 != vp);
+
+ param_type * param(
+ reinterpret_cast< param_type * >( vp) );
+ BOOST_ASSERT( 0 != param);
+
+ Coro * coro(
+ reinterpret_cast< Coro * >( param->coro) );
+ BOOST_ASSERT( 0 != coro);
+
+ coro->run();
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
diff --git a/boost/coroutine/detail/trampoline_push.hpp b/boost/coroutine/detail/trampoline_push.hpp
new file mode 100644
index 0000000000..448904456e
--- /dev/null
+++ b/boost/coroutine/detail/trampoline_push.hpp
@@ -0,0 +1,77 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
+#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/move/move.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+#include <boost/coroutine/detail/parameters.hpp>
+#include <boost/coroutine/detail/setup.hpp>
+#include <boost/coroutine/detail/setup.hpp>
+#include <boost/coroutine/exceptions.hpp>
+#include <boost/coroutine/flags.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Coro >
+void trampoline_push( intptr_t vp)
+{
+ typedef typename Coro::param_type param_type;
+
+ BOOST_ASSERT( vp);
+
+ param_type * param(
+ reinterpret_cast< param_type * >( vp) );
+ BOOST_ASSERT( 0 != param);
+ BOOST_ASSERT( 0 != param->data);
+
+ Coro * coro(
+ reinterpret_cast< Coro * >( param->coro) );
+ BOOST_ASSERT( 0 != coro);
+
+ coro->run( param->data);
+}
+
+template< typename Coro >
+void trampoline_push_void( intptr_t vp)
+{
+ typedef typename Coro::param_type param_type;
+
+ BOOST_ASSERT( vp);
+
+ param_type * param(
+ reinterpret_cast< param_type * >( vp) );
+ BOOST_ASSERT( 0 != param);
+
+ Coro * coro(
+ reinterpret_cast< Coro * >( param->coro) );
+ BOOST_ASSERT( 0 != coro);
+
+ coro->run();
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
diff --git a/boost/coroutine/exceptions.hpp b/boost/coroutine/exceptions.hpp
new file mode 100644
index 0000000000..f263429719
--- /dev/null
+++ b/boost/coroutine/exceptions.hpp
@@ -0,0 +1,105 @@
+
+// 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/detail/scoped_enum_emulation.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_; }
+
+ const char* what() const throw()
+ { return code().message().c_str(); }
+};
+
+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
diff --git a/boost/coroutine/flags.hpp b/boost/coroutine/flags.hpp
new file mode 100644
index 0000000000..a8194c60ee
--- /dev/null
+++ b/boost/coroutine/flags.hpp
@@ -0,0 +1,27 @@
+
+// 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
+};
+
+enum flag_fpu_t
+{
+ fpu_preserved = 0,
+ fpu_not_preserved
+};
+
+}}
+
+#endif // BOOST_COROUTINES_FLAGS_H
diff --git a/boost/coroutine/posix/protected_stack_allocator.hpp b/boost/coroutine/posix/protected_stack_allocator.hpp
new file mode 100644
index 0000000000..659de337a1
--- /dev/null
+++ b/boost/coroutine/posix/protected_stack_allocator.hpp
@@ -0,0 +1,105 @@
+
+// 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
diff --git a/boost/coroutine/posix/segmented_stack_allocator.hpp b/boost/coroutine/posix/segmented_stack_allocator.hpp
new file mode 100644
index 0000000000..335e5789b4
--- /dev/null
+++ b/boost/coroutine/posix/segmented_stack_allocator.hpp
@@ -0,0 +1,69 @@
+
+// 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_COROUTINES_SEGMENTS],
+ std::size_t *);
+
+void __splitstack_releasecontext( void * [BOOST_COROUTINES_SEGMENTS]);
+
+void __splitstack_resetcontext( void * [BOOST_COROUTINES_SEGMENTS]);
+
+void __splitstack_block_signals_context( void * [BOOST_COROUTINES_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
diff --git a/boost/coroutine/protected_stack_allocator.hpp b/boost/coroutine/protected_stack_allocator.hpp
new file mode 100644
index 0000000000..268786fec4
--- /dev/null
+++ b/boost/coroutine/protected_stack_allocator.hpp
@@ -0,0 +1,13 @@
+
+// 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)
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_WINDOWS)
+# include <boost/coroutine/windows/protected_stack_allocator.hpp>
+#else
+# include <boost/coroutine/posix/protected_stack_allocator.hpp>
+#endif
diff --git a/boost/coroutine/segmented_stack_allocator.hpp b/boost/coroutine/segmented_stack_allocator.hpp
new file mode 100644
index 0000000000..f9525a1a5e
--- /dev/null
+++ b/boost/coroutine/segmented_stack_allocator.hpp
@@ -0,0 +1,15 @@
+
+// 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)
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if defined(BOOST_WINDOWS)
+# error "segmented stacks are not supported by Windows"
+# else
+# include <boost/coroutine/posix/segmented_stack_allocator.hpp>
+# endif
+#endif
diff --git a/boost/coroutine/stack_allocator.hpp b/boost/coroutine/stack_allocator.hpp
new file mode 100644
index 0000000000..662533efe7
--- /dev/null
+++ b/boost/coroutine/stack_allocator.hpp
@@ -0,0 +1,37 @@
+
+// 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
diff --git a/boost/coroutine/stack_context.hpp b/boost/coroutine/stack_context.hpp
new file mode 100644
index 0000000000..1ca11eb4a8
--- /dev/null
+++ b/boost/coroutine/stack_context.hpp
@@ -0,0 +1,66 @@
+
+// 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_CONTEXT_H
+#define BOOST_COROUTINES_STACK_CONTEXT_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 {
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+struct stack_context
+{
+ typedef void * segments_context[BOOST_COROUTINES_SEGMENTS];
+
+ std::size_t size;
+ void * sp;
+ segments_context segments_ctx;
+#if defined(BOOST_USE_VALGRIND)
+ unsigned valgrind_stack_id;
+#endif
+
+ stack_context() :
+ size( 0), sp( 0), segments_ctx()
+#if defined(BOOST_USE_VALGRIND)
+ , valgrind_stack_id( 0)
+#endif
+ {}
+};
+#else
+struct stack_context
+{
+ std::size_t size;
+ void * sp;
+#if defined(BOOST_USE_VALGRIND)
+ unsigned valgrind_stack_id;
+#endif
+
+ stack_context() :
+ size( 0), sp( 0)
+#if defined(BOOST_USE_VALGRIND)
+ , valgrind_stack_id( 0)
+#endif
+ {}
+};
+#endif
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_STACK_CONTEXT_H
diff --git a/boost/coroutine/stack_traits.hpp b/boost/coroutine/stack_traits.hpp
new file mode 100644
index 0000000000..0e8f25182d
--- /dev/null
+++ b/boost/coroutine/stack_traits.hpp
@@ -0,0 +1,42 @@
+
+// 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
diff --git a/boost/coroutine/standard_stack_allocator.hpp b/boost/coroutine/standard_stack_allocator.hpp
new file mode 100644
index 0000000000..b946fffc4a
--- /dev/null
+++ b/boost/coroutine/standard_stack_allocator.hpp
@@ -0,0 +1,75 @@
+
+// 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
diff --git a/boost/coroutine/symmetric_coroutine.hpp b/boost/coroutine/symmetric_coroutine.hpp
new file mode 100644
index 0000000000..543cae0a37
--- /dev/null
+++ b/boost/coroutine/symmetric_coroutine.hpp
@@ -0,0 +1,35 @@
+
+// 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
diff --git a/boost/coroutine/windows/protected_stack_allocator.hpp b/boost/coroutine/windows/protected_stack_allocator.hpp
new file mode 100644
index 0000000000..293901223b
--- /dev/null
+++ b/boost/coroutine/windows/protected_stack_allocator.hpp
@@ -0,0 +1,87 @@
+
+// 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 <windows.h>
+}
+
+#include <cmath>
+#include <cstddef>
+#include <new>
+
+#include <boost/config.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/stack_traits.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+struct stack_context;
+
+template< typename traitsT >
+struct basic_protected_stack_allocator
+{
+ typedef traitsT traits_type;
+
+ void allocate( stack_context & ctx, std::size_t 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_);
+
+ void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
+ if ( ! limit) throw std::bad_alloc();
+
+ DWORD old_options;
+#if defined(BOOST_DISABLE_ASSERTS)
+ ::VirtualProtect(
+ limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
+#else
+ const BOOL result = ::VirtualProtect(
+ limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
+ BOOST_ASSERT( FALSE != result);
+#endif
+
+ ctx.size = size_;
+ ctx.sp = static_cast< char * >( limit) + ctx.size;
+ }
+
+ 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) );
+
+ void * limit = static_cast< char * >( ctx.sp) - ctx.size;
+ ::VirtualFree( limit, 0, MEM_RELEASE);
+ }
+};
+
+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