coroutine: support for segmented stacks added

[SVN r82840]
This commit is contained in:
Oliver Kowalke
2013-02-12 19:01:29 +00:00
parent d16dfc92e5
commit 3bf228523c
39 changed files with 2296 additions and 1251 deletions

View File

@@ -12,7 +12,6 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/move/move.hpp>
#include <boost/range.hpp>
#include <boost/static_assert.hpp>
@@ -25,6 +24,7 @@
#include <boost/coroutine/attributes.hpp>
#include <boost/coroutine/detail/arg.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/coroutine_base.hpp>
#include <boost/coroutine/detail/coroutine_get.hpp>
#include <boost/coroutine/detail/coroutine_object.hpp>
@@ -118,7 +118,7 @@ private:
BOOST_MOVABLE_BUT_NOT_COPYABLE( coroutine)
template< typename Allocator >
coroutine( context::fcontext_t * callee,
coroutine( detail::coroutine_context const& callee,
bool unwind, bool preserve_fpu,
Allocator const& alloc) :
detail::coroutine_op<
@@ -665,7 +665,7 @@ private:
BOOST_MOVABLE_BUT_NOT_COPYABLE( coroutine)
template< typename Allocator >
coroutine( context::fcontext_t * callee,
coroutine( detail::coroutine_context const& callee,
bool unwind, bool preserve_fpu,
Allocator const& alloc) :
detail::coroutine_op<

View File

@@ -39,4 +39,11 @@
# include <boost/config/auto_link.hpp>
#endif
#if defined(BOOST_USE_SEGMENTED_STACKS)
# if ! (defined(__GNUC__) && __GNUC__ > 3 && __GNUC_MINOR__ > 6)
# error "compiler does not support segmented stacks"
# endif
# define BOOST_COROUTINES_SEGMENTS 10
#endif
#endif // BOOST_COROUTINES_DETAIL_CONFIG_H

View File

@@ -16,6 +16,7 @@
#include <boost/utility.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/coroutine_base_resume.hpp>
#include <boost/coroutine/detail/flags.hpp>
@@ -25,6 +26,9 @@
namespace boost {
namespace coroutines {
struct stack_context;
namespace detail {
template< typename Signature >
@@ -45,17 +49,35 @@ private:
template< typename X, typename Y, typename Z, typename A, typename B, typename C, int >
friend class coroutine_object;
unsigned int use_count_;
context::fcontext_t caller_;
context::fcontext_t * callee_;
int flags_;
exception_ptr except_;
unsigned int use_count_;
coroutine_context caller_;
coroutine_context callee_;
int flags_;
exception_ptr except_;
protected:
virtual void deallocate_object() = 0;
public:
coroutine_base( context::fcontext_t * callee, bool unwind, bool preserve_fpu) :
coroutine_base( coroutine_context::ctx_fn fn, stack_context * stack_ctx,
bool unwind, bool preserve_fpu) :
coroutine_base_resume<
Signature,
coroutine_base< Signature >,
typename function_traits< Signature >::result_type,
function_traits< Signature >::arity
>(),
use_count_( 0),
caller_(),
callee_( fn, stack_ctx),
flags_( 0),
except_()
{
if ( unwind) flags_ |= flag_force_unwind;
if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
coroutine_base( coroutine_context const& callee, bool unwind, bool preserve_fpu) :
coroutine_base_resume<
Signature,
coroutine_base< Signature >,

View File

@@ -22,6 +22,7 @@
#include <boost/coroutine/detail/arg.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/exceptions.hpp>
#include <boost/coroutine/detail/holder.hpp>
@@ -42,16 +43,15 @@ class coroutine_base_resume< Signature, D, void, 0 >
public:
void resume()
{
BOOST_ASSERT( static_cast< D * >( this)->callee_);
holder< void > hldr_to( & static_cast< D * >( this)->caller_);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
hldr_to.ctx,
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
static_cast< D * >( this)->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
hldr_to.ctx->jump(
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
BOOST_ASSERT( hldr_from->ctx);
static_cast< D * >( this)->callee_ = * hldr_from->ctx;
if ( hldr_from->force_unwind) throw forced_unwind();
if ( static_cast< D * >( this)->except_)
rethrow_exception( static_cast< D * >( this)->except_);
@@ -66,16 +66,16 @@ public:
{
BOOST_ASSERT( static_cast< D * >( this));
BOOST_ASSERT( ! static_cast< D * >( this)->is_complete() );
BOOST_ASSERT( static_cast< D * >( this)->callee_);
holder< void > hldr_to( & static_cast< D * >( this)->caller_);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
hldr_to.ctx,
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
static_cast< D * >( this)->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
hldr_to.ctx->jump(
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
BOOST_ASSERT( hldr_from->ctx);
static_cast< D * >( this)->callee_ = * hldr_from->ctx;
result_ = hldr_from->data;
if ( hldr_from->force_unwind) throw forced_unwind();
if ( static_cast< D * >( this)->except_)
@@ -99,16 +99,16 @@ public:
{
BOOST_ASSERT( static_cast< D * >( this));
BOOST_ASSERT( ! static_cast< D * >( this)->is_complete() );
BOOST_ASSERT( static_cast< D * >( this)->callee_);
holder< arg_type > hldr_to( & static_cast< D * >( this)->caller_, a1);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
hldr_to.ctx,
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
static_cast< D * >( this)->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
hldr_to.ctx->jump(
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
BOOST_ASSERT( hldr_from->ctx);
static_cast< D * >( this)->callee_ = * hldr_from->ctx;
if ( hldr_from->force_unwind) throw forced_unwind();
if ( static_cast< D * >( this)->except_)
rethrow_exception( static_cast< D * >( this)->except_);
@@ -125,17 +125,17 @@ public:
{
BOOST_ASSERT( static_cast< D * >( this));
BOOST_ASSERT( ! static_cast< D * >( this)->is_complete() );
BOOST_ASSERT( static_cast< D * >( this)->callee_);
context::fcontext_t caller;
coroutine_context caller;
holder< arg_type > hldr_to( & static_cast< D * >( this)->caller_, a1);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
hldr_to.ctx,
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
static_cast< D * >( this)->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
hldr_to.ctx->jump(
static_cast< D * >( this)->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
static_cast< D * >( this)->preserve_fpu() ) ) );
BOOST_ASSERT( hldr_from->ctx);
static_cast< D * >( this)->callee_ = * hldr_from->ctx;
result_ = hldr_from->data;
if ( hldr_from->force_unwind) throw forced_unwind();
if ( static_cast< D * >( this)->except_)
@@ -167,18 +167,18 @@ public: \
{ \
BOOST_ASSERT( static_cast< D * >( this)); \
BOOST_ASSERT( ! static_cast< D * >( this)->is_complete() ); \
BOOST_ASSERT( static_cast< D * >( this)->callee_); \
\
holder< arg_type > hldr_to( \
& static_cast< D * >( this)->caller_, \
arg_type(BOOST_COROUTINE_BASE_RESUME_VALS(n) ) ); \
holder< void > * hldr_from( \
reinterpret_cast< holder< void > * >( context::jump_fcontext( \
hldr_to.ctx, \
static_cast< D * >( this)->callee_, \
reinterpret_cast< intptr_t >( & hldr_to), \
static_cast< D * >( this)->preserve_fpu() ) ) ); \
static_cast< D * >( this)->callee_ = hldr_from->ctx; \
reinterpret_cast< holder< void > * >( \
hldr_to.ctx->jump( \
static_cast< D * >( this)->callee_, \
reinterpret_cast< intptr_t >( & hldr_to), \
static_cast< D * >( this)->preserve_fpu() ) ) ); \
BOOST_ASSERT( hldr_from->ctx); \
static_cast< D * >( this)->callee_ = * hldr_from->ctx; \
if ( hldr_from->force_unwind) throw forced_unwind(); \
if ( static_cast< D * >( this)->except_) \
rethrow_exception( static_cast< D * >( this)->except_); \
@@ -195,18 +195,18 @@ public: \
{ \
BOOST_ASSERT( static_cast< D * >( this)); \
BOOST_ASSERT( ! static_cast< D * >( this)->is_complete() ); \
BOOST_ASSERT( static_cast< D * >( this)->callee_); \
\
holder< arg_type > hldr_to( \
& static_cast< D * >( this)->caller_, \
arg_type(BOOST_COROUTINE_BASE_RESUME_VALS(n) ) ); \
holder< Result > * hldr_from( \
reinterpret_cast< holder< Result > * >( context::jump_fcontext( \
hldr_to.ctx, \
static_cast< D * >( this)->callee_, \
reinterpret_cast< intptr_t >( & hldr_to), \
static_cast< D * >( this)->preserve_fpu() ) ) ); \
static_cast< D * >( this)->callee_ = hldr_from->ctx; \
reinterpret_cast< holder< Result > * >( \
hldr_to.ctx->jump( \
static_cast< D * >( this)->callee_, \
reinterpret_cast< intptr_t >( & hldr_to), \
static_cast< D * >( this)->preserve_fpu() ) ) ); \
BOOST_ASSERT( hldr_from->ctx); \
static_cast< D * >( this)->callee_ = * hldr_from->ctx; \
result_ = hldr_from->data; \
if ( hldr_from->force_unwind) throw forced_unwind(); \
if ( static_cast< D * >( this)->except_) \

View File

@@ -29,7 +29,7 @@ public:
coroutine_caller< Signature, Allocator >
>::other allocator_t;
coroutine_caller( context::fcontext_t * callee, bool unwind, bool preserve_fpu,
coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu,
allocator_t const& alloc) BOOST_NOEXCEPT :
coroutine_base< Signature >( callee, unwind, preserve_fpu),
alloc_( alloc)

View File

@@ -0,0 +1,63 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_COROUTINES_DETAIL_COROUTINE_CONTEXT_H
#define BOOST_COROUTINES_DETAIL_COROUTINE_CONTEXT_H
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/utility.hpp>
#include <boost/coroutine/detail/config.hpp>
#include "boost/coroutine/stack_context.hpp"
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
#if defined(BOOST_USE_SEGMENTED_STACKS)
extern "C" void *__splitstack_makecontext(
std::size_t, void * [BOOST_COROUTINES_SEGMENTS], std::size_t *);
#endif
namespace boost {
namespace coroutines {
namespace detail {
class BOOST_COROUTINES_DECL coroutine_context : private noncopyable,
private context::fcontext_t,
private stack_context
{
private:
stack_context * stack_ctx_;
context::fcontext_t * ctx_;
public:
typedef void( * ctx_fn)( intptr_t);
coroutine_context();
explicit coroutine_context( ctx_fn, stack_context *);
coroutine_context( coroutine_context const&);
coroutine_context& operator=( coroutine_context const&);
intptr_t jump( coroutine_context &, intptr_t = 0, bool = true);
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_COROUTINE_CONTEXT_H

View File

@@ -7,6 +7,8 @@
#ifndef BOOST_COROUTINES_DETAIL_COROUTINE_OBJECT_H
#define BOOST_COROUTINES_DETAIL_COROUTINE_OBJECT_H
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -15,6 +17,7 @@
#include <boost/ref.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/utility.hpp>
#include <boost/coroutine/attributes.hpp>
#include <boost/coroutine/detail/arg.hpp>
@@ -25,6 +28,7 @@
#include <boost/coroutine/detail/holder.hpp>
#include <boost/coroutine/detail/param.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -55,6 +59,25 @@ void trampoline2( intptr_t vp)
coro->run( arg);
}
template< typename StackAllocator >
struct stack_tuple
{
coroutines::stack_context stack_ctx;
StackAllocator stack_alloc;
stack_tuple( StackAllocator const& stack_alloc_, std::size_t size) :
stack_ctx(),
stack_alloc( stack_alloc_)
{
stack_alloc.allocate( stack_ctx, size);
}
~stack_tuple()
{
stack_alloc.deallocate( stack_ctx);
}
};
template<
typename Signature,
typename Fn, typename StackAllocator, typename Allocator,

View File

@@ -11,6 +11,7 @@ template<
typename Result
>
class coroutine_object< Signature, Fn, StackAllocator, Allocator, Caller, Result, 0 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -21,12 +22,11 @@ public:
>::other allocator_t;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -40,28 +40,28 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
holder< Result > hldr_to( & caller);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
hldr_to.ctx, callee,
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -73,10 +73,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -86,10 +86,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< void > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< void > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -101,58 +101,52 @@ public:
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#else
coroutine_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#endif
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
@@ -167,6 +161,7 @@ template<
typename Result
>
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -177,12 +172,11 @@ public:
>::other allocator_t;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -196,28 +190,28 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
holder< Result > hldr_to( & caller);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
hldr_to.ctx, callee,
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -229,10 +223,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -242,10 +236,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< void > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< void > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -256,27 +250,25 @@ public:
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
@@ -291,6 +283,7 @@ template<
typename Result
>
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -301,12 +294,11 @@ public:
>::other allocator_t;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -320,10 +312,11 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
@@ -331,17 +324,16 @@ private:
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
holder< Result > hldr_to( & caller);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
hldr_to.ctx, callee,
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -353,10 +345,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -366,10 +358,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< void > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< void > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -380,22 +372,20 @@ public:
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()

View File

@@ -11,6 +11,7 @@ template<
typename Result
>
class coroutine_object< Signature, Fn, StackAllocator, Allocator, Caller, Result, 1 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -22,12 +23,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -41,11 +41,12 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
@@ -53,31 +54,31 @@ private:
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< Result > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -89,10 +90,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -102,10 +103,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -117,109 +118,97 @@ public:
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#else
coroutine_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( Fn fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#endif
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -235,6 +224,7 @@ template<
typename Result
>
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 1 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -246,12 +236,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -265,11 +254,12 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
@@ -277,31 +267,31 @@ private:
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< Result > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -313,10 +303,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -326,10 +316,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -340,48 +330,44 @@ public:
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( reference_wrapper< Fn > fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -397,6 +383,7 @@ template<
typename Result
>
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 1 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -408,12 +395,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -427,11 +413,12 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
@@ -439,31 +426,31 @@ private:
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< Result > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -475,10 +462,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -488,10 +475,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -502,48 +489,44 @@ public:
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( const reference_wrapper< Fn > fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}

View File

@@ -11,6 +11,7 @@ template<
typename Result, int arity
>
class coroutine_object :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -22,12 +23,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -41,11 +41,12 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
@@ -53,31 +54,31 @@ private:
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< Result > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -89,10 +90,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -102,10 +103,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -117,109 +118,97 @@ public:
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#else
coroutine_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( Fn fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#endif
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -235,6 +224,7 @@ template<
typename Result, int arity
>
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, arity > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -246,12 +236,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -265,11 +254,12 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
@@ -277,31 +267,31 @@ private:
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< Result > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -313,10 +303,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -326,10 +316,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -340,48 +330,44 @@ public:
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( reference_wrapper< Fn > fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -397,6 +383,7 @@ template<
typename Result, int arity
>
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, arity > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -408,12 +395,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -427,11 +413,12 @@ private:
void enter_()
{
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
@@ -439,31 +426,31 @@ private:
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< Result > * hldr_from(
reinterpret_cast< holder< Result > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< Result > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
this->result_ = hldr_from->data;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< Result > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -475,10 +462,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< Result > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -488,10 +475,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -502,48 +489,44 @@ public:
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( const reference_wrapper< Fn > fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}

View File

@@ -10,6 +10,7 @@ template<
typename Caller
>
class coroutine_object< Signature, Fn, StackAllocator, Allocator, Caller, void, 0 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -20,12 +21,11 @@ public:
>::other allocator_t;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -39,27 +39,27 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -71,10 +71,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -84,10 +84,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< void > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< void > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -99,58 +99,52 @@ public:
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#else
coroutine_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->pbase_type::stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#endif
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
@@ -164,6 +158,7 @@ template<
typename Caller
>
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, 0 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -174,12 +169,11 @@ public:
>::other allocator_t;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -193,27 +187,27 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -225,10 +219,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -238,10 +232,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< void > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< void > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -252,27 +246,25 @@ public:
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
@@ -286,6 +278,7 @@ template<
typename Caller
>
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, 0 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -296,12 +289,11 @@ public:
>::other allocator_t;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -315,27 +307,27 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr_to( & caller);
context::jump_fcontext(
hldr_to.ctx, callee,
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
@@ -347,10 +339,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -360,10 +352,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< void > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< void > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -374,27 +366,25 @@ public:
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}

View File

@@ -10,6 +10,7 @@ template<
typename Caller
>
class coroutine_object< Signature, Fn, StackAllocator, Allocator, Caller, void, 1 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -21,12 +22,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -40,42 +40,43 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr( & caller);
context::jump_fcontext(
hldr.ctx, callee,
( intptr_t) & hldr,
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -86,10 +87,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -99,10 +100,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -114,109 +115,97 @@ public:
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#else
coroutine_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( Fn fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#endif
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -231,6 +220,7 @@ template<
typename Caller
>
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, 1 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -242,12 +232,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -261,42 +250,43 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr( & caller);
context::jump_fcontext(
hldr.ctx, callee,
( intptr_t) & hldr,
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -307,10 +297,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -320,10 +310,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -334,15 +324,13 @@ public:
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
@@ -350,33 +338,31 @@ public:
typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -391,6 +377,7 @@ template<
typename Caller
>
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, 1 > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -402,12 +389,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -421,42 +407,43 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr( & caller);
context::jump_fcontext(
hldr.ctx, callee,
( intptr_t) & hldr,
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -467,10 +454,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -480,10 +467,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -494,15 +481,13 @@ public:
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
@@ -510,33 +495,31 @@ public:
typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}

View File

@@ -11,6 +11,7 @@ template<
int arity
>
class coroutine_object< Signature, Fn, StackAllocator, Allocator, Caller, void, arity > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -22,12 +23,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -41,42 +41,43 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr( & caller);
context::jump_fcontext(
hldr.ctx, callee,
( intptr_t) & hldr,
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -87,10 +88,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -100,10 +101,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -115,109 +116,97 @@ public:
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#else
coroutine_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( Fn fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( BOOST_RV_REF( Fn) fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
#endif
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -233,6 +222,7 @@ template<
int arity
>
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, arity > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -244,12 +234,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -263,42 +252,43 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr( & caller);
context::jump_fcontext(
hldr.ctx, callee,
( intptr_t) & hldr,
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -309,10 +299,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -322,10 +312,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -336,48 +326,44 @@ public:
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( reference_wrapper< Fn > fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}
@@ -393,6 +379,7 @@ template<
int arity
>
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, arity > :
private stack_tuple< StackAllocator >,
public coroutine_base< Signature >
{
public:
@@ -404,12 +391,11 @@ public:
typedef typename arg< Signature >::type arg_type;
private:
typedef stack_tuple< StackAllocator > pbase_type;
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
Fn fn_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
@@ -423,42 +409,43 @@ private:
void enter_()
{
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void enter_( typename detail::param< arg_type >::type arg)
{
tuple< coroutine_object *,
typename detail::param< arg_type >::type
typename detail::param< arg_type >::type
> tpl( this, arg);
holder< void > * hldr_from(
reinterpret_cast< holder< void > * >( context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = hldr_from->ctx;
reinterpret_cast< holder< void > * >(
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & tpl),
this->preserve_fpu() ) ) );
this->callee_ = * hldr_from->ctx;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t caller;
coroutine_context callee;
coroutine_context caller;
try
{
fn_( c);
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
holder< void > hldr( & caller);
context::jump_fcontext(
hldr.ctx, callee,
( intptr_t) & hldr,
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -469,10 +456,10 @@ private:
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
holder< void > hldr_to( & caller);
caller.jump(
callee,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -482,10 +469,10 @@ private:
BOOST_ASSERT( ! this->is_complete() );
this->flags_ |= flag_unwind_stack;
holder< arg_type > hldr( & this->caller_, true);
context::jump_fcontext(
hldr.ctx, this->callee_,
reinterpret_cast< intptr_t >( & hldr),
holder< arg_type > hldr_to( & this->caller_, true);
this->caller_.jump(
this->callee_,
reinterpret_cast< intptr_t >( & hldr_to),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
@@ -496,48 +483,44 @@ public:
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
trampoline1< coroutine_object >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
coroutine_object( const reference_wrapper< Fn > fn, typename detail::param< arg_type >::type arg, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
pbase_type( stack_alloc, attr.size),
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
trampoline2< coroutine_object, typename detail::param< arg_type >::type >,
& this->stack_ctx,
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( base_type::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_( arg); }
~coroutine_object()
{
if ( ! this->is_complete() && this->force_unwind() ) unwind_stack_();
stack_alloc_.deallocate( stack_.sp, stack_.size);
if ( ! this->is_complete() && this->force_unwind() )
unwind_stack_();
}
void run()
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
run_( c);
}
void run( typename detail::param< arg_type >::type arg)
{
Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
c.impl_->result_ = arg;
run_( c);
}

View File

@@ -11,6 +11,8 @@
#include <boost/config.hpp>
#include <boost/optional.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
@@ -22,19 +24,19 @@ namespace detail {
template< typename Data >
struct holder
{
context::fcontext_t * ctx;
coroutine_context * ctx;
optional< Data > data;
bool force_unwind;
holder( context::fcontext_t * ctx_) :
explicit holder( coroutine_context * ctx_) :
ctx( ctx_), data(), force_unwind( false)
{ BOOST_ASSERT( ctx); }
holder( context::fcontext_t * ctx_, Data data_) :
explicit holder( coroutine_context * ctx_, Data data_) :
ctx( ctx_), data( data_), force_unwind( false)
{ BOOST_ASSERT( ctx); }
holder( context::fcontext_t * ctx_, bool force_unwind_) :
explicit holder( coroutine_context * ctx_, bool force_unwind_) :
ctx( ctx_), data(), force_unwind( force_unwind_)
{
BOOST_ASSERT( ctx);
@@ -59,10 +61,10 @@ struct holder
template<>
struct holder< void >
{
context::fcontext_t * ctx;
bool force_unwind;
coroutine_context * ctx;
bool force_unwind;
holder( context::fcontext_t * ctx_, bool force_unwind_ = false) :
explicit holder( coroutine_context * ctx_, bool force_unwind_ = false) :
ctx( ctx_), force_unwind( force_unwind_)
{ BOOST_ASSERT( ctx); }

View File

@@ -0,0 +1,51 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_COROUTINES_DETAIL_SEGMENTED_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_DETAIL_SEGMENTED_STACK_ALLOCATOR_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
struct stack_context;
namespace detail {
#if defined(BOOST_USE_SEGMENTED_STACKS)
class segmented_stack_allocator
{
public:
static bool is_stack_unbound();
static std::size_t default_stacksize();
static std::size_t minimum_stacksize();
static std::size_t maximum_stacksize();
void allocate( stack_context &, std::size_t size);
void deallocate( stack_context &);
};
#endif
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_SEGMENTED_STACK_ALLOCATOR_H

View File

@@ -1,173 +0,0 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H
#include <boost/config.hpp>
extern "C" {
#include <fcntl.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
}
//#if _POSIX_C_SOURCE >= 200112L
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstring>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/context/detail/config.hpp>
#if !defined (SIGSTKSZ)
# define SIGSTKSZ (8 * 1024)
# define UDEF_SIGSTKSZ
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
inline
std::size_t pagesize()
{
// conform to POSIX.1-2001
static std::size_t size = ::sysconf( _SC_PAGESIZE);
return size;
}
inline
rlimit stacksize_limit_()
{
rlimit limit;
// conforming to POSIX.1-2001
#if defined(BOOST_DISABLE_ASSERTS)
::getrlimit( RLIMIT_STACK, & limit);
#else
const int result = ::getrlimit( RLIMIT_STACK, & limit);
BOOST_ASSERT( 0 == result);
#endif
return limit;
}
inline
rlimit stacksize_limit()
{
static rlimit limit = stacksize_limit_();
return limit;
}
inline
std::size_t page_count( std::size_t stacksize)
{
return static_cast< std::size_t >(
std::ceil(
static_cast< float >( stacksize) / pagesize() ) );
}
class stack_allocator
{
public:
static bool is_stack_unbound()
{ return RLIM_INFINITY == stacksize_limit().rlim_max; }
static std::size_t default_stacksize()
{
std::size_t size = 8 * minimum_stacksize();
if ( is_stack_unbound() ) return size;
BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
return maximum_stacksize() == size
? size
: (std::min)( size, maximum_stacksize() );
}
static std::size_t minimum_stacksize()
{ return SIGSTKSZ + sizeof( context::fcontext_t) + 15; }
static std::size_t maximum_stacksize()
{
BOOST_ASSERT( ! is_stack_unbound() );
return static_cast< std::size_t >( stacksize_limit().rlim_max);
}
void * allocate( std::size_t size) const
{
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages( page_count( size) + 1); // add one guard page
const std::size_t size_( pages * pagesize() );
BOOST_ASSERT( 0 < size && 0 < size_);
const int fd( ::open("/dev/zero", O_RDONLY) );
BOOST_ASSERT( -1 != fd);
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
void * limit =
# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
# else
::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
# endif
::close( fd);
if ( ! limit) throw std::bad_alloc();
std::memset( limit, size_, '\0');
// conforming to POSIX.1-2001
#if defined(BOOST_DISABLE_ASSERTS)
::mprotect( limit, pagesize(), PROT_NONE);
#else
const int result( ::mprotect( limit, pagesize(), PROT_NONE) );
BOOST_ASSERT( 0 == result);
#endif
return static_cast< char * >( limit) + size_;
}
void deallocate( void * vp, std::size_t size) const
{
BOOST_ASSERT( vp);
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages = page_count( size) + 1;
const std::size_t size_ = pages * pagesize();
BOOST_ASSERT( 0 < size && 0 < size_);
void * limit = static_cast< char * >( vp) - size_;
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
::munmap( limit, size_);
}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#ifdef UDEF_SIGSTKSZ
# undef SIGSTKSZ
#endif
//#endif
#endif // BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H

View File

@@ -1,163 +0,0 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H
#include <boost/config.hpp>
extern "C" {
#include <windows.h>
}
//#if defined (BOOST_WINDOWS) || _POSIX_C_SOURCE >= 200112L
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstring>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/context/detail/config.hpp>
#include <boost/context/fcontext.hpp>
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4244 4267)
# endif
// x86_64
// test x86_64 before i386 because icc might
// define __i686__ for x86_64 too
#if defined(__x86_64__) || defined(__x86_64) \
|| defined(__amd64__) || defined(__amd64) \
|| defined(_M_X64) || defined(_M_AMD64)
// Windows seams not to provide a constant or function
// telling the minimal stacksize
# define MIN_STACKSIZE 8 * 1024
#else
# define MIN_STACKSIZE 4 * 1024
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
inline
SYSTEM_INFO system_info_()
{
SYSTEM_INFO si;
::GetSystemInfo( & si);
return si;
}
inline
SYSTEM_INFO system_info()
{
static SYSTEM_INFO si = system_info_();
return si;
}
inline
std::size_t pagesize()
{ return static_cast< std::size_t >( system_info().dwPageSize); }
inline
std::size_t page_count( std::size_t stacksize)
{
return static_cast< std::size_t >(
std::ceil(
static_cast< float >( stacksize) / pagesize() ) );
}
class stack_allocator
{
public:
// Windows seams not to provide a limit for the stacksize
static bool is_stack_unbound()
{ return true; }
static std::size_t default_stacksize()
{
std::size_t size = 64 * 1024; // 64 kB
if ( is_stack_unbound() )
return (std::max)( size, minimum_stacksize() );
BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
return maximum_stacksize() == minimum_stacksize()
? minimum_stacksize()
: ( std::min)( size, maximum_stacksize() );
}
// because Windows seams not to provide a limit for minimum stacksize
static std::size_t minimum_stacksize()
{ return MIN_STACKSIZE; }
// because Windows seams not to provide a limit for maximum stacksize
// maximum_stacksize() can never be called (pre-condition ! is_stack_unbound() )
static std::size_t maximum_stacksize()
{
BOOST_ASSERT( ! is_stack_unbound() );
return 1 * 1024 * 1024 * 1024; // 1GB
}
void * allocate( std::size_t size) const
{
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages( page_count( size) + 1); // add one guard page
const std::size_t size_ = pages * pagesize();
BOOST_ASSERT( 0 < size && 0 < size_);
void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
if ( ! limit) throw std::bad_alloc();
std::memset( limit, size_, '\0');
DWORD old_options;
#if defined(BOOST_DISABLE_ASSERTS)
::VirtualProtect(
limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
#else
const BOOL result = ::VirtualProtect(
limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
BOOST_ASSERT( FALSE != result);
#endif
return static_cast< char * >( limit) + size_;
}
void deallocate( void * vp, std::size_t size) const
{
BOOST_ASSERT( vp);
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages = page_count( size) + 1;
const std::size_t size_ = pages * pagesize();
BOOST_ASSERT( 0 < size && 0 < size_);
void * limit = static_cast< char * >( vp) - size_;
::VirtualFree( limit, 0, MEM_RELEASE);
}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
//#endif
#endif // BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H

View File

@@ -0,0 +1,49 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_COROUTINES_DETAIL_STANDARD_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_DETAIL_STANDARD_STACK_ALLOCATOR_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/context/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
struct stack_context;
namespace detail {
class standard_stack_allocator
{
public:
static bool is_stack_unbound();
static std::size_t default_stacksize();
static std::size_t minimum_stacksize();
static std::size_t maximum_stacksize();
void allocate( stack_context &, std::size_t);
void deallocate( stack_context &);
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_STANDARD_STACK_ALLOCATOR_H

View File

@@ -4,20 +4,34 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_COROUTINES_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_STACK_ALLOCATOR_H
#ifndef BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H
#include <cstddef>
#include <boost/config.hpp>
#if defined (BOOST_WINDOWS)
#include <boost/coroutine/detail/stack_allocator_windows.hpp>
#else
#include <boost/coroutine/detail/stack_allocator_posix.hpp>
#include <boost/context/detail/config.hpp>
#include <boost/coroutine/detail/segmented_stack_allocator.hpp>
#include <boost/coroutine/detail/standard_stack_allocator.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
using detail::stack_allocator;
#if defined(BOOST_USE_SEGMENTED_STACKS)
typedef detail::segmented_stack_allocator stack_allocator;
#else
typedef detail::standard_stack_allocator stack_allocator;
#endif
}}
#endif // BOOST_COROUTINES_STACK_ALLOCATOR_H
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_STACK_ALLOCATOR_H

View File

@@ -0,0 +1,54 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_COROUTINES_STACK_CONTEXT_H
#define BOOST_COROUTINES_STACK_CONTEXT_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
#if defined(BOOST_USE_SEGMENTED_STACKS)
struct stack_context
{
typedef void * segments_context[BOOST_COROUTINES_SEGMENTS];
std::size_t size;
void * sp;
segments_context segments_ctx;
stack_context() :
size( 0), sp( 0), segments_ctx()
{}
};
#else
struct stack_context
{
std::size_t size;
void * sp;
stack_context() :
size( 0), sp( 0)
{}
};
#endif
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_STACK_CONTEXT_H