stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,21 @@
// 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_ALL_H
#define BOOST_COROUTINES_ALL_H
#include <boost/coroutine/attributes.hpp>
#include <boost/coroutine/coroutine.hpp>
#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/protected_stack_allocator.hpp>
#include <boost/coroutine/segmented_stack_allocator.hpp>
#include <boost/coroutine/stack_allocator.hpp>
#include <boost/coroutine/stack_context.hpp>
#include <boost/coroutine/stack_traits.hpp>
#include <boost/coroutine/standard_stack_allocator.hpp>
#endif // BOOST_COROUTINES_ALL_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,58 @@
// 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_ATTRIBUTES_H
#define BOOST_COROUTINES_ATTRIBUTES_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/stack_allocator.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
struct attributes
{
std::size_t size;
flag_unwind_t do_unwind;
attributes() BOOST_NOEXCEPT :
size( stack_allocator::traits_type::default_size() ),
do_unwind( stack_unwind)
{}
explicit attributes( std::size_t size_) BOOST_NOEXCEPT :
size( size_),
do_unwind( stack_unwind)
{}
explicit attributes( flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
size( stack_allocator::traits_type::default_size() ),
do_unwind( do_unwind_)
{}
explicit attributes(
std::size_t size_,
flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
size( size_),
do_unwind( do_unwind_)
{}
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_ATTRIBUTES_H
@@ -0,0 +1,13 @@
// 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_COROUTINE_H
#define BOOST_COROUTINES_COROUTINE_H
#include <boost/coroutine/asymmetric_coroutine.hpp>
#include <boost/coroutine/symmetric_coroutine.hpp>
#endif // BOOST_COROUTINES_COROUTINE_H
@@ -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_CONFIG_H
#define BOOST_COROUTINES_DETAIL_CONFIG_H
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
# elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
# endif
#endif
#ifdef BOOST_COROUTINES_DECL
# undef BOOST_COROUTINES_DECL
#endif
#if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES_DYN_LINK) ) && ! defined(BOOST_COROUTINES_STATIC_LINK)
# if defined(BOOST_COROUTINES_SOURCE)
# define BOOST_COROUTINES_DECL BOOST_SYMBOL_EXPORT
# define BOOST_COROUTINES_BUILD_DLL
# else
# define BOOST_COROUTINES_DECL BOOST_SYMBOL_IMPORT
# endif
#endif
#if ! defined(BOOST_COROUTINES_DECL)
# define BOOST_COROUTINES_DECL
#endif
#if ! defined(BOOST_COROUTINES_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_COROUTINES_NO_LIB)
# define BOOST_LIB_NAME boost_coroutine
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# include <boost/config/auto_link.hpp>
#endif
#define BOOST_COROUTINES_UNIDIRECT
#define BOOST_COROUTINES_SYMMETRIC
#endif // BOOST_COROUTINES_DETAIL_CONFIG_H
@@ -0,0 +1,73 @@
// 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/detail/fcontext.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/preallocated.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
// class hold stack-context and coroutines execution-context
class BOOST_COROUTINES_DECL coroutine_context
{
private:
template< typename Coro >
friend void trampoline( context::detail::transfer_t);
template< typename Coro >
friend void trampoline_void( context::detail::transfer_t);
template< typename Coro >
friend void trampoline_pull( context::detail::transfer_t);
template< typename Coro >
friend void trampoline_push( context::detail::transfer_t);
template< typename Coro >
friend void trampoline_push_void( context::detail::transfer_t);
preallocated palloc_;
context::detail::fcontext_t ctx_;
public:
typedef void( * ctx_fn)( context::detail::transfer_t);
// default ctor represents the current execution-context
coroutine_context();
// ctor creates a new execution-context running coroutine-fn `fn`
// `ctx_` will be allocated on top of the stack managed by parameter
// `stack_ctx`
coroutine_context( ctx_fn fn, preallocated const& palloc);
coroutine_context( coroutine_context const&);
coroutine_context& operator=( coroutine_context const&);
void * jump( coroutine_context &, void * = 0);
stack_context & stack_ctx()
{ return palloc_.sctx; }
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_COROUTINE_CONTEXT_H
@@ -0,0 +1,34 @@
// 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_DATA_H
#define BOOST_COROUTINES_DETAIL_DATA_H
#include <boost/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
struct data_t
{
coroutine_context * from;
void * data;
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_DATA_H
@@ -0,0 +1,47 @@
// 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_FLAGS_H
#define BOOST_COROUTINES_DETAIL_FLAGS_H
#include <boost/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
enum flag_t
{
flag_started = 1 << 1,
flag_running = 1 << 2,
flag_complete = 1 << 3,
flag_unwind_stack = 1 << 4,
flag_force_unwind = 1 << 5
};
struct unwind_t
{
enum flag_t
{ force_unwind = 1 };
};
struct synthesized_t
{
enum flag_t
{ syntesized = 1 };
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_FLAGS_H
@@ -0,0 +1,102 @@
// 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_PARAMETERS_H
#define BOOST_COROUTINES_DETAIL_PARAMETERS_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/detail/flags.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename Data >
struct parameters
{
Data * data;
bool do_unwind;
void * coro;
parameters() :
data( 0), do_unwind( false), coro( 0)
{}
explicit parameters( void * coro_) :
data( 0), do_unwind( false), coro( coro_)
{ BOOST_ASSERT( 0 != coro); }
explicit parameters( Data * data_, void * coro_) :
data( data_), do_unwind( false), coro( coro_)
{
BOOST_ASSERT( 0 != data);
BOOST_ASSERT( 0 != coro);
}
explicit parameters( unwind_t::flag_t) :
data( 0), do_unwind( true)
{}
};
template< typename Data >
struct parameters< Data & >
{
Data * data;
bool do_unwind;
void * coro;
parameters() :
data( 0), do_unwind( false), coro( 0)
{}
explicit parameters( void * coro_) :
data( 0), do_unwind( false), coro( coro_)
{ BOOST_ASSERT( 0 != coro); }
explicit parameters( Data * data_, void * coro_) :
data( data_), do_unwind( false), coro( coro_)
{
BOOST_ASSERT( 0 != data);
BOOST_ASSERT( 0 != coro);
}
explicit parameters( unwind_t::flag_t) :
data( 0), do_unwind( true), coro( 0)
{}
};
template<>
struct parameters< void >
{
bool do_unwind;
void * coro;
parameters() :
do_unwind( false), coro(0)
{}
parameters( void * coro_) :
do_unwind( false), coro( coro_)
{ BOOST_ASSERT( 0 != coro); }
explicit parameters( unwind_t::flag_t) :
do_unwind( true), coro( 0)
{}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PARAMETERS_H
@@ -0,0 +1,45 @@
// Copyright Oliver Kowalke 2015.
// 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_PREALLOCATED_H
#define BOOST_COROUTINES_DETAIL_PREALLOCATED_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
struct preallocated {
void * sp;
std::size_t size;
stack_context sctx;
preallocated() BOOST_NOEXCEPT :
sp( 0), size( 0), sctx() {
}
preallocated( void * sp_, std::size_t size_, stack_context sctx_) BOOST_NOEXCEPT :
sp( sp_), size( size_), sctx( sctx_) {
}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PREALLOCATED_H
@@ -0,0 +1,335 @@
// 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_PULL_COROUTINE_IMPL_H
#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/throw_exception.hpp>
#include <boost/utility.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/parameters.hpp>
#include <boost/coroutine/detail/trampoline_pull.hpp>
#include <boost/coroutine/exceptions.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
struct stack_context;
namespace detail {
template< typename R >
class pull_coroutine_impl : private noncopyable
{
protected:
int flags_;
exception_ptr except_;
coroutine_context * caller_;
coroutine_context * callee_;
R * result_;
public:
typedef parameters< R > param_type;
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee),
result_( 0)
{
if ( unwind) flags_ |= flag_force_unwind;
}
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind,
R * result) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee),
result_( result)
{
if ( unwind) flags_ |= flag_force_unwind;
}
virtual ~pull_coroutine_impl() {}
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
& to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
void pull()
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
param_type to( this);
param_type * from(
static_cast< param_type * >(
caller_->jump(
* callee_,
& to) ) );
flags_ &= ~flag_running;
result_ = from->data;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
}
bool has_result() const
{ return 0 != result_; }
R get() const
{
if ( ! has_result() )
boost::throw_exception(
invalid_result() );
return * result_;
}
R * get_pointer() const
{
if ( ! has_result() )
boost::throw_exception(
invalid_result() );
return result_;
}
virtual void destroy() = 0;
};
template< typename R >
class pull_coroutine_impl< R & > : private noncopyable
{
protected:
int flags_;
exception_ptr except_;
coroutine_context * caller_;
coroutine_context * callee_;
R * result_;
public:
typedef parameters< R & > param_type;
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee),
result_( 0)
{
if ( unwind) flags_ |= flag_force_unwind;
}
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind,
R * result) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee),
result_( result)
{
if ( unwind) flags_ |= flag_force_unwind;
}
virtual ~pull_coroutine_impl() {}
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
& to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
void pull()
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
param_type to( this);
param_type * from(
static_cast< param_type * >(
caller_->jump(
* callee_,
& to) ) );
flags_ &= ~flag_running;
result_ = from->data;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
}
bool has_result() const
{ return 0 != result_; }
R & get() const
{
if ( ! has_result() )
boost::throw_exception(
invalid_result() );
return * result_;
}
R * get_pointer() const
{
if ( ! has_result() )
boost::throw_exception(
invalid_result() );
return result_;
}
virtual void destroy() = 0;
};
template<>
class pull_coroutine_impl< void > : private noncopyable
{
protected:
int flags_;
exception_ptr except_;
coroutine_context * caller_;
coroutine_context * callee_;
public:
typedef parameters< void > param_type;
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
}
virtual ~pull_coroutine_impl() {}
inline bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
inline bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
inline bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
inline bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
inline bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
inline void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
& to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
inline void pull()
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
param_type to( this);
param_type * from(
static_cast< param_type * >(
caller_->jump(
* callee_,
& to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
}
virtual void destroy() = 0;
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
@@ -0,0 +1,310 @@
// 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_PULL_COROUTINE_OBJECT_H
#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/move/move.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/preallocated.hpp>
#include <boost/coroutine/detail/pull_coroutine_impl.hpp>
#include <boost/coroutine/detail/trampoline_pull.hpp>
#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355)
#endif
namespace boost {
namespace coroutines {
namespace detail {
struct pull_coroutine_context
{
coroutine_context caller;
coroutine_context callee;
template< typename Coro >
pull_coroutine_context( preallocated const& palloc, Coro *) :
caller(),
callee( trampoline_pull< Coro >, palloc)
{}
};
template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
class pull_coroutine_object : private pull_coroutine_context,
public pull_coroutine_impl< R >
{
private:
typedef pull_coroutine_context ctx_t;
typedef pull_coroutine_impl< R > base_t;
typedef pull_coroutine_object< PushCoro, R, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
pull_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run()
{
BOOST_ASSERT( ! base_t::unwind_requested() );
base_t::flags_ |= flag_started;
base_t::flags_ |= flag_running;
// create push_coroutine
typename PushCoro::synth_type b( & this->callee, & this->caller, false);
PushCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
catch ( forced_unwind const&)
{}
catch (...)
{ base_t::except_ = current_exception(); }
base_t::flags_ |= flag_complete;
base_t::flags_ &= ~flag_running;
typename base_t::param_type to;
this->callee.jump(
this->caller,
& to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
template< typename PushCoro, typename R, typename Fn, typename StackAllocator >
class pull_coroutine_object< PushCoro, R &, Fn, StackAllocator > : private pull_coroutine_context,
public pull_coroutine_impl< R & >
{
private:
typedef pull_coroutine_context ctx_t;
typedef pull_coroutine_impl< R & > base_t;
typedef pull_coroutine_object< PushCoro, R &, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
pull_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run()
{
BOOST_ASSERT( ! base_t::unwind_requested() );
base_t::flags_ |= flag_started;
base_t::flags_ |= flag_running;
// create push_coroutine
typename PushCoro::synth_type b( & this->callee, & this->caller, false);
PushCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
catch ( forced_unwind const&)
{}
catch (...)
{ base_t::except_ = current_exception(); }
base_t::flags_ |= flag_complete;
base_t::flags_ &= ~flag_running;
typename base_t::param_type to;
this->callee.jump(
this->caller,
& to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
template< typename PushCoro, typename Fn, typename StackAllocator >
class pull_coroutine_object< PushCoro, void, Fn, StackAllocator > : private pull_coroutine_context,
public pull_coroutine_impl< void >
{
private:
typedef pull_coroutine_context ctx_t;
typedef pull_coroutine_impl< void > base_t;
typedef pull_coroutine_object< PushCoro, void, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
pull_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run()
{
BOOST_ASSERT( ! base_t::unwind_requested() );
base_t::flags_ |= flag_started;
base_t::flags_ |= flag_running;
// create push_coroutine
typename PushCoro::synth_type b( & this->callee, & this->caller, false);
PushCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
catch ( forced_unwind const&)
{}
catch (...)
{ base_t::except_ = current_exception(); }
base_t::flags_ |= flag_complete;
base_t::flags_ &= ~flag_running;
typename base_t::param_type to;
this->callee.jump(
this->caller,
& to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
}}}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_OBJECT_H
@@ -0,0 +1,80 @@
// 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_PULL_COROUTINE_SYNTHESIZED_H
#define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/pull_coroutine_impl.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename R >
class pull_coroutine_synthesized : public pull_coroutine_impl< R >
{
private:
typedef pull_coroutine_impl< R > impl_t;
public:
pull_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
bool unwind,
R * result) :
impl_t( caller, callee, unwind, result)
{}
void destroy() {}
};
template< typename R >
class pull_coroutine_synthesized< R & > : public pull_coroutine_impl< R & >
{
private:
typedef pull_coroutine_impl< R & > impl_t;
public:
pull_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
bool unwind,
R * result) :
impl_t( caller, callee, unwind, result)
{}
void destroy() {}
};
template<>
class pull_coroutine_synthesized< void > : public pull_coroutine_impl< void >
{
private:
typedef pull_coroutine_impl< void > impl_t;
public:
pull_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
impl_t( caller, callee, unwind)
{}
inline void destroy() {}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_SYNTHESIZED_H
@@ -0,0 +1,276 @@
// 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_PUSH_COROUTINE_IMPL_H
#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/throw_exception.hpp>
#include <boost/utility.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/parameters.hpp>
#include <boost/coroutine/detail/trampoline_push.hpp>
#include <boost/coroutine/exceptions.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
struct stack_context;
namespace detail {
template< typename Arg >
class push_coroutine_impl : private noncopyable
{
protected:
int flags_;
exception_ptr except_;
coroutine_context * caller_;
coroutine_context * callee_;
public:
typedef parameters< Arg > param_type;
push_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
}
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
& to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
void push( Arg const& arg)
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
param_type to( const_cast< Arg * >( & arg), this);
param_type * from(
static_cast< param_type * >(
caller_->jump(
* callee_,
& to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
}
void push( BOOST_RV_REF( Arg) arg)
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
param_type to( const_cast< Arg * >( & arg), this);
param_type * from(
static_cast< param_type * >(
caller_->jump(
* callee_,
& to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
}
virtual void destroy() = 0;
};
template< typename Arg >
class push_coroutine_impl< Arg & > : private noncopyable
{
protected:
int flags_;
exception_ptr except_;
coroutine_context * caller_;
coroutine_context * callee_;
public:
typedef parameters< Arg & > param_type;
push_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
}
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
& to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
void push( Arg & arg)
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
param_type to( & arg, this);
param_type * from(
static_cast< param_type * >(
caller_->jump(
* callee_,
& to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
}
virtual void destroy() = 0;
};
template<>
class push_coroutine_impl< void > : private noncopyable
{
protected:
int flags_;
exception_ptr except_;
coroutine_context * caller_;
coroutine_context * callee_;
public:
typedef parameters< void > param_type;
push_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
}
inline bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
inline bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
inline bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
inline bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
inline bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
inline void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
& to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
inline void push()
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
param_type to( this);
param_type * from(
static_cast< param_type * >(
caller_->jump(
* callee_,
& to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
}
virtual void destroy() = 0;
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_IMPL_H
@@ -0,0 +1,322 @@
// 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_PUSH_COROUTINE_OBJECT_H
#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/move/move.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/preallocated.hpp>
#include <boost/coroutine/detail/push_coroutine_impl.hpp>
#include <boost/coroutine/detail/trampoline_push.hpp>
#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355)
#endif
namespace boost {
namespace coroutines {
namespace detail {
struct push_coroutine_context
{
coroutine_context caller;
coroutine_context callee;
template< typename Coro >
push_coroutine_context( preallocated const& palloc, Coro *) :
caller(),
callee( trampoline_push< Coro >, palloc)
{}
};
struct push_coroutine_context_void
{
coroutine_context caller;
coroutine_context callee;
template< typename Coro >
push_coroutine_context_void( preallocated const& palloc, Coro *) :
caller(),
callee( trampoline_push_void< Coro >, palloc)
{}
};
template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
class push_coroutine_object : private push_coroutine_context,
public push_coroutine_impl< R >
{
private:
typedef push_coroutine_context ctx_t;
typedef push_coroutine_impl< R > base_t;
typedef push_coroutine_object< PullCoro, R, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
push_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run( R * result)
{
BOOST_ASSERT( ! base_t::unwind_requested() );
base_t::flags_ |= flag_started;
base_t::flags_ |= flag_running;
// create push_coroutine
typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
PullCoro pull_coro( synthesized_t::syntesized, b);
try
{ fn_( pull_coro); }
catch ( forced_unwind const&)
{}
catch (...)
{ base_t::except_ = current_exception(); }
base_t::flags_ |= flag_complete;
base_t::flags_ &= ~flag_running;
typename base_t::param_type to;
this->callee.jump(
this->caller,
& to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
class push_coroutine_object< PullCoro, R &, Fn, StackAllocator > : private push_coroutine_context,
public push_coroutine_impl< R & >
{
private:
typedef push_coroutine_context ctx_t;
typedef push_coroutine_impl< R & > base_t;
typedef push_coroutine_object< PullCoro, R &, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
push_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run( R * result)
{
BOOST_ASSERT( ! base_t::unwind_requested() );
base_t::flags_ |= flag_started;
base_t::flags_ |= flag_running;
// create push_coroutine
typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
PullCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
catch ( forced_unwind const&)
{}
catch (...)
{ base_t::except_ = current_exception(); }
base_t::flags_ |= flag_complete;
base_t::flags_ &= ~flag_running;
typename base_t::param_type to;
this->callee.jump(
this->caller,
& to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
template< typename PullCoro, typename Fn, typename StackAllocator >
class push_coroutine_object< PullCoro, void, Fn, StackAllocator > : private push_coroutine_context_void,
public push_coroutine_impl< void >
{
private:
typedef push_coroutine_context_void ctx_t;
typedef push_coroutine_impl< void > base_t;
typedef push_coroutine_object< PullCoro, void, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
push_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run()
{
BOOST_ASSERT( ! base_t::unwind_requested() );
base_t::flags_ |= flag_started;
base_t::flags_ |= flag_running;
// create push_coroutine
typename PullCoro::synth_type b( & this->callee, & this->caller, false);
PullCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
catch ( forced_unwind const&)
{}
catch (...)
{ base_t::except_ = current_exception(); }
base_t::flags_ |= flag_complete;
base_t::flags_ &= ~flag_running;
typename base_t::param_type to;
this->callee.jump(
this->caller,
& to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
}}}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
@@ -0,0 +1,78 @@
// 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_PUSH_COROUTINE_SYNTHESIZED_H
#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/push_coroutine_impl.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename R >
class push_coroutine_synthesized : public push_coroutine_impl< R >
{
private:
typedef push_coroutine_impl< R > impl_t;
public:
push_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
impl_t( caller, callee, unwind)
{}
void destroy() {}
};
template< typename R >
class push_coroutine_synthesized< R & > : public push_coroutine_impl< R & >
{
private:
typedef push_coroutine_impl< R & > impl_t;
public:
push_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
impl_t( caller, callee, unwind)
{}
void destroy() {}
};
template<>
class push_coroutine_synthesized< void > : public push_coroutine_impl< void >
{
private:
typedef push_coroutine_impl< void > impl_t;
public:
push_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
bool unwind) :
impl_t( caller, callee, unwind)
{}
inline void destroy() {}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_SYNTHESIZED_H
@@ -0,0 +1,75 @@
// 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_SETUP_H
#define BOOST_COROUTINES_DETAIL_SETUP_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/coroutine/attributes.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/flags.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename Fn >
struct setup
{
struct dummy {};
Fn fn;
coroutine_context * caller;
coroutine_context * callee;
attributes attr;
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
setup( Fn fn_,
coroutine_context * caller_,
coroutine_context * callee_,
attributes const& attr_) :
fn( boost::forward< Fn >( fn_) ),
caller( caller_),
callee( callee_),
attr( attr_)
{}
#endif
setup( BOOST_RV_REF( Fn) fn_,
coroutine_context * caller_,
coroutine_context * callee_,
attributes const& attr_,
typename disable_if<
is_same< typename decay< Fn >::type, setup >,
dummy*
>::type = 0) :
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn( fn_),
#else
fn( boost::forward< Fn >( fn_) ),
#endif
caller( caller_),
callee( callee_),
attr( attr_)
{}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_SETUP_H
@@ -0,0 +1,811 @@
// 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_SYMMETRIC_COROUTINE_CALL_H
#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#include <boost/coroutine/attributes.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/preallocated.hpp>
#include <boost/coroutine/detail/symmetric_coroutine_impl.hpp>
#include <boost/coroutine/detail/symmetric_coroutine_object.hpp>
#include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
#include <boost/coroutine/stack_allocator.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename Arg >
class symmetric_coroutine_call
{
private:
template< typename X >
friend class symmetric_coroutine_yield;
typedef symmetric_coroutine_impl< Arg > impl_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
struct dummy {};
impl_type * impl_;
public:
typedef Arg value_type;
typedef symmetric_coroutine_yield< Arg > yield_type;
symmetric_coroutine_call() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( yield_type &);
explicit symmetric_coroutine_call( coroutine_fn fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, coroutine_fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename StackAllocator >
explicit symmetric_coroutine_call( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, coroutine_fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
# endif
template< typename Fn >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#else
template< typename Fn >
explicit symmetric_coroutine_call( Fn fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#endif
~symmetric_coroutine_call()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
{
symmetric_coroutine_call tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
symmetric_coroutine_call & operator()( Arg arg) BOOST_NOEXCEPT
{
BOOST_ASSERT( * this);
impl_->resume( arg);
return * this;
}
};
template< typename Arg >
class symmetric_coroutine_call< Arg & >
{
private:
template< typename X >
friend class symmetric_coroutine_yield;
typedef symmetric_coroutine_impl< Arg & > impl_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
struct dummy {};
impl_type * impl_;
public:
typedef Arg value_type;
typedef symmetric_coroutine_yield< Arg & > yield_type;
symmetric_coroutine_call() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( yield_type &);
explicit symmetric_coroutine_call( coroutine_fn fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, coroutine_fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename StackAllocator >
explicit symmetric_coroutine_call( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, coroutine_fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
# endif
template< typename Fn >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#else
template< typename Fn >
explicit symmetric_coroutine_call( Fn fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#endif
~symmetric_coroutine_call()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
{
symmetric_coroutine_call tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
symmetric_coroutine_call & operator()( Arg & arg) BOOST_NOEXCEPT
{
BOOST_ASSERT( * this);
impl_->resume( arg);
return * this;
}
};
template<>
class symmetric_coroutine_call< void >
{
private:
template< typename X >
friend class symmetric_coroutine_yield;
typedef symmetric_coroutine_impl< void > impl_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
struct dummy {};
impl_type * impl_;
public:
typedef void value_type;
typedef symmetric_coroutine_yield< void > yield_type;
symmetric_coroutine_call() BOOST_NOEXCEPT :
impl_( 0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# ifdef BOOST_MSVC
typedef void ( * coroutine_fn)( yield_type &);
explicit symmetric_coroutine_call( coroutine_fn fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, coroutine_fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename StackAllocator >
explicit symmetric_coroutine_call( coroutine_fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, coroutine_fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
# endif
template< typename Fn >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#else
template< typename Fn >
explicit symmetric_coroutine_call( Fn fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( Fn fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs = attributes(),
stack_allocator stack_alloc = stack_allocator() ) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
template< typename Fn, typename StackAllocator >
explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
attributes const& attrs,
StackAllocator stack_alloc) :
impl_( 0)
{
// create a stack-context
stack_context stack_ctx;
// allocate the coroutine-stack
stack_alloc.allocate( stack_ctx, attrs.size);
BOOST_ASSERT( 0 != stack_ctx.sp);
// typedef of internal coroutine-type
typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
// reserve space on top of coroutine-stack for internal coroutine-type
std::size_t size = stack_ctx.size - sizeof( object_t);
BOOST_ASSERT( 0 != size);
void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
BOOST_ASSERT( 0 != sp);
// placement new for internal coroutine
impl_ = new ( sp) object_t(
fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
BOOST_ASSERT( impl_);
}
#endif
~symmetric_coroutine_call()
{
if ( 0 != impl_)
{
impl_->destroy();
impl_ = 0;
}
}
inline symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
inline symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
{
symmetric_coroutine_call tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
inline bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
inline void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
inline symmetric_coroutine_call & operator()() BOOST_NOEXCEPT
{
BOOST_ASSERT( * this);
impl_->resume();
return * this;
}
};
template< typename Arg >
void swap( symmetric_coroutine_call< Arg > & l,
symmetric_coroutine_call< Arg > & r)
{ l.swap( r); }
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
@@ -0,0 +1,449 @@
// 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_SYMMETRIC_COROUTINE_IMPL_H
#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/utility.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/parameters.hpp>
#include <boost/coroutine/detail/preallocated.hpp>
#include <boost/coroutine/detail/trampoline.hpp>
#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename R >
class symmetric_coroutine_impl : private noncopyable
{
public:
typedef parameters< R > param_type;
symmetric_coroutine_impl( preallocated const& palloc,
bool unwind) BOOST_NOEXCEPT :
flags_( 0),
caller_(),
callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
{
if ( unwind) flags_ |= flag_force_unwind;
}
virtual ~symmetric_coroutine_impl() {}
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
flags_ |= flag_running;
param_type to( unwind_t::force_unwind);
caller_.jump(
callee_,
& to);
flags_ &= ~flag_running;
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
void resume( R r) BOOST_NOEXCEPT
{
param_type to( const_cast< R * >( & r), this);
resume_( & to);
}
R * yield()
{
BOOST_ASSERT( is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ &= ~flag_running;
param_type to;
param_type * from(
static_cast< param_type * >(
callee_.jump(
caller_,
& to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
return from->data;
}
template< typename X >
R * yield_to( symmetric_coroutine_impl< X > * other, X x)
{
typename symmetric_coroutine_impl< X >::param_type to( & x, other);
return yield_to_( other, & to);
}
template< typename X >
R * yield_to( symmetric_coroutine_impl< X & > * other, X & x)
{
typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
return yield_to_( other, & to);
}
template< typename X >
R * yield_to( symmetric_coroutine_impl< X > * other)
{
typename symmetric_coroutine_impl< X >::param_type to( other);
return yield_to_( other, & to);
}
virtual void run( R *) BOOST_NOEXCEPT = 0;
virtual void destroy() = 0;
protected:
template< typename X >
friend class symmetric_coroutine_impl;
int flags_;
coroutine_context caller_;
coroutine_context callee_;
void resume_( param_type * to) BOOST_NOEXCEPT
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
caller_.jump(
callee_,
to);
flags_ &= ~flag_running;
}
template< typename Other >
R * yield_to_( Other * other, typename Other::param_type * to)
{
BOOST_ASSERT( is_running() );
BOOST_ASSERT( ! is_complete() );
BOOST_ASSERT( ! other->is_running() );
BOOST_ASSERT( ! other->is_complete() );
other->caller_ = caller_;
flags_ &= ~flag_running;
param_type * from(
static_cast< param_type * >(
callee_.jump(
other->callee_,
to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
return from->data;
}
};
template< typename R >
class symmetric_coroutine_impl< R & > : private noncopyable
{
public:
typedef parameters< R & > param_type;
symmetric_coroutine_impl( preallocated const& palloc,
bool unwind) BOOST_NOEXCEPT :
flags_( 0),
caller_(),
callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
{
if ( unwind) flags_ |= flag_force_unwind;
}
virtual ~symmetric_coroutine_impl() {}
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
flags_ |= flag_running;
param_type to( unwind_t::force_unwind);
caller_.jump(
callee_,
& to);
flags_ &= ~flag_running;
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
void resume( R & arg) BOOST_NOEXCEPT
{
param_type to( & arg, this);
resume_( & to);
}
R * yield()
{
BOOST_ASSERT( is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ &= ~flag_running;
param_type to;
param_type * from(
static_cast< param_type * >(
callee_.jump(
caller_,
& to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
return from->data;
}
template< typename X >
R * yield_to( symmetric_coroutine_impl< X > * other, X x)
{
typename symmetric_coroutine_impl< X >::param_type to( & x, other);
return yield_to_( other, & to);
}
template< typename X >
R * yield_to( symmetric_coroutine_impl< X & > * other, X & x)
{
typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
return yield_to_( other, & to);
}
template< typename X >
R * yield_to( symmetric_coroutine_impl< X > * other)
{
typename symmetric_coroutine_impl< X >::param_type to( other);
return yield_to_( other, & to);
}
virtual void run( R *) BOOST_NOEXCEPT = 0;
virtual void destroy() = 0;
protected:
template< typename X >
friend class symmetric_coroutine_impl;
int flags_;
coroutine_context caller_;
coroutine_context callee_;
void resume_( param_type * to) BOOST_NOEXCEPT
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_running;
caller_.jump(
callee_,
to);
flags_ &= ~flag_running;
}
template< typename Other >
R * yield_to_( Other * other, typename Other::param_type * to)
{
BOOST_ASSERT( is_running() );
BOOST_ASSERT( ! is_complete() );
BOOST_ASSERT( ! other->is_running() );
BOOST_ASSERT( ! other->is_complete() );
other->caller_ = caller_;
flags_ &= ~flag_running;
param_type * from(
static_cast< param_type * >(
callee_.jump(
other->callee_,
to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
return from->data;
}
};
template<>
class symmetric_coroutine_impl< void > : private noncopyable
{
public:
typedef parameters< void > param_type;
symmetric_coroutine_impl( preallocated const& palloc,
bool unwind) BOOST_NOEXCEPT :
flags_( 0),
caller_(),
callee_( trampoline_void< symmetric_coroutine_impl< void > >, palloc)
{
if ( unwind) flags_ |= flag_force_unwind;
}
virtual ~symmetric_coroutine_impl() {}
inline bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
inline bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
inline bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
inline bool is_running() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_running); }
inline bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
inline void unwind_stack() BOOST_NOEXCEPT
{
if ( is_started() && ! is_complete() && force_unwind() )
{
flags_ |= flag_unwind_stack;
flags_ |= flag_running;
param_type to( unwind_t::force_unwind);
caller_.jump(
callee_,
& to);
flags_ &= ~flag_running;
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
}
inline void resume() BOOST_NOEXCEPT
{
BOOST_ASSERT( ! is_running() );
BOOST_ASSERT( ! is_complete() );
param_type to( this);
flags_ |= flag_running;
caller_.jump(
callee_,
& to);
flags_ &= ~flag_running;
}
inline void yield()
{
BOOST_ASSERT( is_running() );
BOOST_ASSERT( ! is_complete() );
flags_ &= ~flag_running;
param_type to;
param_type * from(
static_cast< param_type * >(
callee_.jump(
caller_,
& to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
}
template< typename X >
void yield_to( symmetric_coroutine_impl< X > * other, X x)
{
typename symmetric_coroutine_impl< X >::param_type to( & x, other);
yield_to_( other, & to);
}
template< typename X >
void yield_to( symmetric_coroutine_impl< X & > * other, X & x)
{
typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
yield_to_( other, & to);
}
template< typename X >
void yield_to( symmetric_coroutine_impl< X > * other)
{
typename symmetric_coroutine_impl< X >::param_type to( other);
yield_to_( other, & to);
}
virtual void run() BOOST_NOEXCEPT = 0;
virtual void destroy() = 0;
protected:
template< typename X >
friend class symmetric_coroutine_impl;
int flags_;
coroutine_context caller_;
coroutine_context callee_;
template< typename Other >
void yield_to_( Other * other, typename Other::param_type * to)
{
BOOST_ASSERT( is_running() );
BOOST_ASSERT( ! is_complete() );
BOOST_ASSERT( ! other->is_running() );
BOOST_ASSERT( ! other->is_complete() );
other->caller_ = caller_;
flags_ &= ~flag_running;
param_type * from(
static_cast< param_type * >(
callee_.jump(
other->callee_,
to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H
@@ -0,0 +1,267 @@
// 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_SYMMETRIC_COROUTINE_OBJECT_H
#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/preallocated.hpp>
#include <boost/coroutine/detail/symmetric_coroutine_impl.hpp>
#include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
struct stack_context;
namespace detail {
template< typename R, typename Fn, typename StackAllocator >
class symmetric_coroutine_object : public symmetric_coroutine_impl< R >
{
private:
typedef symmetric_coroutine_impl< R > impl_t;
typedef symmetric_coroutine_object< R, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
symmetric_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run( R * r) BOOST_NOEXCEPT
{
BOOST_ASSERT( ! impl_t::unwind_requested() );
impl_t::flags_ |= flag_started;
impl_t::flags_ |= flag_running;
try
{
symmetric_coroutine_yield< R > yc( this, r);
fn_( yc);
}
catch ( forced_unwind const&)
{}
catch (...)
{ std::terminate(); }
impl_t::flags_ |= flag_complete;
impl_t::flags_ &= ~flag_running;
typename impl_t::param_type to;
impl_t::callee_.jump(
impl_t::caller_,
& to);
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
template< typename R, typename Fn, typename StackAllocator >
class symmetric_coroutine_object< R &, Fn, StackAllocator > : public symmetric_coroutine_impl< R & >
{
private:
typedef symmetric_coroutine_impl< R & > impl_t;
typedef symmetric_coroutine_object< R &, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
symmetric_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run( R * r) BOOST_NOEXCEPT
{
BOOST_ASSERT( ! impl_t::unwind_requested() );
impl_t::flags_ |= flag_started;
impl_t::flags_ |= flag_running;
try
{
symmetric_coroutine_yield< R & > yc( this, r);
fn_( yc);
}
catch ( forced_unwind const&)
{}
catch (...)
{ std::terminate(); }
impl_t::flags_ |= flag_complete;
impl_t::flags_ &= ~flag_running;
typename impl_t::param_type to;
impl_t::callee_.jump(
impl_t::caller_,
& to);
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
template< typename Fn, typename StackAllocator >
class symmetric_coroutine_object< void, Fn, StackAllocator > : public symmetric_coroutine_impl< void >
{
private:
typedef symmetric_coroutine_impl< void > impl_t;
typedef symmetric_coroutine_object< void, Fn, StackAllocator > obj_t;
Fn fn_;
stack_context stack_ctx_;
StackAllocator stack_alloc_;
static void deallocate_( obj_t * obj)
{
stack_context stack_ctx( obj->stack_ctx_);
StackAllocator stack_alloc( obj->stack_alloc_);
obj->unwind_stack();
obj->~obj_t();
stack_alloc.deallocate( stack_ctx);
}
public:
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
symmetric_coroutine_object( Fn fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
#endif
symmetric_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
{}
void run() BOOST_NOEXCEPT
{
BOOST_ASSERT( ! impl_t::unwind_requested() );
impl_t::flags_ |= flag_started;
impl_t::flags_ |= flag_running;
try
{
symmetric_coroutine_yield< void > yc( this);
fn_( yc);
}
catch ( forced_unwind const&)
{}
catch (...)
{ std::terminate(); }
impl_t::flags_ |= flag_complete;
impl_t::flags_ &= ~flag_running;
typename impl_t::param_type to;
impl_t::callee_.jump(
impl_t::caller_,
& to);
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
void destroy()
{ deallocate_( this); }
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_OBJECT_H
@@ -0,0 +1,307 @@
// 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_SYMMETRIC_COROUTINE_YIELD_H
#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/exceptions.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename R >
class symmetric_coroutine_yield
{
private:
template< typename X, typename Y, typename Z >
friend class symmetric_coroutine_object;
typedef symmetric_coroutine_impl< R > impl_type;
struct dummy {};
BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
impl_type * impl_;
R * result_;
symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
impl_( impl),
result_( result)
{
BOOST_ASSERT( 0 != impl_);
BOOST_ASSERT( 0 != result_);
}
public:
symmetric_coroutine_yield() BOOST_NOEXCEPT :
impl_( 0),
result_( 0)
{}
symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
impl_( 0),
result_( 0)
{ swap( other); }
symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
{
symmetric_coroutine_yield tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_; }
void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
{
std::swap( impl_, other.impl_);
std::swap( result_, other.result_);
}
symmetric_coroutine_yield & operator()()
{
result_ = impl_->yield();
return * this;
}
template< typename Coro >
symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type x,
typename disable_if<
is_same< typename Coro::value_type, void >,
dummy*
>::type = 0)
{
BOOST_ASSERT( other);
result_ = impl_->yield_to( other.impl_, x);
return * this;
}
template< typename Coro >
symmetric_coroutine_yield & operator()( Coro & other,
typename enable_if<
is_same< typename Coro::value_type, void >,
dummy*
>::type = 0)
{
BOOST_ASSERT( other);
result_ = impl_->yield_to( other.impl_);
return * this;
}
R get() const
{
if ( 0 == result_)
boost::throw_exception(
invalid_result() );
return * result_;
}
};
template< typename R >
class symmetric_coroutine_yield< R & >
{
private:
template< typename X, typename Y, typename Z >
friend class symmetric_coroutine_object;
typedef symmetric_coroutine_impl< R & > impl_type;
struct dummy {};
BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
impl_type * impl_;
R * result_;
symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
impl_( impl),
result_( result)
{
BOOST_ASSERT( 0 != impl_);
BOOST_ASSERT( 0 != result_);
}
public:
symmetric_coroutine_yield() BOOST_NOEXCEPT :
impl_( 0),
result_( 0)
{}
symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
impl_( 0),
result_( 0)
{ swap( other); }
symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
{
symmetric_coroutine_yield tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_; }
void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
{
std::swap( impl_, other.impl_);
std::swap( result_, other.result_);
}
symmetric_coroutine_yield & operator()()
{
result_ = impl_->yield();
return * this;
}
template< typename Coro >
symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
typename disable_if<
is_same< typename Coro::value_type, void >,
dummy*
>::type = 0)
{
BOOST_ASSERT( other);
result_ = impl_->yield_to( other.impl_, x);
return * this;
}
template< typename Coro >
symmetric_coroutine_yield & operator()( Coro & other,
typename enable_if<
is_same< typename Coro::value_type, void >,
dummy*
>::type = 0)
{
BOOST_ASSERT( other);
result_ = impl_->yield_to( other.impl_);
return * this;
}
R & get() const
{
if ( 0 == result_)
boost::throw_exception(
invalid_result() );
return * result_;
}
};
template<>
class symmetric_coroutine_yield< void >
{
private:
template< typename X, typename Y, typename Z >
friend class symmetric_coroutine_object;
typedef symmetric_coroutine_impl< void > impl_type;
struct dummy {};
BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
impl_type * impl_;
symmetric_coroutine_yield( impl_type * impl) BOOST_NOEXCEPT :
impl_( impl)
{ BOOST_ASSERT( 0 != impl_); }
public:
symmetric_coroutine_yield() BOOST_NOEXCEPT :
impl_( 0)
{}
symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
impl_( 0)
{ swap( other); }
symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
{
symmetric_coroutine_yield tmp( boost::move( other) );
swap( tmp);
return * this;
}
BOOST_EXPLICIT_OPERATOR_BOOL();
inline bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_; }
inline void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
{ std::swap( impl_, other.impl_); }
inline symmetric_coroutine_yield & operator()()
{
impl_->yield();
return * this;
}
template< typename Coro >
symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
typename disable_if<
is_same< typename Coro::value_type, void >,
dummy*
>::type = 0)
{
BOOST_ASSERT( other);
impl_->yield_to( other.impl_, x);
return * this;
}
template< typename Coro >
symmetric_coroutine_yield & operator()( Coro & other,
typename enable_if<
is_same< typename Coro::value_type, void >,
dummy*
>::type = 0)
{
BOOST_ASSERT( other);
impl_->yield_to( other.impl_);
return * this;
}
};
template< typename R >
void swap( symmetric_coroutine_yield< R > & l, symmetric_coroutine_yield< R > & r)
{ l.swap( r); }
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
@@ -0,0 +1,69 @@
// 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_TRAMPOLINE_H
#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/detail/fcontext.hpp>
#include <boost/cstdint.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/data.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename Coro >
void trampoline( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
data_t * data = static_cast< data_t * >( t.data);
data->from->ctx_ = t.fctx;
param_type * param(
static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
BOOST_ASSERT( 0 != param->data);
Coro * coro(
static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run( param->data);
}
template< typename Coro >
void trampoline_void( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
data_t * data = static_cast< data_t * >( t.data);
data->from->ctx_ = t.fctx;
param_type * param(
static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
Coro * coro(
static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run();
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
@@ -0,0 +1,50 @@
// 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_TRAMPOLINE_PULL_H
#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/detail/fcontext.hpp>
#include <boost/cstdint.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/data.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename Coro >
void trampoline_pull( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
data_t * data = static_cast< data_t * >( t.data);
data->from->ctx_ = t.fctx;
param_type * param(
static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
Coro * coro(
static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run();
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PULL_H
@@ -0,0 +1,79 @@
// 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_TRAMPOLINE_PUSH_H
#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/detail/fcontext.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/move/move.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/data.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/parameters.hpp>
#include <boost/coroutine/detail/setup.hpp>
#include <boost/coroutine/detail/setup.hpp>
#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/flags.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
template< typename Coro >
void trampoline_push( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
data_t * data = static_cast< data_t * >( t.data);
data->from->ctx_ = t.fctx;
param_type * param(
static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
BOOST_ASSERT( 0 != param->data);
Coro * coro(
static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run( param->data);
}
template< typename Coro >
void trampoline_push_void( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
data_t * data = static_cast< data_t * >( t.data);
data->from->ctx_ = t.fctx;
param_type * param(
static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
Coro * coro(
static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run();
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_PUSH_H
@@ -0,0 +1,103 @@
// 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_EXCEPTIONS_H
#define BOOST_COROUTINES_EXCEPTIONS_H
#include <stdexcept>
#include <string>
#include <boost/config.hpp>
#include <boost/detail/scoped_enum_emulation.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/coroutine/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
namespace detail {
struct forced_unwind {};
}
BOOST_SCOPED_ENUM_DECLARE_BEGIN(coroutine_errc)
{
no_data = 1
}
BOOST_SCOPED_ENUM_DECLARE_END(coroutine_errc)
BOOST_COROUTINES_DECL
system::error_category const& coroutine_category() BOOST_NOEXCEPT;
}
namespace system {
template<>
struct is_error_code_enum< coroutines::coroutine_errc > : public true_type
{};
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
template<>
struct is_error_code_enum< coroutines::coroutine_errc::enum_type > : public true_type
{};
#endif
inline
error_code make_error_code( coroutines::coroutine_errc e) //BOOST_NOEXCEPT
{
return error_code( underlying_cast< int >( e), coroutines::coroutine_category() );
}
inline
error_condition make_error_condition( coroutines::coroutine_errc e) //BOOST_NOEXCEPT
{
return error_condition( underlying_cast< int >( e), coroutines::coroutine_category() );
}
}
namespace coroutines {
class coroutine_error : public std::logic_error
{
private:
system::error_code ec_;
public:
coroutine_error( system::error_code ec) :
logic_error( ec.message() ),
ec_( ec)
{}
system::error_code const& code() const BOOST_NOEXCEPT
{ return ec_; }
};
class invalid_result : public coroutine_error
{
public:
invalid_result() :
coroutine_error(
system::make_error_code(
coroutine_errc::no_data) )
{}
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_EXCEPTIONS_H
@@ -0,0 +1,21 @@
// 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_FLAGS_H
#define BOOST_COROUTINES_FLAGS_H
namespace boost {
namespace coroutines {
enum flag_unwind_t
{
stack_unwind = 0,
no_stack_unwind
};
}}
#endif // BOOST_COROUTINES_FLAGS_H
@@ -0,0 +1,105 @@
// 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_PROTECTED_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
extern "C" {
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
}
#if defined(BOOST_USE_VALGRIND)
#include <valgrind/valgrind.h>
#endif
#include <cmath>
#include <cstddef>
#include <new>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/stack_context.hpp>
#include <boost/coroutine/stack_traits.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
template< typename traitsT >
struct basic_protected_stack_allocator
{
typedef traitsT traits_type;
void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() )
{
BOOST_ASSERT( traits_type::minimum_size() <= size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) );
// page at bottom will be used as guard-page
const std::size_t pages(
static_cast< std::size_t >(
std::floor(
static_cast< float >( size) / traits_type::page_size() ) ) );
BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
const std::size_t size_( pages * traits_type::page_size() );
BOOST_ASSERT( 0 != size && 0 != size_);
BOOST_ASSERT( size_ <= size);
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
#if defined(MAP_ANON)
void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#else
void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#endif
if ( MAP_FAILED == limit) throw std::bad_alloc();
// conforming to POSIX.1-2001
#if defined(BOOST_DISABLE_ASSERTS)
::mprotect( limit, traits_type::page_size(), PROT_NONE);
#else
const int result( ::mprotect( limit, traits_type::page_size(), PROT_NONE) );
BOOST_ASSERT( 0 == result);
#endif
ctx.size = size_;
ctx.sp = static_cast< char * >( limit) + ctx.size;
#if defined(BOOST_USE_VALGRIND)
ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( ctx.sp, limit);
#endif
}
void deallocate( stack_context & ctx)
{
BOOST_ASSERT( ctx.sp);
BOOST_ASSERT( traits_type::minimum_size() <= ctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) );
#if defined(BOOST_USE_VALGRIND)
VALGRIND_STACK_DEREGISTER( ctx.valgrind_stack_id);
#endif
void * limit = static_cast< char * >( ctx.sp) - ctx.size;
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
::munmap( limit, ctx.size);
}
};
typedef basic_protected_stack_allocator< stack_traits > protected_stack_allocator;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
@@ -0,0 +1,69 @@
// 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_SEGMENTED_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_SEGMENTED_STACK_ALLOCATOR_H
#include <cstddef>
#include <new>
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/stack_context.hpp>
#include <boost/coroutine/stack_traits.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
// forward declaration for splitstack-functions defined in libgcc
extern "C" {
void *__splitstack_makecontext( std::size_t,
void * [BOOST_CONTEXT_SEGMENTS],
std::size_t *);
void __splitstack_releasecontext( void * [BOOST_CONTEXT_SEGMENTS]);
void __splitstack_resetcontext( void * [BOOST_CONTEXT_SEGMENTS]);
void __splitstack_block_signals_context( void * [BOOST_CONTEXT_SEGMENTS],
int * new_value, int * old_value);
}
namespace boost {
namespace coroutines {
template< typename traitsT >
struct basic_segmented_stack_allocator
{
typedef traitsT traits_type;
void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() )
{
void * limit = __splitstack_makecontext( size, ctx.segments_ctx, & ctx.size);
if ( ! limit) throw std::bad_alloc();
// ctx.size is already filled by __splitstack_makecontext
ctx.sp = static_cast< char * >( limit) + ctx.size;
int off = 0;
__splitstack_block_signals_context( ctx.segments_ctx, & off, 0);
}
void deallocate( stack_context & ctx)
{ __splitstack_releasecontext( ctx.segments_ctx); }
};
typedef basic_segmented_stack_allocator< stack_traits > segmented_stack_allocator;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_SEGMENTED_STACK_ALLOCATOR_H
@@ -0,0 +1,13 @@
// 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)
#include <boost/config.hpp>
#if defined(BOOST_WINDOWS)
# include <boost/coroutine/windows/protected_stack_allocator.hpp>
#else
# include <boost/coroutine/posix/protected_stack_allocator.hpp>
#endif
@@ -0,0 +1,15 @@
// 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)
#include <boost/config.hpp>
#if defined(BOOST_USE_SEGMENTED_STACKS)
# if defined(BOOST_WINDOWS)
# error "segmented stacks are not supported by Windows"
# else
# include <boost/coroutine/posix/segmented_stack_allocator.hpp>
# endif
#endif
@@ -0,0 +1,37 @@
// 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_ALLOCATOR_H
#define BOOST_COROUTINES_STACK_ALLOCATOR_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/context/detail/config.hpp>
#include <boost/coroutine/segmented_stack_allocator.hpp>
#include <boost/coroutine/standard_stack_allocator.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
#if defined(BOOST_USE_SEGMENTED_STACKS)
typedef segmented_stack_allocator stack_allocator;
#else
typedef standard_stack_allocator stack_allocator;
#endif
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_STACK_ALLOCATOR_H
@@ -0,0 +1,66 @@
// 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_CONTEXT_SEGMENTS];
std::size_t size;
void * sp;
segments_context segments_ctx;
#if defined(BOOST_USE_VALGRIND)
unsigned valgrind_stack_id;
#endif
stack_context() :
size( 0), sp( 0), segments_ctx()
#if defined(BOOST_USE_VALGRIND)
, valgrind_stack_id( 0)
#endif
{}
};
#else
struct stack_context
{
std::size_t size;
void * sp;
#if defined(BOOST_USE_VALGRIND)
unsigned valgrind_stack_id;
#endif
stack_context() :
size( 0), sp( 0)
#if defined(BOOST_USE_VALGRIND)
, valgrind_stack_id( 0)
#endif
{}
};
#endif
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_STACK_CONTEXT_H
@@ -0,0 +1,42 @@
// 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_TRAITS_H
#define BOOST_COROUTINES_STACK_TRAITS_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 BOOST_COROUTINES_DECL stack_traits
{
static bool is_unbounded() BOOST_NOEXCEPT;
static std::size_t page_size() BOOST_NOEXCEPT;
static std::size_t default_size() BOOST_NOEXCEPT;
static std::size_t minimum_size() BOOST_NOEXCEPT;
static std::size_t maximum_size() BOOST_NOEXCEPT;
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_STACK_TRAITS_H
@@ -0,0 +1,75 @@
// 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_STANDARD_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_STANDARD_STACK_ALLOCATOR_H
#if defined(BOOST_USE_VALGRIND)
#include <valgrind/valgrind.h>
#endif
#include <cstddef>
#include <cstdlib>
#include <new>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/stack_context.hpp>
#include <boost/coroutine/stack_traits.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
template< typename traitsT >
struct basic_standard_stack_allocator
{
typedef traitsT traits_type;
void allocate( stack_context & ctx, std::size_t size = traits_type::minimum_size() )
{
BOOST_ASSERT( traits_type::minimum_size() <= size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) );
void * limit = std::malloc( size);
if ( ! limit) throw std::bad_alloc();
ctx.size = size;
ctx.sp = static_cast< char * >( limit) + ctx.size;
#if defined(BOOST_USE_VALGRIND)
ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( ctx.sp, limit);
#endif
}
void deallocate( stack_context & ctx)
{
BOOST_ASSERT( ctx.sp);
BOOST_ASSERT( traits_type::minimum_size() <= ctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) );
#if defined(BOOST_USE_VALGRIND)
VALGRIND_STACK_DEREGISTER( ctx.valgrind_stack_id);
#endif
void * limit = static_cast< char * >( ctx.sp) - ctx.size;
std::free( limit);
}
};
typedef basic_standard_stack_allocator< stack_traits > standard_stack_allocator;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_STANDARD_STACK_ALLOCATOR_H
@@ -0,0 +1,43 @@
// 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_SYMMETRIC_COROUTINE_H
#define BOOST_COROUTINES_SYMMETRIC_COROUTINE_H
#ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
# elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
# endif
#endif
#include <boost/config.hpp>
#include <boost/coroutine/detail/symmetric_coroutine_call.hpp>
#include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
template< typename T >
struct symmetric_coroutine
{
typedef detail::symmetric_coroutine_call< T > call_type;
typedef detail::symmetric_coroutine_yield< T > yield_type;
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_SYMMETRIC_COROUTINE_H
@@ -0,0 +1,87 @@
// 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_PROTECTED_STACK_ALLOCATOR_H
#define BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
extern "C" {
#include <windows.h>
}
#include <cmath>
#include <cstddef>
#include <new>
#include <boost/config.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/stack_traits.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines {
struct stack_context;
template< typename traitsT >
struct basic_protected_stack_allocator
{
typedef traitsT traits_type;
void allocate( stack_context & ctx, std::size_t size)
{
BOOST_ASSERT( traits_type::minimum_size() <= size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) );
// page at bottom will be used as guard-page
const std::size_t pages(
static_cast< std::size_t >(
std::floor(
static_cast< float >( size) / traits_type::page_size() ) ) );
BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
const std::size_t size_ = pages * traits_type::page_size();
BOOST_ASSERT( 0 != size && 0 != size_);
void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
if ( ! limit) throw std::bad_alloc();
DWORD old_options;
#if defined(BOOST_DISABLE_ASSERTS)
::VirtualProtect(
limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
#else
const BOOL result = ::VirtualProtect(
limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
BOOST_ASSERT( FALSE != result);
#endif
ctx.size = size_;
ctx.sp = static_cast< char * >( limit) + ctx.size;
}
void deallocate( stack_context & ctx)
{
BOOST_ASSERT( ctx.sp);
BOOST_ASSERT( traits_type::minimum_size() <= ctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) );
void * limit = static_cast< char * >( ctx.sp) - ctx.size;
::VirtualFree( limit, 0, MEM_RELEASE);
}
};
typedef basic_protected_stack_allocator< stack_traits > protected_stack_allocator;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H