summaryrefslogtreecommitdiff
path: root/boost/coroutine/detail/symmetric_coroutine_call.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/coroutine/detail/symmetric_coroutine_call.hpp')
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_call.hpp822
1 files changed, 822 insertions, 0 deletions
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