Current File : //proc/self/root/usr/include/boost/coroutine/detail/coroutine_object_void_1.ipp |
// 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)
template<
typename Signature,
typename Fn, typename StackAllocator, typename Allocator,
typename Caller
>
class coroutine_object< Signature, Fn, StackAllocator, Allocator, Caller, void, 1 > :
public coroutine_base< Signature >
{
public:
typedef typename Allocator::template rebind<
coroutine_object<
Signature, Fn, StackAllocator, Allocator, Caller, void, 1
>
>::other allocator_t;
typedef typename arg< Signature >::type arg_type;
private:
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
coroutine_object( coroutine_object &);
coroutine_object & operator=( coroutine_object const&);
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;
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
> 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;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t 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,
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
catch ( forced_unwind const&)
{}
catch (...)
{ this->except_ = current_exception(); }
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
void unwind_stack_() BOOST_NOEXCEPT
{
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),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( this->is_complete() );
}
public:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
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) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
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) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
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) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
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) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
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) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
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);
}
void run()
{
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_);
c.impl_->result_ = arg;
run_( c);
}
void deallocate_object()
{ destroy_( alloc_, this); }
};
template<
typename Signature,
typename Fn, typename StackAllocator, typename Allocator,
typename Caller
>
class coroutine_object< Signature, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, 1 > :
public coroutine_base< Signature >
{
public:
typedef typename Allocator::template rebind<
coroutine_object<
Signature, Fn, StackAllocator, Allocator, Caller, void, 1
>
>::other allocator_t;
typedef typename arg< Signature >::type arg_type;
private:
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
coroutine_object( coroutine_object &);
coroutine_object & operator=( coroutine_object const&);
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;
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
> 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;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t 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,
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
catch ( forced_unwind const&)
{}
catch (...)
{ this->except_ = current_exception(); }
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
void unwind_stack_() BOOST_NOEXCEPT
{
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),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( this->is_complete() );
}
public:
coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
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) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
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);
}
void run()
{
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_);
c.impl_->result_ = arg;
run_( c);
}
void deallocate_object()
{ destroy_( alloc_, this); }
};
template<
typename Signature,
typename Fn, typename StackAllocator, typename Allocator,
typename Caller
>
class coroutine_object< Signature, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, void, 1 > :
public coroutine_base< Signature >
{
public:
typedef typename Allocator::template rebind<
coroutine_object<
Signature, Fn, StackAllocator, Allocator, Caller, void, 1
>
>::other allocator_t;
typedef typename arg< Signature >::type arg_type;
private:
typedef coroutine_base< Signature > base_type;
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, coroutine_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
coroutine_object( coroutine_object &);
coroutine_object & operator=( coroutine_object const&);
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;
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
> 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;
if ( this->except_) rethrow_exception( this->except_);
}
void run_( Caller & c)
{
context::fcontext_t * callee( 0);
context::fcontext_t 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,
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
catch ( forced_unwind const&)
{}
catch (...)
{ this->except_ = current_exception(); }
this->flags_ |= flag_complete;
callee = c.impl_->callee_;
BOOST_ASSERT( callee);
context::jump_fcontext(
& caller, callee,
reinterpret_cast< intptr_t >( & caller),
this->preserve_fpu() );
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
void unwind_stack_() BOOST_NOEXCEPT
{
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),
this->preserve_fpu() );
this->flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( this->is_complete() );
}
public:
coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline1< coroutine_object >),
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) :
base_type(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline2< coroutine_object, typename detail::param< arg_type >::type >),
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);
}
void run()
{
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_);
c.impl_->result_ = arg;
run_( c);
}
void deallocate_object()
{ destroy_( alloc_, this); }
};