Created
January 15, 2020 03:57
-
-
Save tchaikov/831e638546aef72eabd9341dbef66818 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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