Skip to content

Instantly share code, notes, and snippets.

@tchaikov
Created January 15, 2020 03:57
Show Gist options
  • Save tchaikov/831e638546aef72eabd9341dbef66818 to your computer and use it in GitHub Desktop.
Save tchaikov/831e638546aef72eabd9341dbef66818 to your computer and use it in GitHub Desktop.
// 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>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
template< typename R >
class pull_coroutine;
template< typename Arg >
class push_coroutine
{
private:
template< typename V, typename X, typename Y, typename Z >
friend class detail::pull_coroutine_object;
typedef detail::push_coroutine_impl< Arg > impl_type;
typedef detail::push_coroutine_synthesized< Arg > synth_type;
typedef detail::parameters< Arg > param_type;
struct dummy {};
impl_type * impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
impl_( & impl)
{ BOOST_ASSERT( impl_); }
public:
push_coroutine() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( pull_coroutine< Arg > &);
explicit push_coroutine( coroutine_fn,
attributes const& = attributes() );
template< typename StackAllocator >
explicit push_coroutine( coroutine_fn,
attributes const&,
StackAllocator);
# endif
template< typename Fn >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const&,
StackAllocator);
#else
template< typename Fn >
explicit push_coroutine( Fn fn,
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( Fn fn,
attributes const&,
StackAllocator);
template< typename Fn >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const&,
StackAllocator);
#endif
~push_coroutine()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
{
push_coroutine tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete(); }
void swap( push_coroutine & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
push_coroutine & operator()( Arg arg)
{
BOOST_ASSERT( * this);
impl_->push( arg);
return * this;
}
class iterator
{
private:
push_coroutine< Arg > * c_;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
iterator() :
c_( 0)
{}
explicit iterator( push_coroutine< Arg > * c) :
c_( c)
{}
iterator & operator=( Arg a)
{
BOOST_ASSERT( c_);
if ( ! ( * c_)( a) ) c_ = 0;
return * this;
}
bool operator==( iterator const& other) const
{ return other.c_ == c_; }
bool operator!=( iterator const& other) const
{ return other.c_ != c_; }
iterator & operator*()
{ return * this; }
iterator & operator++()
{ return * this; }
};
struct const_iterator;
};
template< typename Arg >
class push_coroutine< Arg & >
{
private:
template< typename V, typename X, typename Y, typename Z >
friend class detail::pull_coroutine_object;
typedef detail::push_coroutine_impl< Arg & > impl_type;
typedef detail::push_coroutine_synthesized< Arg & > synth_type;
typedef detail::parameters< Arg & > param_type;
struct dummy {};
impl_type * impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
impl_( & impl)
{ BOOST_ASSERT( impl_); }
public:
push_coroutine() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( pull_coroutine< Arg & > &);
explicit push_coroutine( coroutine_fn,
attributes const& = attributes() );
template< typename StackAllocator >
explicit push_coroutine( coroutine_fn,
attributes const&,
StackAllocator);
# endif
template< typename Fn >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const&,
StackAllocator);
#else
template< typename Fn >
explicit push_coroutine( Fn,
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( Fn,
attributes const&,
StackAllocator);
template< typename Fn >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const&,
StackAllocator);
#endif
~push_coroutine()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
{
push_coroutine tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete(); }
void swap( push_coroutine & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
push_coroutine & operator()( Arg & arg)
{
BOOST_ASSERT( * this);
impl_->push( arg);
return * this;
}
class iterator
{
private:
push_coroutine< Arg & > * c_;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
iterator() :
c_( 0)
{}
explicit iterator( push_coroutine< Arg & > * c) :
c_( c)
{}
iterator & operator=( Arg & a)
{
BOOST_ASSERT( c_);
if ( ! ( * c_)( a) ) c_ = 0;
return * this;
}
bool operator==( iterator const& other) const
{ return other.c_ == c_; }
bool operator!=( iterator const& other) const
{ return other.c_ != c_; }
iterator & operator*()
{ return * this; }
iterator & operator++()
{ return * this; }
};
struct const_iterator;
};
template<>
class push_coroutine< void >
{
private:
template< typename V, typename X, typename Y, typename Z >
friend class detail::pull_coroutine_object;
typedef detail::push_coroutine_impl< void > impl_type;
typedef detail::push_coroutine_synthesized< void > synth_type;
typedef detail::parameters< void > param_type;
struct dummy {};
impl_type * impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
impl_( & impl)
{ BOOST_ASSERT( impl_); }
public:
push_coroutine() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( pull_coroutine< void > &);
explicit push_coroutine( coroutine_fn,
attributes const& = attributes() );
template< typename StackAllocator >
explicit push_coroutine( coroutine_fn,
attributes const&,
StackAllocator);
# endif
template< typename Fn >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const&,
StackAllocator);
#else
template< typename Fn >
explicit push_coroutine( Fn,
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( Fn,
attributes const&,
StackAllocator);
template< typename Fn >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const& = attributes() );
template< typename Fn, typename StackAllocator >
explicit push_coroutine( BOOST_RV_REF( Fn),
attributes const&,
StackAllocator);
#endif
~push_coroutine()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
inline push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
inline push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
{
push_coroutine tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
inline bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete(); }
inline void swap( push_coroutine & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
inline push_coroutine & operator()()
{
BOOST_ASSERT( * this);
impl_->push();
return * this;
}
struct iterator;
struct const_iterator;
};
template< typename R >
class pull_coroutine
{
private:
template< typename V, typename X, typename Y, typename Z >
friend class detail::push_coroutine_object;
typedef detail::pull_coroutine_impl< R > impl_type;
typedef detail::pull_coroutine_synthesized< R > synth_type;
typedef detail::parameters< R > param_type;
struct dummy {};
impl_type * impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
impl_( & impl)
{ BOOST_ASSERT( impl_); }
public:
pull_coroutine() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( push_coroutine< R > &);
explicit pull_coroutine( coroutine_fn fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, coroutine_fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename StackAllocator >
explicit pull_coroutine( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, coroutine_fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
# endif
template< typename Fn >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
#else
template< typename Fn >
explicit pull_coroutine( Fn fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R >, R, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
#endif
~pull_coroutine()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
{
pull_coroutine tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete(); }
void swap( pull_coroutine & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
pull_coroutine & operator()()
{
BOOST_ASSERT( * this);
impl_->pull();
return * this;
}
R get() const
{
BOOST_ASSERT( 0 != impl_);
return impl_->get();
}
class iterator
{
private:
pull_coroutine< R > * c_;
R * val_;
void fetch_()
{
BOOST_ASSERT( c_);
if ( ! ( * c_) )
{
c_ = 0;
val_ = 0;
return;
}
val_ = c_->impl_->get_pointer();
}
void increment_()
{
BOOST_ASSERT( c_);
BOOST_ASSERT( * c_);
( * c_)();
fetch_();
}
public:
typedef std::input_iterator_tag iterator_category;
typedef typename remove_reference< R >::type value_type;
typedef std::ptrdiff_t difference_type;
typedef value_type * pointer;
typedef value_type & reference;
typedef pointer pointer_t;
typedef reference reference_t;
iterator() :
c_( 0), val_( 0)
{}
explicit iterator( pull_coroutine< R > * c) :
c_( c), val_( 0)
{ fetch_(); }
iterator( iterator const& other) :
c_( other.c_), val_( other.val_)
{}
iterator & operator=( iterator const& other)
{
if ( this == & other) return * this;
c_ = other.c_;
val_ = other.val_;
return * this;
}
bool operator==( iterator const& other) const
{ return other.c_ == c_ && other.val_ == val_; }
bool operator!=( iterator const& other) const
{ return other.c_ != c_ || other.val_ != val_; }
iterator & operator++()
{
increment_();
return * this;
}
iterator operator++( int);
reference_t operator*() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return * val_;
}
pointer_t operator->() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return val_;
}
};
class const_iterator
{
private:
pull_coroutine< R > * c_;
R * val_;
void fetch_()
{
BOOST_ASSERT( c_);
if ( ! ( * c_) )
{
c_ = 0;
val_ = 0;
return;
}
val_ = c_->impl_->get_pointer();
}
void increment_()
{
BOOST_ASSERT( c_);
BOOST_ASSERT( * c_);
( * c_)();
fetch_();
}
public:
typedef std::input_iterator_tag iterator_category;
typedef const typename remove_reference< R >::type value_type;
typedef std::ptrdiff_t difference_type;
typedef value_type * pointer;
typedef value_type & reference;
typedef pointer pointer_t;
typedef reference reference_t;
const_iterator() :
c_( 0), val_( 0)
{}
explicit const_iterator( pull_coroutine< R > const* c) :
c_( const_cast< pull_coroutine< R > * >( c) ),
val_( 0)
{ fetch_(); }
const_iterator( const_iterator const& other) :
c_( other.c_), val_( other.val_)
{}
const_iterator & operator=( const_iterator const& other)
{
if ( this == & other) return * this;
c_ = other.c_;
val_ = other.val_;
return * this;
}
bool operator==( const_iterator const& other) const
{ return other.c_ == c_ && other.val_ == val_; }
bool operator!=( const_iterator const& other) const
{ return other.c_ != c_ || other.val_ != val_; }
const_iterator & operator++()
{
increment_();
return * this;
}
const_iterator operator++( int);
reference_t operator*() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return * val_;
}
pointer_t operator->() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return val_;
}
};
friend class iterator;
friend class const_iterator;
};
template< typename R >
class pull_coroutine< R & >
{
private:
template< typename V, typename X, typename Y, typename Z >
friend class detail::push_coroutine_object;
typedef detail::pull_coroutine_impl< R & > impl_type;
typedef detail::pull_coroutine_synthesized< R & > synth_type;
typedef detail::parameters< R & > param_type;
struct dummy {};
impl_type * impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
impl_( & impl)
{ BOOST_ASSERT( impl_); }
public:
pull_coroutine() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( push_coroutine< R & > &);
explicit pull_coroutine( coroutine_fn fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, coroutine_fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename StackAllocator >
explicit pull_coroutine( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, coroutine_fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
# endif
template< typename Fn >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
#else
template< typename Fn >
explicit pull_coroutine( Fn fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< R & >, R &, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
#endif
~pull_coroutine()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
{
pull_coroutine tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete(); }
void swap( pull_coroutine & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
pull_coroutine & operator()()
{
BOOST_ASSERT( * this);
impl_->pull();
return * this;
}
R & get() const
{ return impl_->get(); }
class iterator
{
private:
pull_coroutine< R & > * c_;
R * val_;
void fetch_()
{
BOOST_ASSERT( c_);
if ( ! ( * c_) )
{
c_ = 0;
val_ = 0;
return;
}
val_ = c_->impl_->get_pointer();
}
void increment_()
{
BOOST_ASSERT( c_);
BOOST_ASSERT( * c_);
( * c_)();
fetch_();
}
public:
typedef std::input_iterator_tag iterator_category;
typedef typename remove_reference< R >::type value_type;
typedef std::ptrdiff_t difference_type;
typedef value_type * pointer;
typedef value_type & reference;
typedef pointer pointer_t;
typedef reference reference_t;
iterator() :
c_( 0), val_( 0)
{}
explicit iterator( pull_coroutine< R & > * c) :
c_( c), val_( 0)
{ fetch_(); }
iterator( iterator const& other) :
c_( other.c_), val_( other.val_)
{}
iterator & operator=( iterator const& other)
{
if ( this == & other) return * this;
c_ = other.c_;
val_ = other.val_;
return * this;
}
bool operator==( iterator const& other) const
{ return other.c_ == c_ && other.val_ == val_; }
bool operator!=( iterator const& other) const
{ return other.c_ != c_ || other.val_ != val_; }
iterator & operator++()
{
increment_();
return * this;
}
iterator operator++( int);
reference_t operator*() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return * val_;
}
pointer_t operator->() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return val_;
}
};
class const_iterator
{
private:
pull_coroutine< R & > * c_;
R * val_;
void fetch_()
{
BOOST_ASSERT( c_);
if ( ! ( * c_) )
{
c_ = 0;
val_ = 0;
return;
}
val_ = c_->impl_->get_pointer();
}
void increment_()
{
BOOST_ASSERT( c_);
BOOST_ASSERT( * c_);
( * c_)();
fetch_();
}
public:
typedef std::input_iterator_tag iterator_category;
typedef const typename remove_reference< R >::type value_type;
typedef std::ptrdiff_t difference_type;
typedef value_type * pointer;
typedef value_type & reference;
typedef pointer pointer_t;
typedef reference reference_t;
const_iterator() :
c_( 0), val_( 0)
{}
explicit const_iterator( pull_coroutine< R & > const* c) :
c_( const_cast< pull_coroutine< R & > * >( c) ),
val_( 0)
{ fetch_(); }
const_iterator( const_iterator const& other) :
c_( other.c_), val_( other.val_)
{}
const_iterator & operator=( const_iterator const& other)
{
if ( this == & other) return * this;
c_ = other.c_;
val_ = other.val_;
return * this;
}
bool operator==( const_iterator const& other) const
{ return other.c_ == c_ && other.val_ == val_; }
bool operator!=( const_iterator const& other) const
{ return other.c_ != c_ || other.val_ != val_; }
const_iterator & operator++()
{
increment_();
return * this;
}
const_iterator operator++( int);
reference_t operator*() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return * val_;
}
pointer_t operator->() const
{
if ( ! val_)
boost::throw_exception(
invalid_result() );
return val_;
}
};
friend class iterator;
friend class const_iterator;
};
template<>
class pull_coroutine< void >
{
private:
template< typename V, typename X, typename Y, typename Z >
friend class detail::push_coroutine_object;
typedef detail::pull_coroutine_impl< void > impl_type;
typedef detail::pull_coroutine_synthesized< void > synth_type;
typedef detail::parameters< void > param_type;
struct dummy {};
impl_type * impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
impl_( & impl)
{ BOOST_ASSERT( impl_); }
public:
pull_coroutine() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( push_coroutine< void > &);
explicit pull_coroutine( coroutine_fn fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, coroutine_fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename StackAllocator >
explicit pull_coroutine( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, coroutine_fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
# endif
template< typename Fn >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
#else
template< typename Fn >
explicit pull_coroutine( Fn fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
template< typename Fn, typename StackAllocator >
explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::pull_coroutine_object<
push_coroutine< void >, void, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
impl_->pull();
}
#endif
~pull_coroutine()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
inline pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
inline pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
{
pull_coroutine tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
inline bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete(); }
inline void swap( pull_coroutine & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
inline pull_coroutine & operator()()
{
BOOST_ASSERT( * this);
impl_->pull();
return * this;
}
struct iterator;
struct const_iterator;
};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
template< typename Arg >
push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, coroutine_fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename StackAllocator >
push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, coroutine_fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, coroutine_fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename StackAllocator >
push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, coroutine_fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
inline push_coroutine< void >::push_coroutine( coroutine_fn fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, coroutine_fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename StackAllocator >
push_coroutine< void >::push_coroutine( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, coroutine_fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
# endif
template< typename Arg >
template< typename Fn >
push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn, typename StackAllocator >
push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn >
push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn, typename StackAllocator >
push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn >
push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#else
template< typename Arg >
template< typename Fn >
push_coroutine< Arg >::push_coroutine( Fn fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn, typename StackAllocator >
push_coroutine< Arg >::push_coroutine( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn >
push_coroutine< Arg & >::push_coroutine( Fn fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn, typename StackAllocator >
push_coroutine< Arg & >::push_coroutine( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn >
push_coroutine< void >::push_coroutine( Fn fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
push_coroutine< void >::push_coroutine( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn >
push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn, typename StackAllocator >
push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg >, Arg, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn >
push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Arg >
template< typename Fn, typename StackAllocator >
push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn >
push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
stack_allocator stack_alloc;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, Fn, stack_allocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef detail::push_coroutine_object<
pull_coroutine< void >, void, Fn, StackAllocator
> object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#endif
template< typename R >
void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
{ l.swap( r); }
template< typename Arg >
void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
{ l.swap( r); }
template< typename R >
typename pull_coroutine< R >::iterator
range_begin( pull_coroutine< R > & c)
{ return typename pull_coroutine< R >::iterator( & c); }
template< typename R >
typename pull_coroutine< R >::const_iterator
range_begin( pull_coroutine< R > const& c)
{ return typename pull_coroutine< R >::const_iterator( & c); }
template< typename R >
typename pull_coroutine< R >::iterator
range_end( pull_coroutine< R > &)
{ return typename pull_coroutine< R >::iterator(); }
template< typename R >
typename pull_coroutine< R >::const_iterator
range_end( pull_coroutine< R > const&)
{ return typename pull_coroutine< R >::const_iterator(); }
template< typename Arg >
typename push_coroutine< Arg >::iterator
range_begin( push_coroutine< Arg > & c)
{ return typename push_coroutine< Arg >::iterator( & c); }
template< typename Arg >
typename push_coroutine< Arg >::iterator
range_end( push_coroutine< Arg > &)
{ return typename push_coroutine< Arg >::iterator(); }
template< typename T >
struct asymmetric_coroutine
{
typedef push_coroutine< T > push_type;
typedef pull_coroutine< T > pull_type;
};
// deprecated
template< typename T >
struct coroutine
{
typedef push_coroutine< T > push_type;
typedef pull_coroutine< T > pull_type;
};
template< typename R >
typename pull_coroutine< R >::iterator
begin( pull_coroutine< R > & c)
{ return boost::begin( c); }
template< typename R >
typename pull_coroutine< R >::const_iterator
begin( pull_coroutine< R > const& 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 pull_coroutine< R >::const_iterator
end( pull_coroutine< R > const& 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment