mirror of
https://github.com/boostorg/coroutine.git
synced 2026-02-13 00:12:15 +00:00
coroutine: support for segmented stacks added
[SVN r82840]
This commit is contained in:
@@ -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<
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 >,
|
||||
|
||||
@@ -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_) \
|
||||
|
||||
@@ -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)
|
||||
|
||||
63
include/boost/coroutine/detail/coroutine_context.hpp
Normal file
63
include/boost/coroutine/detail/coroutine_context.hpp
Normal 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
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
51
include/boost/coroutine/detail/segmented_stack_allocator.hpp
Normal file
51
include/boost/coroutine/detail/segmented_stack_allocator.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
49
include/boost/coroutine/detail/standard_stack_allocator.hpp
Normal file
49
include/boost/coroutine/detail/standard_stack_allocator.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
54
include/boost/coroutine/stack_context.hpp
Normal file
54
include/boost/coroutine/stack_context.hpp
Normal 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
|
||||
Reference in New Issue
Block a user