add boost on mac
This commit is contained in:
41
macx64/include/boost/coroutine/detail/config.hpp
Normal file
41
macx64/include/boost/coroutine/detail/config.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
// 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>
|
||||
|
||||
#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
|
||||
73
macx64/include/boost/coroutine/detail/coroutine_context.hpp
Normal file
73
macx64/include/boost/coroutine/detail/coroutine_context.hpp
Normal file
@@ -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
|
||||
34
macx64/include/boost/coroutine/detail/data.hpp
Normal file
34
macx64/include/boost/coroutine/detail/data.hpp
Normal file
@@ -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
|
||||
47
macx64/include/boost/coroutine/detail/flags.hpp
Normal file
47
macx64/include/boost/coroutine/detail/flags.hpp
Normal file
@@ -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
|
||||
102
macx64/include/boost/coroutine/detail/parameters.hpp
Normal file
102
macx64/include/boost/coroutine/detail/parameters.hpp
Normal file
@@ -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
|
||||
45
macx64/include/boost/coroutine/detail/preallocated.hpp
Normal file
45
macx64/include/boost/coroutine/detail/preallocated.hpp
Normal file
@@ -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 BOOST_COROUTINES_DECL 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
|
||||
335
macx64/include/boost/coroutine/detail/pull_coroutine_impl.hpp
Normal file
335
macx64/include/boost/coroutine/detail/pull_coroutine_impl.hpp
Normal file
@@ -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
|
||||
323
macx64/include/boost/coroutine/detail/pull_coroutine_object.hpp
Normal file
323
macx64/include/boost/coroutine/detail/pull_coroutine_object.hpp
Normal file
@@ -0,0 +1,323 @@
|
||||
|
||||
// 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/context/detail/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&)
|
||||
{}
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
catch ( abi::__forced_unwind const&)
|
||||
{ throw; }
|
||||
#endif
|
||||
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&)
|
||||
{}
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
catch ( abi::__forced_unwind const&)
|
||||
{ throw; }
|
||||
#endif
|
||||
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&)
|
||||
{}
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
catch ( abi::__forced_unwind const&)
|
||||
{ throw; }
|
||||
#endif
|
||||
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
|
||||
282
macx64/include/boost/coroutine/detail/push_coroutine_impl.hpp
Normal file
282
macx64/include/boost/coroutine/detail/push_coroutine_impl.hpp
Normal file
@@ -0,0 +1,282 @@
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
virtual ~push_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 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;
|
||||
}
|
||||
|
||||
virtual ~push_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 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;
|
||||
}
|
||||
|
||||
virtual ~push_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 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
|
||||
335
macx64/include/boost/coroutine/detail/push_coroutine_object.hpp
Normal file
335
macx64/include/boost/coroutine/detail/push_coroutine_object.hpp
Normal file
@@ -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_PUSH_COROUTINE_OBJECT_H
|
||||
#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/detail/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&)
|
||||
{}
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
catch ( abi::__forced_unwind const&)
|
||||
{ throw; }
|
||||
#endif
|
||||
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&)
|
||||
{}
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
catch ( abi::__forced_unwind const&)
|
||||
{ throw; }
|
||||
#endif
|
||||
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&)
|
||||
{}
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
catch ( abi::__forced_unwind const&)
|
||||
{ throw; }
|
||||
#endif
|
||||
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
|
||||
75
macx64/include/boost/coroutine/detail/setup.hpp
Normal file
75
macx64/include/boost/coroutine/detail/setup.hpp
Normal file
@@ -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
|
||||
69
macx64/include/boost/coroutine/detail/trampoline.hpp
Normal file
69
macx64/include/boost/coroutine/detail/trampoline.hpp
Normal file
@@ -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
|
||||
50
macx64/include/boost/coroutine/detail/trampoline_pull.hpp
Normal file
50
macx64/include/boost/coroutine/detail/trampoline_pull.hpp
Normal file
@@ -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
|
||||
79
macx64/include/boost/coroutine/detail/trampoline_push.hpp
Normal file
79
macx64/include/boost/coroutine/detail/trampoline_push.hpp
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user