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

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,16 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_ALL_H
#define BOOST_COROUTINES2_ALL_H
#include <boost/coroutine2/coroutine.hpp>
#include <boost/coroutine2/fixedsize_stack.hpp>
#include <boost/coroutine2/pooled_fixedsize_stack.hpp>
#include <boost/coroutine2/protected_fixedsize_stack.hpp>
#include <boost/coroutine2/segmented_stack.hpp>
#endif // BOOST_COROUTINES2_ALL_H
@@ -0,0 +1,39 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_COROUTINE_H
#define BOOST_COROUTINES2_COROUTINE_H
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine2/detail/coroutine.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
template< typename T >
struct coroutine {
using pull_type = detail::pull_coroutine< T >;
using push_type = detail::push_coroutine< T >;
};
template< typename T >
using asymmetric_coroutine = coroutine< T >;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_COROUTINE_H
@@ -0,0 +1,38 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_CONFIG_H
#define BOOST_COROUTINES2_DETAIL_CONFIG_H
#include <boost/config.hpp>
#include <boost/context/detail/config.hpp>
#include <boost/detail/workaround.hpp>
#ifdef BOOST_COROUTINES2_DECL
# undef BOOST_COROUTINES2_DECL
#endif
#if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES2_DYN_LINK) ) && ! defined(BOOST_COROUTINES2_STATIC_LINK)
# if defined(BOOST_COROUTINES2_SOURCE)
# define BOOST_COROUTINES2_DECL BOOST_SYMBOL_EXPORT
# else
# define BOOST_COROUTINES2_DECL BOOST_SYMBOL_IMPORT
# endif
#endif
#if ! defined(BOOST_COROUTINES2_DECL)
# define BOOST_COROUTINES2_DECL
#endif
#if ! defined(BOOST_COROUTINES2_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_COROUTINES2_NO_LIB)
# define BOOST_LIB_NAME boost_coroutine2
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES2_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# include <boost/config/auto_link.hpp>
#endif
#endif // BOOST_COROUTINES2_DETAIL_CONFIG_H
@@ -0,0 +1,57 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_COROUTINE_HPP
#define BOOST_COROUTINES2_DETAIL_COROUTINE_HPP
#include <boost/config.hpp>
#include <boost/context/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
class pull_coroutine;
template< typename T >
class push_coroutine;
}}}
#include <boost/coroutine2/detail/pull_coroutine.hpp>
#include <boost/coroutine2/detail/push_coroutine.hpp>
#if defined(BOOST_EXECUTION_CONTEXT)
# if (BOOST_EXECUTION_CONTEXT==1)
# include <boost/coroutine2/detail/pull_control_block_ecv1.hpp>
# include <boost/coroutine2/detail/push_control_block_ecv1.hpp>
# else
# include <boost/coroutine2/detail/pull_control_block_cc.hpp>
# include <boost/coroutine2/detail/push_control_block_cc.hpp>
# endif
# include <boost/coroutine2/detail/pull_coroutine.ipp>
# include <boost/coroutine2/detail/push_coroutine.ipp>
# if (BOOST_EXECUTION_CONTEXT==1)
# include <boost/coroutine2/detail/pull_control_block_ecv1.ipp>
# include <boost/coroutine2/detail/push_control_block_ecv1.ipp>
# else
# include <boost/coroutine2/detail/pull_control_block_cc.ipp>
# include <boost/coroutine2/detail/push_control_block_cc.ipp>
# endif
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_COROUTINE_HPP
@@ -0,0 +1,60 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
#define BOOST_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
#include <cstddef>
#include <memory>
#include <utility>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/preallocated.hpp>
#include <boost/context/stack_context.hpp>
#include <boost/coroutine2/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename ControlBlock, typename StackAllocator, typename Fn >
ControlBlock * create_control_block( StackAllocator salloc, Fn && fn) {
auto sctx = salloc.allocate();
// reserve space for control structure
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
void * sp = static_cast< char * >( sctx.sp) - sizeof( ControlBlock);
const std::size_t size = sctx.size - sizeof( ControlBlock);
#else
constexpr std::size_t func_alignment = 64; // alignof( ControlBlock);
constexpr std::size_t func_size = sizeof( ControlBlock);
// reserve space on stack
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
// align sp pointer
std::size_t space = func_size + func_alignment;
sp = std::align( func_alignment, func_size, sp, space);
BOOST_ASSERT( nullptr != sp);
// calculate remaining size
const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
#endif
// placment new for control structure on coroutine stack
return new ( sp) ControlBlock{ context::preallocated( sp, size, sctx),
salloc, std::forward< Fn >( fn) };
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
@@ -0,0 +1,36 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_DECAY_COPY_H
#define BOOST_COROUTINES2_DETAIL_DECAY_COPY_H
#include <type_traits>
#include <boost/config.hpp>
#include <boost/context/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
typename std::decay< T >::type
decay_copy( T && t) {
return std::forward< T >( t);
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_DECAY_COPY_H
@@ -0,0 +1,34 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_DISABLE_OVERLOAD_H
#define BOOST_COROUTINES2_DETAIL_DISABLE_OVERLOAD_H
#include <type_traits>
#include <boost/config.hpp>
#include <boost/context/detail/disable_overload.hpp>
#include <boost/coroutine2/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename X, typename Y >
using disable_overload = boost::context::detail::disable_overload< X, Y >;
}}}
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_DISABLE_OVERLOAD_H
@@ -0,0 +1,37 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_FORCED_UNWIND_HPP
#define BOOST_COROUTINES2_DETAIL_FORCED_UNWIND_HPP
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
struct forced_unwind {};
inline
void * unwind_coroutine( void * data) {
throw forced_unwind{};
return data;
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_FORCED_UNWIND_HPP
@@ -0,0 +1,128 @@
// Copyright Oliver Kowalke 2016.
// 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_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
#include <exception>
#include <type_traits>
#include <boost/config.hpp>
#include <boost/context/continuation.hpp>
#include <boost/coroutine2/detail/state.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
struct pull_coroutine< T >::control_block {
boost::context::continuation c;
typename push_coroutine< T >::control_block * other;
state_t state;
std::exception_ptr except;
bool bvalid;
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename push_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
~control_block();
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
void set( T const&);
void set( T &&);
void reset();
T & get() noexcept;
bool valid() const noexcept;
};
template< typename T >
struct pull_coroutine< T & >::control_block {
struct holder {
T & t;
holder( T & t_) :
t{ t_ } {
}
};
boost::context::continuation c;
typename push_coroutine< T & >::control_block * other;
state_t state;
std::exception_ptr except;
bool bvalid;
typename std::aligned_storage< sizeof( holder), alignof( holder) >::type storage;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename push_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
void set( T &);
void reset();
T & get() noexcept;
bool valid() const noexcept;
};
struct pull_coroutine< void >::control_block {
boost::context::continuation c;
push_coroutine< void >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( push_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
bool valid() const noexcept;
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
@@ -0,0 +1,452 @@
// Copyright Oliver Kowalke 2016.
// 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_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
#include <algorithm>
#include <exception>
#include <memory>
#include <tuple>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/continuation.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/forced_unwind.hpp>
#include <boost/coroutine2/detail/wrap.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
// pull_coroutine< T >
template< typename T >
void
pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
boost::context::continuation c = std::move( cb->c);
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
c.resume();
}
template< typename T >
template< typename StackAllocator, typename Fn >
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
c{},
other{ nullptr },
state{ state_t::unwind },
except{},
bvalid{ false },
storage{} {
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
// create synthesized push_coroutine< T >
typename push_coroutine< T >::control_block synthesized_cb{ this, c };
push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
},
std::forward< Fn >( fn) ) );
#else
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
// create synthesized push_coroutine< T >
typename push_coroutine< T >::control_block synthesized_cb{ this, c };
push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
});
#endif
if ( c.data_available() ) {
set( c.get_data< T >() );
}
}
template< typename T >
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
other{ cb },
state{ state_t::none },
except{},
bvalid{ false },
storage{} {
}
template< typename T >
pull_coroutine< T >::control_block::~control_block() {
// destroy data if set
if ( bvalid) {
reinterpret_cast< T * >( std::addressof( storage) )->~T();
}
}
template< typename T >
void
pull_coroutine< T >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
pull_coroutine< T >::control_block::resume() {
c = c.resume();
if ( c.data_available() ) {
set( c.get_data< T >() );
} else {
reset();
}
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
void
pull_coroutine< T >::control_block::set( T const& t) {
// destroy data if set
if ( bvalid) {
reinterpret_cast< T * >( std::addressof( storage) )->~T();
}
::new ( static_cast< void * >( std::addressof( storage) ) ) T( t);
bvalid = true;
}
template< typename T >
void
pull_coroutine< T >::control_block::set( T && t) {
// destroy data if set
if ( bvalid) {
reinterpret_cast< T * >( std::addressof( storage) )->~T();
}
::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( t) );
bvalid = true;
}
template< typename T >
void
pull_coroutine< T >::control_block::reset() {
// destroy data if set
if ( bvalid) {
reinterpret_cast< T * >( std::addressof( storage) )->~T();
}
bvalid = false;
}
template< typename T >
T &
pull_coroutine< T >::control_block::get() noexcept {
return * reinterpret_cast< T * >( std::addressof( storage) );
}
template< typename T >
bool
pull_coroutine< T >::control_block::valid() const noexcept {
return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
}
// pull_coroutine< T & >
template< typename T >
void
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::continuation c = std::move( cb->c);
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
c.resume();
}
template< typename T >
template< typename StackAllocator, typename Fn >
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
c{},
other{ nullptr },
state{ state_t::unwind },
except{},
bvalid{ false },
storage{} {
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
// create synthesized push_coroutine< T & >
typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
},
std::forward< Fn >( fn) ) );
#else
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
// create synthesized push_coroutine< T & >
typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
});
#endif
if ( c.data_available() ) {
set( c.get_data< T & >() );
}
}
template< typename T >
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
other{ cb },
state{ state_t::none },
except{},
bvalid{ false },
storage{} {
}
template< typename T >
void
pull_coroutine< T & >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
pull_coroutine< T & >::control_block::resume() {
c = c.resume();
if ( c.data_available() ) {
set( c.get_data< T & >() );
} else {
reset();
}
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
void
pull_coroutine< T & >::control_block::set( T & t) {
::new ( static_cast< void * >( std::addressof( storage) ) ) holder{ t };
bvalid = true;
}
template< typename T >
void
pull_coroutine< T & >::control_block::reset() {
if ( bvalid) {
reinterpret_cast< holder * >( std::addressof( storage) )->~holder();
}
bvalid = false;
}
template< typename T >
T &
pull_coroutine< T & >::control_block::get() noexcept {
return reinterpret_cast< holder * >( std::addressof( storage) )->t;
}
template< typename T >
bool
pull_coroutine< T & >::control_block::valid() const noexcept {
return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
}
// pull_coroutine< void >
inline
void
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::continuation c = std::move( cb->c);
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
c.resume();
}
template< typename StackAllocator, typename Fn >
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
c{},
other{ nullptr },
state{ state_t::unwind },
except{} {
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
// create synthesized push_coroutine< void >
typename push_coroutine< void >::control_block synthesized_cb{ this, c };
push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
},
std::forward< Fn >( fn) ) );
#else
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
[this,fn_=std::forward< Fn >( fn)]( boost::context::continuation && c) mutable {
// create synthesized push_coroutine< void >
typename push_coroutine< void >::control_block synthesized_cb{ this, c };
push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
return other->c.resume();
});
#endif
}
inline
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
other{ cb },
state{ state_t::none },
except{} {
}
inline
void
pull_coroutine< void >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
inline
void
pull_coroutine< void >::control_block::resume() {
c = c.resume();
if ( except) {
std::rethrow_exception( except);
}
}
inline
bool
pull_coroutine< void >::control_block::valid() const noexcept {
return nullptr != other && state_t::none == ( state & state_t::complete);
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
@@ -0,0 +1,119 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
#include <exception>
#include <functional>
#include <type_traits>
#include <boost/config.hpp>
#include <boost/context/execution_context.hpp>
#include <boost/coroutine2/detail/state.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
struct pull_coroutine< T >::control_block {
boost::context::execution_context ctx;
typename push_coroutine< T >::control_block * other;
state_t state;
std::exception_ptr except;
bool bvalid;
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
void set( T *);
T & get() noexcept;
bool valid() const noexcept;
};
template< typename T >
struct pull_coroutine< T & >::control_block {
boost::context::execution_context ctx;
typename push_coroutine< T & >::control_block * other;
state_t state;
std::exception_ptr except;
T * t;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
T & get() noexcept;
bool valid() const noexcept;
};
struct pull_coroutine< void >::control_block {
boost::context::execution_context ctx;
push_coroutine< void >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
bool valid() const noexcept;
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
@@ -0,0 +1,431 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
#include <exception>
#include <functional>
#include <memory>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/execution_context.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/decay_copy.hpp>
#include <boost/coroutine2/detail/forced_unwind.hpp>
#include <boost/coroutine2/detail/state.hpp>
#include <boost/coroutine2/detail/wrap.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
// pull_coroutine< T >
template< typename T >
void
pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
template< typename T >
template< typename StackAllocator, typename Fn >
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
// create synthesized push_coroutine< T >
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
},
std::forward< Fn >( fn),
boost::context::execution_context::current() ) },
#else
ctx{ std::allocator_arg, palloc, salloc,
[this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
// create synthesized push_coroutine< T >
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}},
#endif
other{ nullptr },
state{ state_t::unwind },
except{},
bvalid{ false },
storage{} {
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
set( static_cast< T * >( ctx() ) );
}
template< typename T >
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
boost::context::execution_context const& ctx_) noexcept :
ctx{ ctx_ },
other{ cb },
state{ state_t::none },
except{},
bvalid{ false },
storage{} {
}
template< typename T >
pull_coroutine< T >::control_block::~control_block() {
if ( state_t::none == ( state & state_t::complete) &&
state_t::none != ( state & state_t::unwind) ) {
// unwind coroutine stack
other->ctx = boost::context::execution_context::current();
ctx( context::exec_ontop_arg, unwind_coroutine);
}
// destroy data if it set
if ( bvalid) {
reinterpret_cast< T * >( std::addressof( storage) )->~T();
}
}
template< typename T >
void
pull_coroutine< T >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
pull_coroutine< T >::control_block::resume() {
other->ctx = boost::context::execution_context::current();
set( static_cast< T * >( ctx() ) );
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
void
pull_coroutine< T >::control_block::set( T * t) {
// destroy data if it set
if ( bvalid) {
reinterpret_cast< T * >( std::addressof( storage) )->~T();
}
if ( nullptr != t) {
::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( * t) );
bvalid = true;
} else {
bvalid = false;
}
}
template< typename T >
T &
pull_coroutine< T >::control_block::get() noexcept {
return * reinterpret_cast< T * >( std::addressof( storage) );
}
template< typename T >
bool
pull_coroutine< T >::control_block::valid() const noexcept {
return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
}
// pull_coroutine< T & >
template< typename T >
void
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
template< typename T >
template< typename StackAllocator, typename Fn >
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
// create synthesized push_coroutine< T >
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
},
std::forward< Fn >( fn),
boost::context::execution_context::current() ) },
#else
ctx{ std::allocator_arg, palloc, salloc,
[this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
// create synthesized push_coroutine< T >
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}},
#endif
other{ nullptr },
state{ state_t::unwind },
except{},
t{ nullptr } {
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
t = static_cast< T * >( ctx() );
}
template< typename T >
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
boost::context::execution_context const& ctx_) noexcept :
ctx{ ctx_ },
other{ cb },
state{ state_t::none },
except{},
t( nullptr) {
}
template< typename T >
pull_coroutine< T & >::control_block::~control_block() {
if ( state_t::none == ( state & state_t::complete) &&
state_t::none != ( state & state_t::unwind) ) {
// unwind coroutine stack
other->ctx = boost::context::execution_context::current();
ctx( context::exec_ontop_arg, unwind_coroutine);
}
}
template< typename T >
void
pull_coroutine< T & >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
pull_coroutine< T & >::control_block::resume() {
other->ctx = boost::context::execution_context::current();
t = static_cast< T * >( ctx() );
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
T &
pull_coroutine< T & >::control_block::get() noexcept {
return * static_cast< T * >( t);
}
template< typename T >
bool
pull_coroutine< T & >::control_block::valid() const noexcept {
return nullptr != other && state_t::none == ( state & state_t::complete) && nullptr != t;
}
// pull_coroutine< void >
inline
void
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
template< typename StackAllocator, typename Fn >
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
// create synthesized push_coroutine< T >
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
},
std::forward< Fn >( fn),
boost::context::execution_context::current() ) },
#else
ctx{ std::allocator_arg, palloc, salloc,
[this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
// create synthesized push_coroutine< T >
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized push_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}},
#endif
other{ nullptr },
state{ state_t::unwind },
except{} {
// enter coroutine-fn in order to have first value available after ctor returns
ctx();
}
inline
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
boost::context::execution_context const& ctx_) noexcept :
ctx{ ctx_ },
other{ cb },
state{ state_t::none },
except{} {
}
inline
pull_coroutine< void >::control_block::~control_block() {
if ( state_t::none == ( state & state_t::complete) &&
state_t::none != ( state & state_t::unwind) ) {
// unwind coroutine stack
other->ctx = boost::context::execution_context::current();
ctx( context::exec_ontop_arg, unwind_coroutine);
}
}
inline
void
pull_coroutine< void >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
inline
void
pull_coroutine< void >::control_block::resume() {
other->ctx = boost::context::execution_context::current();
ctx();
if ( except) {
std::rethrow_exception( except);
}
}
inline
bool
pull_coroutine< void >::control_block::valid() const noexcept {
return nullptr != other && state_t::none == ( state & state_t::complete);
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
@@ -0,0 +1,311 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
#define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
#include <iterator>
#include <type_traits>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/disable_overload.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
class pull_coroutine {
private:
template< typename X >
friend class push_coroutine;
struct control_block;
control_block * cb_;
explicit pull_coroutine( control_block *) noexcept;
bool has_result_() const noexcept;
public:
template< typename Fn,
typename = detail::disable_overload< pull_coroutine, Fn >
>
explicit pull_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
pull_coroutine( StackAllocator, Fn &&);
~pull_coroutine();
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
pull_coroutine( pull_coroutine &&) noexcept;
pull_coroutine & operator=( pull_coroutine && other) noexcept {
if ( this == & other) return * this;
cb_ = other.cb_;
other.cb_ = nullptr;
return * this;
}
pull_coroutine & operator()();
explicit operator bool() const noexcept;
bool operator!() const noexcept;
T get() noexcept;
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
private:
pull_coroutine< T > * c_{ nullptr };
void fetch_() noexcept {
BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_) ) {
c_ = nullptr;
return;
}
}
void increment_() {
BOOST_ASSERT( nullptr != c_);
BOOST_ASSERT( * c_);
( * c_)();
fetch_();
}
public:
typedef typename iterator::pointer pointer_t;
typedef typename iterator::reference reference_t;
iterator() noexcept = default;
explicit iterator( pull_coroutine< T > * c) noexcept :
c_{ c } {
fetch_();
}
iterator( iterator const& other) noexcept :
c_{ other.c_ } {
}
iterator & operator=( iterator const& other) noexcept {
if ( this == & other) return * this;
c_ = other.c_;
return * this;
}
bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
iterator & operator++() {
increment_();
return * this;
}
iterator operator++( int) = delete;
reference_t operator*() const noexcept {
return c_->cb_->get();
}
pointer_t operator->() const noexcept {
return std::addressof( c_->cb_->get() );
}
};
friend class iterator;
};
template< typename T >
class pull_coroutine< T & > {
private:
template< typename X >
friend class push_coroutine;
struct control_block;
control_block * cb_;
explicit pull_coroutine( control_block *) noexcept;
bool has_result_() const noexcept;
public:
template< typename Fn,
typename = detail::disable_overload< pull_coroutine, Fn >
>
explicit pull_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
pull_coroutine( StackAllocator, Fn &&);
~pull_coroutine();
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
pull_coroutine( pull_coroutine &&) noexcept;
pull_coroutine & operator=( pull_coroutine && other) noexcept {
if ( this == & other) return * this;
cb_ = other.cb_;
other.cb_ = nullptr;
return * this;
}
pull_coroutine & operator()();
explicit operator bool() const noexcept;
bool operator!() const noexcept;
T & get() noexcept;
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
private:
pull_coroutine< T & > * c_{ nullptr };
void fetch_() noexcept {
BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_) ) {
c_ = nullptr;
return;
}
}
void increment_() {
BOOST_ASSERT( nullptr != c_);
BOOST_ASSERT( * c_);
( * c_)();
fetch_();
}
public:
typedef typename iterator::pointer pointer_t;
typedef typename iterator::reference reference_t;
iterator() noexcept = default;
explicit iterator( pull_coroutine< T & > * c) noexcept :
c_{ c } {
fetch_();
}
iterator( iterator const& other) noexcept :
c_{ other.c_ } {
}
iterator & operator=( iterator const& other) noexcept {
if ( this == & other) return * this;
c_ = other.c_;
return * this;
}
bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
iterator & operator++() {
increment_();
return * this;
}
iterator operator++( int) = delete;
reference_t operator*() const noexcept {
return c_->cb_->get();
}
pointer_t operator->() const noexcept {
return std::addressof( c_->cb_->get() );
}
};
friend class iterator;
};
template<>
class pull_coroutine< void > {
private:
template< typename X >
friend class push_coroutine;
struct control_block;
control_block * cb_;
explicit pull_coroutine( control_block *) noexcept;
public:
template< typename Fn,
typename = detail::disable_overload< pull_coroutine, Fn >
>
explicit pull_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
pull_coroutine( StackAllocator, Fn &&);
~pull_coroutine();
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
pull_coroutine( pull_coroutine &&) noexcept;
pull_coroutine & operator=( pull_coroutine && other) noexcept {
if ( this == & other) return * this;
cb_ = other.cb_;
other.cb_ = nullptr;
return * this;
}
pull_coroutine & operator()();
explicit operator bool() const noexcept;
bool operator!() const noexcept;
};
template< typename T >
typename pull_coroutine< T >::iterator
begin( pull_coroutine< T > & c) {
return typename pull_coroutine< T >::iterator( & c);
}
template< typename T >
typename pull_coroutine< T >::iterator
end( pull_coroutine< T > &) {
return typename pull_coroutine< T >::iterator();
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
@@ -0,0 +1,228 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PULL_COROUTINE_IPP
#define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_IPP
#include <algorithm>
#include <utility>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/create_control_block.ipp>
#include <boost/coroutine2/detail/disable_overload.hpp>
#include <boost/coroutine2/fixedsize_stack.hpp>
#include <boost/coroutine2/segmented_stack.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
// pull_coroutine< T >
template< typename T >
pull_coroutine< T >::pull_coroutine( control_block * cb) noexcept :
cb_{ cb } {
}
template< typename T >
bool
pull_coroutine< T >::has_result_() const noexcept {
return nullptr != cb_->other->t;
}
template< typename T >
template< typename Fn,
typename
>
pull_coroutine< T >::pull_coroutine( Fn && fn) :
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
if ( ! cb_->valid() ) {
cb_->deallocate();
cb_ = nullptr;
}
}
template< typename T >
pull_coroutine< T >::~pull_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
}
template< typename T >
pull_coroutine< T >::pull_coroutine( pull_coroutine && other) noexcept :
cb_{ other.cb_ } {
other.cb_ = nullptr;
}
template< typename T >
pull_coroutine< T > &
pull_coroutine< T >::operator()() {
cb_->resume();
return * this;
}
template< typename T >
pull_coroutine< T >::operator bool() const noexcept {
return nullptr != cb_ && cb_->valid();
}
template< typename T >
bool
pull_coroutine< T >::operator!() const noexcept {
return nullptr == cb_ || ! cb_->valid();
}
template< typename T >
T
pull_coroutine< T >::get() noexcept {
return std::move( cb_->get() );
}
// pull_coroutine< T & >
template< typename T >
pull_coroutine< T & >::pull_coroutine( control_block * cb) noexcept :
cb_{ cb } {
}
template< typename T >
bool
pull_coroutine< T & >::has_result_() const noexcept {
return nullptr != cb_->other->t;
}
template< typename T >
template< typename Fn,
typename
>
pull_coroutine< T & >::pull_coroutine( Fn && fn) :
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
if ( ! cb_->valid() ) {
cb_->deallocate();
cb_ = nullptr;
}
}
template< typename T >
pull_coroutine< T & >::~pull_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
}
template< typename T >
pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) noexcept :
cb_{ other.cb_ } {
other.cb_ = nullptr;
}
template< typename T >
pull_coroutine< T & > &
pull_coroutine< T & >::operator()() {
cb_->resume();
return * this;
}
template< typename T >
pull_coroutine< T & >::operator bool() const noexcept {
return nullptr != cb_ && cb_->valid();
}
template< typename T >
bool
pull_coroutine< T & >::operator!() const noexcept {
return nullptr == cb_ || ! cb_->valid();
}
template< typename T >
T &
pull_coroutine< T & >::get() noexcept {
return cb_->get();
}
// pull_coroutine< void >
inline
pull_coroutine< void >::pull_coroutine( control_block * cb) noexcept :
cb_{ cb } {
}
template< typename Fn,
typename
>
pull_coroutine< void >::pull_coroutine( Fn && fn) :
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename StackAllocator, typename Fn >
pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
if ( ! cb_->valid() ) {
cb_->deallocate();
cb_ = nullptr;
}
}
inline
pull_coroutine< void >::~pull_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
}
inline
pull_coroutine< void >::pull_coroutine( pull_coroutine && other) noexcept :
cb_{ other.cb_ } {
other.cb_ = nullptr;
}
inline
pull_coroutine< void > &
pull_coroutine< void >::operator()() {
cb_->resume();
return * this;
}
inline
pull_coroutine< void >::operator bool() const noexcept {
return nullptr != cb_ && cb_->valid();
}
inline
bool
pull_coroutine< void >::operator!() const noexcept {
return nullptr == cb_ || ! cb_->valid();
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_IPP
@@ -0,0 +1,104 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
#include <exception>
#include <boost/config.hpp>
#include <boost/context/continuation.hpp>
#include <boost/coroutine2/detail/state.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
struct push_coroutine< T >::control_block {
boost::context::continuation c;
typename pull_coroutine< T >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename pull_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume( T const&);
void resume( T &&);
bool valid() const noexcept;
};
template< typename T >
struct push_coroutine< T & >::control_block {
boost::context::continuation c;
typename pull_coroutine< T & >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename pull_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume( T &);
bool valid() const noexcept;
};
struct push_coroutine< void >::control_block {
boost::context::continuation c;
pull_coroutine< void >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( pull_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
bool valid() const noexcept;
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
@@ -0,0 +1,400 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
#include <algorithm>
#include <exception>
#include <memory>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/continuation.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/forced_unwind.hpp>
#include <boost/coroutine2/detail/wrap.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
// push_coroutine< T >
template< typename T >
void
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
boost::context::continuation c = std::move( cb->c);
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
c.resume();
}
template< typename T >
template< typename StackAllocator, typename Fn >
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
c{},
other{ nullptr },
state{ state_t::unwind },
except{} {
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
// set transferred value
if ( other->c.data_available() ) {
synthesized_cb.set( other->c.template get_data< T >() );
} else {
synthesized_cb.reset();
}
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
},
std::forward< Fn >( fn) ) );
#else
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
// set transferred value
if ( other->c.data_available() ) {
synthesized_cb.set( other->c.template get_data< T >() );
} else {
synthesized_cb.reset();
}
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
});
#endif
}
template< typename T >
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
other{ cb },
state{ state_t::none },
except{} {
}
template< typename T >
void
push_coroutine< T >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
push_coroutine< T >::control_block::resume( T const& data) {
// pass an pointer to other context
c = c.resume( data);
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
void
push_coroutine< T >::control_block::resume( T && data) {
// pass an pointer to other context
c = c.resume( std::move( data) );
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
bool
push_coroutine< T >::control_block::valid() const noexcept {
return state_t::none == ( state & state_t::complete );
}
// push_coroutine< T & >
template< typename T >
void
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::continuation c = std::move( cb->c);
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
c.resume();
}
template< typename T >
template< typename StackAllocator, typename Fn >
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
c{},
other{ nullptr },
state{ state_t::unwind },
except{} {
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
// create synthesized pull_coroutine< T & >
typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
// set transferred value
if ( other->c.data_available() ) {
synthesized_cb.set( other->c.template get_data< T & >() );
} else {
synthesized_cb.reset();
}
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
},
std::forward< Fn >( fn) ) );
#else
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
// create synthesized pull_coroutine< T & >
typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
// set transferred value
if ( other->c.data_available() ) {
synthesized_cb.set( other->c.template get_data< T & >() );
} else {
synthesized_cb.reset();
}
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
});
#endif
}
template< typename T >
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
other{ cb },
state{ state_t::none },
except{} {
}
template< typename T >
void
push_coroutine< T & >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
push_coroutine< T & >::control_block::resume( T & t) {
// pass an pointer to other context
c = c.resume( std::ref( t) );
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
bool
push_coroutine< T & >::control_block::valid() const noexcept {
return state_t::none == ( state & state_t::complete );
}
// push_coroutine< void >
inline
void
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::continuation c = std::move( cb->c);
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
c.resume();
}
template< typename StackAllocator, typename Fn >
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
c{},
other{ nullptr },
state{ state_t::unwind },
except{} {
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
// create synthesized pull_coroutine< void >
typename pull_coroutine< void >::control_block synthesized_cb{ this, c };
pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
},
std::forward< Fn >( fn) ) );
#else
c = boost::context::callcc(
std::allocator_arg, palloc, salloc,
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
// create synthesized pull_coroutine< void >
typename pull_coroutine< void >::control_block synthesized_cb{ this, c};
pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
other->c = other->c.resume();
if ( state_t::none == ( state & state_t::destroy) ) {
try {
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( boost::context::detail::forced_unwind const&) {
throw;
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
});
#endif
}
inline
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
other{ cb },
state{ state_t::none },
except{} {
}
inline
void
push_coroutine< void >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
inline
void
push_coroutine< void >::control_block::resume() {
c = c.resume();
if ( except) {
std::rethrow_exception( except);
}
}
inline
bool
push_coroutine< void >::control_block::valid() const noexcept {
return state_t::none == ( state & state_t::complete );
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
@@ -0,0 +1,111 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
#include <functional>
#include <exception>
#include <boost/config.hpp>
#include <boost/context/execution_context.hpp>
#include <boost/coroutine2/detail/state.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
struct push_coroutine< T >::control_block {
boost::context::execution_context ctx;
typename pull_coroutine< T >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume( T const&);
void resume( T &&);
bool valid() const noexcept;
};
template< typename T >
struct push_coroutine< T & >::control_block {
boost::context::execution_context ctx;
typename pull_coroutine< T & >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume( T &);
bool valid() const noexcept;
};
struct push_coroutine< void >::control_block {
boost::context::execution_context ctx;
pull_coroutine< void >::control_block * other;
state_t state;
std::exception_ptr except;
static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
void deallocate() noexcept;
void resume();
bool valid() const noexcept;
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
@@ -0,0 +1,428 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
#include <algorithm>
#include <exception>
#include <functional>
#include <memory>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/execution_context.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/decay_copy.hpp>
#include <boost/coroutine2/detail/forced_unwind.hpp>
#include <boost/coroutine2/detail/state.hpp>
#include <boost/coroutine2/detail/wrap.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
// push_coroutine< T >
template< typename T >
void
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
template< typename T >
template< typename StackAllocator, typename Fn >
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
// set transferred value
synthesized_cb.set( t);
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
},
std::forward< Fn >( fn),
boost::context::execution_context::current() ) },
#else
ctx{ std::allocator_arg, palloc, salloc,
[this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
// set transferred value
synthesized_cb.set( t);
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
}},
#endif
other{ nullptr },
state{ state_t::unwind },
except{} {
// enter coroutine-fn in order to get other set
ctx();
}
template< typename T >
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
boost::context::execution_context const& ctx_) noexcept :
ctx{ ctx_ },
other{ cb },
state{ state_t::none },
except{} {
}
template< typename T >
push_coroutine< T >::control_block::~control_block() {
if ( state_t::none == ( state & state_t::complete) &&
state_t::none != ( state & state_t::unwind) ) {
// unwind coroutine stack
other->ctx = boost::context::execution_context::current();
ctx( context::exec_ontop_arg, unwind_coroutine);
}
}
template< typename T >
void
push_coroutine< T >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
push_coroutine< T >::control_block::resume( T const& t) {
other->ctx = boost::context::execution_context::current();
// pass an pointer to other context
ctx( const_cast< T * >( & t) );
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
void
push_coroutine< T >::control_block::resume( T && t) {
other->ctx = boost::context::execution_context::current();
// pass an pointer to other context
ctx( std::addressof( t) );
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
bool
push_coroutine< T >::control_block::valid() const noexcept {
return state_t::none == ( state & state_t::complete );
}
// push_coroutine< T & >
template< typename T >
void
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
template< typename T >
template< typename StackAllocator, typename Fn >
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
// set transferred value
synthesized_cb.t = t;
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
},
std::forward< Fn >( fn),
boost::context::execution_context::current() ) },
#else
ctx{ std::allocator_arg, palloc, salloc,
[this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
// set transferred value
synthesized_cb.t = t;
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
}},
#endif
other{ nullptr },
state{ state_t::unwind },
except{} {
// enter coroutine-fn in order to get other set
ctx();
}
template< typename T >
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
boost::context::execution_context const& ctx_) noexcept :
ctx{ ctx_ },
other{ cb },
state{ state_t::none },
except{} {
}
template< typename T >
push_coroutine< T & >::control_block::~control_block() {
if ( state_t::none == ( state & state_t::complete) &&
state_t::none != ( state & state_t::unwind) ) {
// unwind coroutine stack
other->ctx = boost::context::execution_context::current();
ctx( context::exec_ontop_arg, unwind_coroutine);
}
}
template< typename T >
void
push_coroutine< T & >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
template< typename T >
void
push_coroutine< T & >::control_block::resume( T & t) {
other->ctx = boost::context::execution_context::current();
// pass an pointer to other context
ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
if ( except) {
std::rethrow_exception( except);
}
}
template< typename T >
bool
push_coroutine< T & >::control_block::valid() const noexcept {
return state_t::none == ( state & state_t::complete );
}
// push_coroutine< void >
inline
void
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
template< typename StackAllocator, typename Fn >
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
wrap( [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx,
void * vp) mutable noexcept {
// create synthesized pull_coroutine< T >
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
ctx();
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
},
std::forward< Fn >( fn),
boost::context::execution_context::current() ) },
#else
ctx{ std::allocator_arg, palloc, salloc,
[this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
// create synthesized pull_coroutine< T >
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
ctx();
auto fn = std::move( fn_);
// call coroutine-fn with synthesized pull_coroutine as argument
fn( synthesized);
} catch ( forced_unwind const&) {
// do nothing for unwinding exception
} catch (...) {
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
other->ctx();
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
}},
#endif
other{ nullptr },
state{ state_t::unwind },
except{} {
// enter coroutine-fn in order to get other set
ctx();
}
inline
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
boost::context::execution_context const& ctx_) noexcept :
ctx{ ctx_ },
other{ cb },
state{ state_t::none },
except{} {
}
inline
push_coroutine< void >::control_block::~control_block() {
if ( state_t::none == ( state & state_t::complete) &&
state_t::none != ( state & state_t::unwind) ) {
// unwind coroutine stack
other->ctx = boost::context::execution_context::current();
ctx( context::exec_ontop_arg, unwind_coroutine);
}
}
inline
void
push_coroutine< void >::control_block::deallocate() noexcept {
if ( state_t::none != ( state & state_t::unwind) ) {
destroy( this);
}
}
inline
void
push_coroutine< void >::control_block::resume() {
other->ctx = boost::context::execution_context::current();
ctx();
if ( except) {
std::rethrow_exception( except);
}
}
inline
bool
push_coroutine< void >::control_block::valid() const noexcept {
return state_t::none == ( state & state_t::complete );
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
@@ -0,0 +1,245 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
#define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
#include <iterator>
#include <type_traits>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/disable_overload.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
template< typename T >
class push_coroutine {
private:
template< typename X >
friend class pull_coroutine;
struct control_block;
control_block * cb_;
explicit push_coroutine( control_block *) noexcept;
public:
template< typename Fn,
typename = detail::disable_overload< push_coroutine, Fn >
>
explicit push_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
push_coroutine( StackAllocator, Fn &&);
~push_coroutine();
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
push_coroutine( push_coroutine &&) noexcept;
push_coroutine & operator=( push_coroutine && other) noexcept {
if ( this == & other) return * this;
cb_ = other.cb_;
other.cb_ = nullptr;
return * this;
}
push_coroutine & operator()( T const&);
push_coroutine & operator()( T &&);
explicit operator bool() const noexcept;
bool operator!() const noexcept;
class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
private:
push_coroutine< T > * c_{ nullptr };
public:
iterator() noexcept = default;
explicit iterator( push_coroutine< T > * c) noexcept :
c_{ c } {
}
iterator & operator=( T t) {
BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_)( t) ) {
c_ = nullptr;
}
return * this;
}
bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
iterator & operator*() noexcept {
return * this;
}
iterator & operator++() noexcept {
return * this;
}
};
};
template< typename T >
class push_coroutine< T & > {
private:
template< typename X >
friend class pull_coroutine;
struct control_block;
control_block * cb_;
explicit push_coroutine( control_block *) noexcept;
public:
template< typename Fn,
typename = detail::disable_overload< push_coroutine, Fn >
>
explicit push_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
push_coroutine( StackAllocator, Fn &&);
~push_coroutine();
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
push_coroutine( push_coroutine &&) noexcept;
push_coroutine & operator=( push_coroutine && other) noexcept {
if ( this == & other) return * this;
cb_ = other.cb_;
other.cb_ = nullptr;
return * this;
}
push_coroutine & operator()( T &);
explicit operator bool() const noexcept;
bool operator!() const noexcept;
class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
private:
push_coroutine< T & > * c_{ nullptr };
public:
iterator() noexcept = default;
explicit iterator( push_coroutine< T & > * c) noexcept :
c_{ c } {
}
iterator & operator=( T & t) {
BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_)( t) ) {
c_ = nullptr;
}
return * this;
}
bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
iterator & operator*() noexcept {
return * this;
}
iterator & operator++() noexcept {
return * this;
}
};
};
template<>
class push_coroutine< void > {
private:
template< typename X >
friend class pull_coroutine;
struct control_block;
control_block * cb_;
explicit push_coroutine( control_block *) noexcept;
public:
template< typename Fn,
typename = detail::disable_overload< push_coroutine, Fn >
>
explicit push_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
push_coroutine( StackAllocator, Fn &&);
~push_coroutine();
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
push_coroutine( push_coroutine &&) noexcept;
push_coroutine & operator=( push_coroutine && other) noexcept {
if ( this == & other) return * this;
cb_ = other.cb_;
other.cb_ = nullptr;
return * this;
}
push_coroutine & operator()();
explicit operator bool() const noexcept;
bool operator!() const noexcept;
};
template< typename T >
typename push_coroutine< T >::iterator
begin( push_coroutine< T > & c) {
return typename push_coroutine< T >::iterator( & c);
}
template< typename T >
typename push_coroutine< T >::iterator
end( push_coroutine< T > &) {
return typename push_coroutine< T >::iterator();
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
@@ -0,0 +1,198 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
#define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
#include <utility>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine2/detail/config.hpp>
#include <boost/coroutine2/detail/create_control_block.ipp>
#include <boost/coroutine2/detail/disable_overload.hpp>
#include <boost/coroutine2/fixedsize_stack.hpp>
#include <boost/coroutine2/segmented_stack.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
// push_coroutine< T >
template< typename T >
push_coroutine< T >::push_coroutine( control_block * cb) noexcept :
cb_{ cb } {
}
template< typename T >
template< typename Fn,
typename
>
push_coroutine< T >::push_coroutine( Fn && fn) :
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn) :
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
}
template< typename T >
push_coroutine< T >::~push_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
}
template< typename T >
push_coroutine< T >::push_coroutine( push_coroutine && other) noexcept :
cb_{ other.cb_ } {
other.cb_ = nullptr;
}
template< typename T >
push_coroutine< T > &
push_coroutine< T >::operator()( T const& t) {
cb_->resume( t);
return * this;
}
template< typename T >
push_coroutine< T > &
push_coroutine< T >::operator()( T && t) {
cb_->resume( std::forward< T >( t) );
return * this;
}
template< typename T >
push_coroutine< T >::operator bool() const noexcept {
return nullptr != cb_ && cb_->valid();
}
template< typename T >
bool
push_coroutine< T >::operator!() const noexcept {
return nullptr == cb_ || ! cb_->valid();
}
// push_coroutine< T & >
template< typename T >
push_coroutine< T & >::push_coroutine( control_block * cb) noexcept :
cb_{ cb } {
}
template< typename T >
template< typename Fn,
typename
>
push_coroutine< T & >::push_coroutine( Fn && fn) :
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn) :
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
}
template< typename T >
push_coroutine< T & >::~push_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
}
template< typename T >
push_coroutine< T & >::push_coroutine( push_coroutine && other) noexcept :
cb_{ other.cb_ } {
other.cb_ = nullptr;
}
template< typename T >
push_coroutine< T & > &
push_coroutine< T & >::operator()( T & t) {
cb_->resume( t);
return * this;
}
template< typename T >
push_coroutine< T & >::operator bool() const noexcept {
return nullptr != cb_ && cb_->valid();
}
template< typename T >
bool
push_coroutine< T & >::operator!() const noexcept {
return nullptr == cb_ || ! cb_->valid();
}
// push_coroutine< void >
inline
push_coroutine< void >::push_coroutine( control_block * cb) noexcept :
cb_{ cb } {
}
template< typename Fn,
typename
>
push_coroutine< void >::push_coroutine( Fn && fn) :
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename StackAllocator, typename Fn >
push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn) :
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
}
inline
push_coroutine< void >::~push_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
}
inline
push_coroutine< void >::push_coroutine( push_coroutine && other) noexcept :
cb_{ other.cb_ } {
other.cb_ = nullptr;
}
inline
push_coroutine< void > &
push_coroutine< void >::operator()() {
cb_->resume();
return * this;
}
inline
push_coroutine< void >::operator bool() const noexcept {
return nullptr != cb_ && cb_->valid();
}
inline
bool
push_coroutine< void >::operator!() const noexcept {
return nullptr == cb_ || ! cb_->valid();
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
@@ -0,0 +1,87 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_DETAIL_ASYMMETRIC_COROUTINE_HPP
#define BOOST_COROUTINES2_DETAIL_ASYMMETRIC_COROUTINE_HPP
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine2/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
enum class state_t : unsigned int {
none = 0,
complete = 1 << 1,
unwind = 1 << 2,
destroy = 1 << 3
};
inline
constexpr state_t
operator&( state_t l, state_t r) {
return static_cast< state_t >(
static_cast< unsigned int >( l) & static_cast< unsigned int >( r) );
}
inline
constexpr state_t
operator|( state_t l, state_t r) {
return static_cast< state_t >(
static_cast< unsigned int >( l) | static_cast< unsigned int >( r) );
}
inline
constexpr state_t
operator^( state_t l, state_t r) {
return static_cast< state_t >(
static_cast< unsigned int >( l) ^ static_cast< unsigned int >( r) );
}
inline
constexpr state_t
operator~( state_t l) {
return static_cast< state_t >( ~static_cast< unsigned int >( l) );
}
inline
state_t &
operator&=( state_t & l, state_t r) {
l = l & r;
return l;
}
inline
state_t &
operator|=( state_t & l, state_t r) {
l = l | r;
return l;
}
inline
state_t &
operator^=( state_t & l, state_t r) {
l = l ^ r;
return l;
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_DETAIL_ASYMMETRIC_COROUTINE_HPP
@@ -0,0 +1,112 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINE2_DETAIL_WRAP_H
#define BOOST_COROUTINE2_DETAIL_WRAP_H
#include <type_traits>
#include <boost/config.hpp>
#include <boost/context/detail/invoke.hpp>
#if (BOOST_EXECUTION_CONTEXT==1)
# include <boost/context/execution_context.hpp>
#else
# include <boost/context/continuation.hpp>
#endif
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/data.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
namespace detail {
#if (BOOST_EXECUTION_CONTEXT==1)
template< typename Fn1, typename Fn2 >
class wrapper {
private:
typename std::decay< Fn1 >::type fn1_;
typename std::decay< Fn2 >::type fn2_;
boost::context::execution_context ctx_;
public:
wrapper( Fn1 && fn1, Fn2 && fn2,
boost::context::execution_context const& ctx) :
fn1_( std::move( fn1) ),
fn2_( std::move( fn2) ),
ctx_{ ctx } {
}
wrapper( wrapper const&) = delete;
wrapper & operator=( wrapper const&) = delete;
wrapper( wrapper && other) = default;
wrapper & operator=( wrapper && other) = default;
void operator()( void * vp) {
boost::context::detail::invoke(
std::move( fn1_),
fn2_, ctx_, vp);
}
};
template< typename Fn1, typename Fn2 >
wrapper< Fn1, Fn2 >
wrap( Fn1 && fn1, Fn2 && fn2,
boost::context::execution_context const& ctx) {
return wrapper< Fn1, Fn2 >(
std::forward< Fn1 >( fn1),
std::forward< Fn2 >( fn2),
ctx);
}
#else
template< typename Fn1, typename Fn2 >
class wrapper {
private:
typename std::decay< Fn1 >::type fn1_;
typename std::decay< Fn2 >::type fn2_;
public:
wrapper( Fn1 && fn1, Fn2 && fn2) :
fn1_( std::move( fn1) ),
fn2_( std::move( fn2) ) {
}
wrapper( wrapper const&) = delete;
wrapper & operator=( wrapper const&) = delete;
wrapper( wrapper && other) = default;
wrapper & operator=( wrapper && other) = default;
boost::context::continuation
operator()( boost::context::continuation && c) {
return boost::context::detail::invoke(
std::move( fn1_),
fn2_,
std::forward< boost::context::continuation >( c) );
}
};
template< typename Fn1, typename Fn2 >
wrapper< Fn1, Fn2 >
wrap( Fn1 && fn1, Fn2 && fn2) {
return wrapper< Fn1, Fn2 >(
std::forward< Fn1 >( fn1),
std::forward< Fn2 >( fn2) );
}
#endif
}}}
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINE2_DETAIL_WRAP_H
@@ -0,0 +1,36 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_FIXEDSIZE_H
#define BOOST_COROUTINES2_FIXEDSIZE_H
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/fixedsize_stack.hpp>
#include <boost/coroutine2/detail/coroutine.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
using fixedsize_stack = boost::context::fixedsize_stack;
#if !defined(BOOST_USE_SEGMENTED_STACKS)
using default_stack = boost::context::default_stack;
#endif
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_FIXEDSIZE_H
@@ -0,0 +1,33 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_POOLED_FIXEDSIZE_H
#define BOOST_COROUTINES2_POOLED_FIXEDSIZE_H
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/pooled_fixedsize_stack.hpp>
#include <boost/coroutine2/detail/coroutine.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
using pooled_fixedsize_stack = boost::context::pooled_fixedsize_stack;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_POOLED_FIXEDSIZE_H
@@ -0,0 +1,33 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_PROTECTED_FIXEDSIZE_H
#define BOOST_COROUTINES2_PROTECTED_FIXEDSIZE_H
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/protected_fixedsize_stack.hpp>
#include <boost/coroutine2/detail/coroutine.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
using protected_fixedsize_stack = boost::context::protected_fixedsize_stack;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_PROTECTED_FIXEDSIZE_H
@@ -0,0 +1,38 @@
// Copyright Oliver Kowalke 2014.
// 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_COROUTINES2_SEGMENTED_H
#define BOOST_COROUTINES2_SEGMENTED_H
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/segmented_stack.hpp>
#include <boost/coroutine2/detail/coroutine.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace coroutines2 {
#if defined(BOOST_USE_SEGMENTED_STACKS)
# if ! defined(BOOST_WINDOWS)
using segmented_stack = boost::context::segmented_stack;
using default_stack = boost::context::default_stack;
# endif
#endif
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_COROUTINES2_SEGMENTED_H