2
0
mirror of https://github.com/boostorg/context.git synced 2026-01-19 04:02:17 +00:00

remove template arg from callcc()

This commit is contained in:
Oliver Kowalke
2016-12-26 19:07:25 +01:00
parent b78e0c894b
commit ba37cd3968
15 changed files with 475 additions and 344 deletions

View File

@@ -42,6 +42,14 @@ exe jump
: jump.cpp
;
exe jump_ref
: jump_ref.cpp
;
exe jump_mov
: jump_mov.cpp
;
exe fibonacci
: fibonacci.cpp
;
@@ -54,10 +62,10 @@ exe ontop
: ontop.cpp
;
exe backtrace
: backtrace.cpp
;
exe echosse
: echosse.cpp
;
#exe backtrace
# : backtrace.cpp
# ;
#
#exe echosse
# : echosse.cpp
# ;

View File

@@ -51,7 +51,7 @@ ctx::continuation f1( ctx::continuation && c) {
}
int main() {
ctx::callcc< void >( f1);
ctx::callcc( f1);
std::cout << "main: done" << std::endl;
return EXIT_SUCCESS;
}

View File

@@ -30,16 +30,16 @@ ctx::continuation echo( ctx::continuation && c, int i) {
std::cout << i;
echoSSE( i);
std::cout << " ";
c = ctx::callcc< int >( std::move( c), 0);
i = ctx::get_data< int >( c);
c = ctx::callcc( std::move( c), 0);
std::tie( i) = ctx::data< int >( c);
}
return std::move( c);
}
int main( int argc, char * argv[]) {
ctx::continuation c = ctx::callcc< int >( echo, 0);
ctx::continuation c = ctx::callcc( echo, 0);
for ( int i = 1; i < 10; ++i) {
c = ctx::callcc< int >( std::move( c), i);
c = ctx::callcc( std::move( c), i);
}
std::cout << "\nmain: done" << std::endl;
return EXIT_SUCCESS;

View File

@@ -15,12 +15,14 @@ namespace ctx = boost::context;
int main() {
ctx::continuation c;
int i=0;
c=ctx::callcc< int >(
[](ctx::continuation && c, int) mutable {
c=ctx::callcc(
std::allocator_arg,
ctx::fixedsize_stack(),
[](ctx::continuation && c, int){
int a=0;
int b=1;
for(;;){
c=ctx::callcc< int >(std::move(c),a);
c=ctx::callcc(std::move(c),a);
auto next=a+b;
a=b;
b=next;
@@ -28,14 +30,11 @@ int main() {
return std::move( c);
},
0);
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
c=ctx::callcc< int >(std::move(c),0); i=ctx::get_data<int>(c); std::cout<<i<<" ";
for ( int j = 0; j < 10; ++j) {
c=ctx::callcc(std::move(c),0);
i=ctx::data<int>(c);
std::cout<<i<<" ";
}
std::cout<<std::endl;
std::cout << "main: done" << std::endl;
}

View File

@@ -13,8 +13,8 @@ namespace ctx = boost::context;
ctx::continuation f1( ctx::continuation && c, int data) {
std::cout << "f1: entered first time: " << data << std::endl;
c = ctx::callcc< int >( std::move( c), data + 2);
data = ctx::get_data< int >( c);
c = ctx::callcc( std::move( c), data + 2);
data = ctx::data< int >( c);
std::cout << "f1: entered second time: " << data << std::endl;
return std::move( c);
}
@@ -22,12 +22,12 @@ ctx::continuation f1( ctx::continuation && c, int data) {
int main() {
ctx::continuation c;
int data = 1;
c = ctx::callcc< int >( f1, data);
data = ctx::get_data< int >( c);
c = ctx::callcc( f1, data);
data = ctx::data< int >( c);
std::cout << "f1: returned first time: " << data << std::endl;
c = ctx::callcc< int >( std::move( c), data + 2);
c = ctx::callcc( std::move( c), data + 2);
if ( ctx::has_data( c) ) {
data = ctx::get_data< int >( c);
data = ctx::data< int >( c);
std::cout << "f1: returned second time: " << data << std::endl;
} else {
std::cout << "f1: returned second time: no data" << std::endl;

View File

@@ -0,0 +1,62 @@
// 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)
#include <cstdlib>
#include <iostream>
#include <boost/context/continuation.hpp>
namespace ctx = boost::context;
class moveable {
public:
bool state;
int value;
moveable() :
state( false),
value( -1) {
}
moveable( int v) :
state( true),
value( v) {
}
moveable( moveable && other) :
state( other.state),
value( other.value) {
other.state = false;
other.value = -1;
}
moveable & operator=( moveable && other) {
if ( this == & other) return * this;
state = other.state;
value = other.value;
other.state = false;
other.value = -1;
return * this;
}
moveable( moveable const& other) = delete;
moveable & operator=( moveable const& other) = delete;
};
ctx::continuation f1( ctx::continuation && c, moveable && data) {
c = ctx::callcc( std::move( c), std::move( data) );
return std::move( c);
}
int main() {
ctx::continuation c;
moveable data1{ 3 };
c = ctx::callcc( std::allocator_arg, ctx::fixedsize_stack{}, f1, std::move( data1) );
moveable data2;
data2 = ctx::data< moveable >( c);
std::cout << "main: done" << std::endl;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,38 @@
// 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)
#include <cstdlib>
#include <iostream>
#include <boost/context/continuation.hpp>
namespace ctx = boost::context;
ctx::continuation f1( ctx::continuation && c, int & data) {
std::cout << "f1: entered first time: " << data << std::endl;
data += 2;
c = ctx::callcc( std::move( c), std::ref( data) );
data += 2;
std::cout << "f1: entered second time: " << data << std::endl;
return std::move( c);
}
int main() {
ctx::continuation c;
int data_ = 1;
int & data = data_;
c = ctx::callcc( std::allocator_arg, ctx::fixedsize_stack{}, f1, std::ref( data) );
data = ctx::data< int & >( c);
std::cout << "f1: returned first time: " << data << std::endl;
c = ctx::callcc( std::move( c), std::ref( data) );
if ( c) {
std::cout << "f1: returned second time: " << data << std::endl;
} else {
std::cout << "f1: returned second time: no data" << std::endl;
}
std::cout << "main: done" << std::endl;
return EXIT_SUCCESS;
}

View File

@@ -13,15 +13,15 @@ namespace ctx = boost::context;
ctx::continuation f1( ctx::continuation && cm) {
std::cout << "f1: entered first time" << std::endl;
cm = ctx::callcc< void >( std::move( cm) );
cm = ctx::callcc( std::move( cm) );
std::cout << "f1: entered second time" << std::endl;
return std::move( cm);
}
int main() {
ctx::continuation c = ctx::callcc< void >( f1);
ctx::continuation c = ctx::callcc( f1);
std::cout << "f1: returned first time" << std::endl;
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
std::cout << "f1: returned second time" << std::endl;
std::cout << "main: done" << std::endl;

View File

@@ -12,32 +12,31 @@
namespace ctx = boost::context;
ctx::continuation f1( ctx::continuation && c, int data) {
std::cout << "f1: entered first time: " << data << std::endl;
c = ctx::callcc< int >( std::move( c), data + 1);
data = ctx::get_data< int >( c);
std::cout << "f1: entered second time: " << data << std::endl;
c = ctx::callcc< int >( std::move( c), data + 1);
data = ctx::get_data< int >( c);
std::cout << "f1: entered third time: " << data << std::endl;
return std::move( c);
}
int f2( int data) {
std::cout << "f2: entered: " << data << std::endl;
return -1;
}
int main() {
ctx::continuation c;
int data = 0;
c = ctx::callcc< int >( f1, data + 1);
data = ctx::get_data< int >( c);
c = ctx::callcc( [](ctx::continuation && c,int data) {
std::cout << "f1: entered first time: " << data << std::endl;
c = ctx::callcc( std::move( c), data + 1);
data = ctx::data< int >( c);
std::cout << "f1: entered second time: " << data << std::endl;
c = ctx::callcc( std::move( c), data + 1);
data = ctx::data< int >( c);
std::cout << "f1: entered third time: " << data << std::endl;
return std::move( c);
},
data + 1);
data = ctx::data< int >( c);
std::cout << "f1: returned first time: " << data << std::endl;
c = ctx::callcc< int >( std::move( c), data + 1);
data = ctx::get_data< int >( c);
c = ctx::callcc( std::move( c), data + 1);
data = ctx::data< int >( c);
std::cout << "f1: returned second time: " << data << std::endl;
c = ctx::callcc< int >( std::move( c), ctx::exec_ontop_arg, f2, data + 1);
c = ctx::callcc( std::move( c), ctx::exec_ontop_arg,
[](int data){
std::cout << "f2: entered: " << data << std::endl;
return -1;
},
data + 1);
std::cout << "f1: returned third time" << std::endl;
std::cout << "main: done" << std::endl;
return EXIT_SUCCESS;

View File

@@ -14,9 +14,9 @@ namespace ctx = boost::context;
ctx::continuation f1( ctx::continuation && c) {
std::cout << "f1: entered first time" << std::endl;
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
std::cout << "f1: entered second time" << std::endl;
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
std::cout << "f1: entered third time" << std::endl;
return std::move( c);
}
@@ -26,11 +26,11 @@ void f2() {
}
int main() {
ctx::continuation c = ctx::callcc< void >( f1);
ctx::continuation c = ctx::callcc( f1);
std::cout << "f1: returned first time" << std::endl;
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
std::cout << "f1: returned second time" << std::endl;
c = ctx::callcc< void >( std::move( c), ctx::exec_ontop_arg, f2);
c = ctx::callcc( std::move( c), ctx::exec_ontop_arg, f2);
std::cout << "f1: returned third time" << std::endl;
std::cout << "main: done" << std::endl;

View File

@@ -96,13 +96,13 @@ int main() {
boost::context::continuation source;
// user-code pulls parsed data from parser
// invert control flow
source=ctx::callcc<char>(
source=ctx::callcc(
[&is](ctx::continuation && sink,char){
// create parser with callback function
Parser p( is,
[&sink](char c){
// resume main execution context
sink=ctx::callcc<char>(std::move(sink),c);
sink=ctx::callcc(std::move(sink),c);
});
// start recursive parsing
p.run();
@@ -111,9 +111,9 @@ int main() {
},
'\0');
while(ctx::has_data(source)){
char c=ctx::get_data<char>(source);
char c=ctx::data<char>(source);
printf("Parsed: %c\n",c);
source=ctx::callcc<char>(std::move(source),'\0');
source=ctx::callcc(std::move(source),'\0');
if (!c) {
break;
}

View File

@@ -21,11 +21,11 @@ struct my_exception : public std::runtime_error {
};
int main() {
ctx::continuation c = ctx::callcc< void >([](boost::context::continuation && c) {
ctx::continuation c = ctx::callcc([](boost::context::continuation && c) {
for (;;) {
try {
std::cout << "entered" << std::endl;
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
} catch ( boost::context::ontop_error const& e) {
try {
std::rethrow_if_nested( e);
@@ -37,9 +37,9 @@ int main() {
}
return std::move( c);
});
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc< void >( std::move( c), ctx::exec_ontop_arg, []() { throw my_exception("abc"); });
c = ctx::callcc( std::move( c) );
c = ctx::callcc( std::move( c) );
c = ctx::callcc( std::move( c), ctx::exec_ontop_arg, []() { throw my_exception("abc"); });
std::cout << "main: done" << std::endl;

View File

@@ -27,6 +27,7 @@
#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
#endif
#include <boost/context/detail/decay_copy.hpp>
#include <boost/context/detail/disable_overload.hpp>
#include <boost/context/detail/exception.hpp>
#include <boost/context/detail/exchange.hpp>
@@ -293,8 +294,27 @@ fcontext_t context_create( preallocated palloc, StackAlloc salloc, Fn && fn) {
return jump_fcontext( fctx, rec).fctx;
}
template< typename ... Ret >
struct callcc_helper;
template< typename ... Arg >
struct result_type {
typedef std::tuple< Arg ... > type;
static
type get( void * data) {
auto p = static_cast< std::tuple< std::exception_ptr, std::tuple< Arg ... > > * >( data);
return std::move( std::get< 1 >( * p) );
}
};
template< typename Arg >
struct result_type< Arg > {
typedef Arg type;
static
type get( void * data) {
auto p = static_cast< std::tuple< std::exception_ptr, std::tuple< Arg > > * >( data);
return std::forward< Arg >( std::get< 0 >( std::get< 1 >( * p) ) );
}
};
}}
@@ -302,24 +322,52 @@ inline namespace v1 {
class continuation {
private:
friend class ontop_error;
template< typename ... Ret >
friend struct detail::callcc_helper;
template< typename Ctx, typename ArgTuple, typename StackAlloc, typename Fn >
friend class detail::record;
template< typename Ctx, typename StackAlloc, typename Fn >
friend class detail::record_void;
friend class ontop_error;
template< typename StackAlloc, typename Fn, typename ... Arg >
friend continuation
callcc( std::allocator_arg_t, StackAlloc, Fn &&, Arg ...);
template< typename StackAlloc, typename Fn, typename ... Arg >
friend continuation
callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&, Arg ...);
template< typename ... Arg >
friend continuation
callcc( continuation &&, Arg ...);
template< typename Fn, typename ... Arg >
friend continuation
callcc( continuation &&, exec_ontop_arg_t, Fn &&, Arg ...);
template< typename StackAlloc, typename Fn >
friend continuation
callcc( std::allocator_arg_t, StackAlloc, Fn &&);
template< typename StackAlloc, typename Fn >
friend continuation
callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
friend continuation
callcc( continuation &&);
template< typename Fn >
friend continuation
callcc( continuation &&, exec_ontop_arg_t, Fn &&);
friend bool has_data( continuation const&) noexcept;
template< typename Arg >
friend Arg get_data( continuation const&);
friend Arg get( continuation const&);
template< typename ... Arg >
friend std::tuple< Arg ... > get_data( continuation const&);
friend typename detail::result_type< Arg ... >::type data( continuation const&);
detail::fcontext_t fctx_{ nullptr };
void * data_{ nullptr };
@@ -408,6 +456,17 @@ public:
}
};
inline
bool has_data( continuation const& c) noexcept {
return c && nullptr != c.data_;
}
template< typename ... Arg >
typename detail::result_type< Arg ... >::type data( continuation const& c) {
BOOST_ASSERT( nullptr != c.data_);
return detail::result_type< Arg ... >::get( c.data_);
}
class ontop_error : public std::exception {
private:
detail::fcontext_t fctx_;
@@ -422,238 +481,164 @@ public:
}
};
inline
bool has_data( continuation const& c) noexcept {
return c && nullptr != c.data_;
}
template< typename Arg >
Arg get_data( continuation const& c) {
BOOST_ASSERT( has_data( c) );
using ArgTuple = std::tuple< Arg >;
auto p = static_cast< std::tuple< std::exception_ptr, ArgTuple > * >( c.data_);
return std::get< 0 >( std::move( std::get< 1 >( * p) ) );
}
template< typename ... Arg >
std::tuple< Arg ... > get_data( continuation const& c) {
BOOST_ASSERT( nullptr != c.data_);
using ArgTuple = std::tuple< Arg ... >;
auto p = static_cast< std::tuple< std::exception_ptr, ArgTuple > * >( c.data_);
return std::move( std::get< 1 >( * p) );
}
}
namespace detail {
inline namespace v1 {
template< typename ... Arg >
struct callcc_helper {
template< typename StackAlloc, typename Fn >
static
continuation
callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Arg ... arg) {
using ArgTuple = std::tuple< Arg ... >;
using Record = detail::record< continuation, ArgTuple, StackAlloc, Fn >;
return callcc( continuation{
context_create< Record >(
salloc, std::forward< Fn >( fn) ) },
std::forward< Arg >( arg) ... );
}
template< typename StackAlloc, typename Fn >
static
continuation
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Arg ... arg) {
using ArgTuple = std::tuple< Arg ... >;
using Record = detail::record< continuation, ArgTuple, StackAlloc, Fn >;
return callcc( continuation{
context_create< Record >(
palloc, salloc, std::forward< Fn >( fn) ) },
std::forward< Arg >( arg) ... );
}
static
continuation
callcc( continuation && c, Arg ... arg) {
BOOST_ASSERT( nullptr != c.fctx_);
using ArgTuple = std::tuple< Arg ... >;
ArgTuple tpl{ std::forward< Arg >( arg) ... };
auto p = std::make_tuple( std::exception_ptr{}, std::move( tpl) );
detail::transfer_t t = detail::jump_fcontext( detail::exchange( c.fctx_, nullptr), & p);
if ( nullptr != t.data) {
auto p = static_cast< std::tuple< std::exception_ptr, ArgTuple > * >( t.data);
std::exception_ptr eptr = std::get< 0 >( * p);
if ( eptr) {
try {
std::rethrow_exception( eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
}
return continuation{ t.fctx, t.data };
}
template< typename Fn >
static
continuation
callcc( continuation && c, exec_ontop_arg_t, Fn && fn, Arg ... arg) {
BOOST_ASSERT( nullptr != c.fctx_);
using ArgTuple = std::tuple< Arg ... >;
ArgTuple tpl{ std::forward< Arg >( arg) ... };
auto p = std::make_tuple( fn, std::make_tuple( std::exception_ptr{}, std::move( tpl) ) );
detail::transfer_t t = detail::ontop_fcontext(
detail::exchange( c.fctx_, nullptr),
& p,
detail::context_ontop< Fn, Arg ... >);
if ( nullptr != t.data) {
auto p = static_cast< std::tuple< std::exception_ptr, ArgTuple > * >( t.data);
std::exception_ptr eptr = std::get< 0 >( * p);
if ( eptr) {
try {
std::rethrow_exception( eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
}
return continuation{ t.fctx, t.data };
}
};
template<>
struct callcc_helper< void > {
template< typename StackAlloc, typename Fn >
static
continuation
callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
using Record = detail::record_void< continuation, StackAlloc, Fn >;
return callcc(
continuation{
detail::context_create< Record >(
salloc, std::forward< Fn >( fn) ) } );
}
template< typename StackAlloc, typename Fn >
static
continuation
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
using Record = detail::record_void< continuation, StackAlloc, Fn >;
return callcc(
continuation{
detail::context_create< Record >(
palloc, salloc, std::forward< Fn >( fn) ) } );
}
static
continuation
callcc( continuation && c) {
BOOST_ASSERT( nullptr != c.fctx_);
detail::transfer_t t = detail::jump_fcontext( detail::exchange( c.fctx_, nullptr), nullptr);
if ( nullptr != t.data) {
std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
try {
std::rethrow_exception( * eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
return continuation{ t.fctx };
}
template< typename Fn >
static
continuation
callcc( continuation && c, exec_ontop_arg_t, Fn && fn) {
BOOST_ASSERT( nullptr != c.fctx_);
auto p = std::make_tuple( fn, std::exception_ptr{} );
detail::transfer_t t = detail::ontop_fcontext(
detail::exchange( c.fctx_, nullptr),
& p,
detail::context_ontop_void< Fn >);
if ( nullptr != t.data) {
std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
try {
std::rethrow_exception( * eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
return continuation{ t.fctx };
}
};
}}
inline namespace v1 {
// Arg
template<
typename ... Ret,
typename Fn,
typename ... Arg,
typename = detail::disable_overload< continuation, Fn >
>
continuation
callcc( Fn && fn, Arg && ... arg) {
return detail::callcc_helper< Ret ... >::callcc(
callcc( Fn && fn, Arg ... arg) {
return callcc(
std::allocator_arg, fixedsize_stack(),
std::forward< Fn >( fn), std::forward< Arg >( arg) ...);
}
template<
typename ... Ret,
typename StackAlloc,
typename Fn,
typename ... Arg
>
continuation
callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Arg && ... arg) {
return detail::callcc_helper< Ret ... >::callcc(
std::allocator_arg, salloc,
std::forward< Fn >( fn), std::forward< Arg >( arg) ...);
callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Arg ... arg) {
using ArgTuple = std::tuple< Arg ... >;
using Record = detail::record< continuation, ArgTuple, StackAlloc, Fn >;
return callcc( continuation{
detail::context_create< Record >(
salloc, std::forward< Fn >( fn) ) },
std::forward< Arg >( arg) ... );
}
template<
typename ... Ret,
typename StackAlloc,
typename Fn,
typename ... Arg
>
continuation
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Arg && ... arg) {
return detail::callcc_helper< Ret ... >::callcc(
std::allocator_arg, palloc, salloc,
std::forward< Fn >( fn), std::forward< Arg >( arg) ...);
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Arg ... arg) {
using ArgTuple = std::tuple< Arg ... >;
using Record = detail::record< continuation, ArgTuple, StackAlloc, Fn >;
return callcc( continuation{
detail::context_create< Record >(
palloc, salloc, std::forward< Fn >( fn) ) },
std::forward< Arg >( arg) ... );
}
template<
typename ... Ret,
typename ... Arg
>
template< typename ... Arg >
continuation
callcc( continuation && c, Arg && ... arg) {
return detail::callcc_helper< Ret ... >::callcc(
std::move( c), std::forward< Arg >( arg) ... );
callcc( continuation && c, Arg ... arg) {
BOOST_ASSERT( nullptr != c.fctx_);
using ArgTuple = std::tuple< Arg ... >;
auto p = std::make_tuple( std::exception_ptr{}, ArgTuple{ std::forward< Arg >( arg) ... } );
detail::transfer_t t = detail::jump_fcontext( detail::exchange( c.fctx_, nullptr), & p);
if ( nullptr != t.data) {
auto p = static_cast< std::tuple< std::exception_ptr, ArgTuple > * >( t.data);
std::exception_ptr eptr = std::get< 0 >( * p);
if ( eptr) {
try {
std::rethrow_exception( eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
}
return continuation{ t.fctx, t.data };
}
template< typename Fn, typename ... Arg >
continuation
callcc( continuation && c, exec_ontop_arg_t, Fn && fn, Arg ... arg) {
BOOST_ASSERT( nullptr != c.fctx_);
using ArgTuple = std::tuple< Arg ... >;
auto p = std::make_tuple( fn, std::make_tuple( std::exception_ptr{}, ArgTuple{ std::forward< Arg >( arg) ... } ) );
detail::transfer_t t = detail::ontop_fcontext(
detail::exchange( c.fctx_, nullptr),
& p,
detail::context_ontop< Fn, Arg ... >);
if ( nullptr != t.data) {
auto p = static_cast< std::tuple< std::exception_ptr, ArgTuple > * >( t.data);
std::exception_ptr eptr = std::get< 0 >( * p);
if ( eptr) {
try {
std::rethrow_exception( eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
}
return continuation{ t.fctx, t.data };
}
// void
template<
typename ... Ret,
typename Fn,
typename ... Arg
typename = detail::disable_overload< continuation, Fn >
>
continuation
callcc( continuation && c, exec_ontop_arg_t, Fn && fn, Arg && ... arg) {
return detail::callcc_helper< Ret ... >::callcc(
std::move( c),
exec_ontop_arg, std::forward< Fn >( fn), std::forward< Arg >( arg) ... );
callcc( Fn && fn) {
return callcc(
std::allocator_arg, fixedsize_stack(),
std::forward< Fn >( fn) );
}
template< typename StackAlloc, typename Fn >
continuation
callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
using Record = detail::record_void< continuation, StackAlloc, Fn >;
return callcc(
continuation{
detail::context_create< Record >(
salloc, std::forward< Fn >( fn) ) } );
}
template< typename StackAlloc, typename Fn >
continuation
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
using Record = detail::record_void< continuation, StackAlloc, Fn >;
return callcc(
continuation{
detail::context_create< Record >(
palloc, salloc, std::forward< Fn >( fn) ) } );
}
inline
continuation
callcc( continuation && c) {
BOOST_ASSERT( nullptr != c.fctx_);
detail::transfer_t t = detail::jump_fcontext( detail::exchange( c.fctx_, nullptr), nullptr);
if ( nullptr != t.data) {
std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
try {
std::rethrow_exception( * eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
return continuation{ t.fctx };
}
template< typename Fn >
continuation
callcc( continuation && c, exec_ontop_arg_t, Fn && fn) {
BOOST_ASSERT( nullptr != c.fctx_);
auto p = std::make_tuple( fn, std::exception_ptr{} );
detail::transfer_t t = detail::ontop_fcontext(
detail::exchange( c.fctx_, nullptr),
& p,
detail::context_ontop_void< Fn >);
if ( nullptr != t.data) {
std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
try {
std::rethrow_exception( * eptr);
} catch (...) {
std::throw_with_nested( ontop_error{ t.fctx } );
}
}
return continuation{ t.fctx };
}
#if defined(BOOST_USE_SEGMENTED_STACKS)
template<
typename ... Ret,
typename Fn,
typename ... Arg
>
@@ -661,7 +646,6 @@ continuation
callcc( std::allocator_arg_t, segmented_stack, Fn &&, Arg ...);
template<
typename ... Ret,
typename StackAlloc,
typename Fn,
typename ... Arg

View File

@@ -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_CONTEXT_DETAIL_DECAY_COPY_H
#define BOOST_CONTEXT_DETAIL_DECAY_COPY_H
#include <type_traits>
#include <boost/config.hpp>
#include <boost/fiber/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace context {
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_CONTEXT_DETAIL_DECAY_COPY_H

View File

@@ -138,7 +138,7 @@ ctx::continuation fn5( ctx::continuation && c) {
}
ctx::continuation fn4( ctx::continuation && c) {
ctx::continuation c1 = ctx::callcc< void >( fn5);
ctx::continuation c1 = ctx::callcc( fn5);
value3 = 3.14;
return std::move( c);
}
@@ -146,9 +146,9 @@ ctx::continuation fn4( ctx::continuation && c) {
ctx::continuation fn6( ctx::continuation && c) {
try {
value1 = 3;
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
value1 = 7;
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
} catch ( my_exception & e) {
value2 = e.what();
}
@@ -157,7 +157,7 @@ ctx::continuation fn6( ctx::continuation && c) {
ctx::continuation fn7( ctx::continuation && c) {
Y y;
return ctx::callcc< void >( std::move( c) );
return ctx::callcc( std::move( c) );
}
ctx::continuation fn8( ctx::continuation && c, int i) {
@@ -167,50 +167,50 @@ ctx::continuation fn8( ctx::continuation && c, int i) {
ctx::continuation fn9( ctx::continuation && c, int i) {
value1 = i;
c = ctx::callcc< int >( std::move( c), i);
value1 = ctx::get_data< int >( c);
c = ctx::callcc( std::move( c), i);
value1 = ctx::data< int >( c);
return std::move( c);
}
ctx::continuation fn10( ctx::continuation && c, int & i) {
return ctx::callcc< int & >( std::move( c), i);
return ctx::callcc( std::move( c), std::ref( i) );
}
ctx::continuation fn11( ctx::continuation && c, moveable m) {
c = ctx::callcc< moveable >( std::move( c), std::move( m) );
m = ctx::get_data< moveable >( c);
return ctx::callcc< moveable >( std::move( c), std::move( m) );
c = ctx::callcc( std::move( c), std::move( m) );
m = ctx::data< moveable >( c);
return ctx::callcc( std::move( c), std::move( m) );
}
ctx::continuation fn12( ctx::continuation && c, int i, std::string str) {
return ctx::callcc< int, std::string >( std::move( c), i, str);
return ctx::callcc( std::move( c), i, str);
}
ctx::continuation fn13( ctx::continuation && c, int i, moveable m) {
return ctx::callcc< int, moveable >( std::move( c), i, std::move( m) );
return ctx::callcc( std::move( c), i, std::move( m) );
}
ctx::continuation fn14( ctx::continuation && c, variant_t data) {
int i = boost::get< int >( data);
data = boost::lexical_cast< std::string >( i);
return ctx::callcc< variant_t >( std::move( c), data);
return ctx::callcc( std::move( c), data);
}
ctx::continuation fn15( ctx::continuation && c, Y * py) {
return ctx::callcc< Y * >( std::move( c), py);
return ctx::callcc( std::move( c), py);
}
ctx::continuation fn16( ctx::continuation && c, int i) {
value1 = i;
c = ctx::callcc< int >( std::move( c), i);
value1 = ctx::get_data< int >( c);
c = ctx::callcc( std::move( c), i);
value1 = ctx::data< int >( c);
return std::move( c);
}
ctx::continuation fn17( ctx::continuation && c, int i, int j) {
for (;;) {
c = ctx::callcc< int, int >( std::move( c), i, j);
std::tie( i, j) = ctx::get_data< int, int >( c);
c = ctx::callcc( std::move( c), i, j);
std::tie( i, j) = ctx::data< int, int >( c);
}
return std::move( c);
}
@@ -220,15 +220,15 @@ void test_move() {
value1 = 0;
ctx::continuation c;
BOOST_CHECK( ! c );
ctx::continuation c1 = ctx::callcc< int >( fn9, 1);
ctx::continuation c2 = ctx::callcc< int >( fn9, 3);
ctx::continuation c1 = ctx::callcc( fn9, 1);
ctx::continuation c2 = ctx::callcc( fn9, 3);
BOOST_CHECK( c1 );
BOOST_CHECK( c2 );
c1 = std::move( c2);
BOOST_CHECK( c1 );
BOOST_CHECK( ! c2 );
BOOST_CHECK_EQUAL( 3, value1);
ctx::callcc< int >( std::move( c1), 0);
ctx::callcc( std::move( c1), 0);
BOOST_CHECK_EQUAL( 0, value1);
BOOST_CHECK( ! c1 );
BOOST_CHECK( ! c2 );
@@ -237,14 +237,14 @@ void test_move() {
void test_bind() {
value1 = 0;
X x;
ctx::continuation c = ctx::callcc< int >( std::bind( & X::foo, x, std::placeholders::_1, std::placeholders::_2), 7);
ctx::continuation c = ctx::callcc( std::bind( & X::foo, x, std::placeholders::_1, std::placeholders::_2), 7);
BOOST_CHECK_EQUAL( 7, value1);
}
void test_exception() {
{
const char * what = "hello world";
ctx::continuation c = ctx::callcc< const char * >( fn2, what);
ctx::continuation c = ctx::callcc( fn2, what);
BOOST_CHECK_EQUAL( std::string( what), value2);
BOOST_CHECK( ! c );
}
@@ -252,13 +252,13 @@ void test_exception() {
{
bool catched = false;
std::thread([&catched](){
ctx::continuation c = ctx::callcc< void >([&catched](ctx::continuation && c){
c = ctx::callcc< void >( std::move( c) );
ctx::continuation c = ctx::callcc([&catched](ctx::continuation && c){
c = ctx::callcc( std::move( c) );
seh( catched);
return std::move( c);
});
BOOST_CHECK( c );
ctx::callcc< void >( std::move( c) );
ctx::callcc( std::move( c) );
}).join();
BOOST_CHECK( catched);
}
@@ -267,7 +267,7 @@ void test_exception() {
void test_fp() {
double d = 7.13;
ctx::continuation c = ctx::callcc< double >( fn3, d);
ctx::continuation c = ctx::callcc( fn3, d);
BOOST_CHECK_EQUAL( 10.58, value3);
BOOST_CHECK( ! c );
}
@@ -275,7 +275,7 @@ void test_fp() {
void test_stacked() {
value1 = 0;
value3 = 0.;
ctx::continuation c = ctx::callcc< void >( fn4);
ctx::continuation c = ctx::callcc( fn4);
BOOST_CHECK_EQUAL( 3, value1);
BOOST_CHECK_EQUAL( 3.14, value3);
BOOST_CHECK( ! c );
@@ -287,7 +287,7 @@ void test_prealloc() {
ctx::stack_context sctx( alloc.allocate() );
void * sp = static_cast< char * >( sctx.sp) - 10;
std::size_t size = sctx.size - 10;
ctx::continuation c = ctx::callcc< int >( std::allocator_arg, ctx::preallocated( sp, size, sctx), alloc, fn1, 7);
ctx::continuation c = ctx::callcc( std::allocator_arg, ctx::preallocated( sp, size, sctx), alloc, fn1, 7);
BOOST_CHECK_EQUAL( 7, value1);
BOOST_CHECK( ! c );
}
@@ -295,36 +295,40 @@ void test_prealloc() {
void test_ontop() {
{
int i = 3, j = 0;
ctx::continuation c = ctx::callcc< int >([](ctx::continuation && c, int x) {
ctx::continuation c = ctx::callcc([](ctx::continuation && c, int x) {
for (;;) {
c = ctx::callcc< int >( std::move( c), x*10);
x = ctx::get_data< int >( c);
c = ctx::callcc( std::move( c), x*10);
if ( ctx::has_data( c) ) {
x = ctx::data< int >( c);
}
}
return std::move( c);
}, i);
c = ctx::callcc< int >( std::move( c), ctx::exec_ontop_arg, [](int x){ return x-10; }, i);
j = ctx::get_data< int >( c);
c = ctx::callcc( std::move( c), ctx::exec_ontop_arg, [](int x){ return x-10; }, i);
if ( ctx::has_data( c) ) {
j = ctx::data< int >( c);
}
BOOST_CHECK( c );
BOOST_CHECK_EQUAL( j, -70);
}
{
int i = 3, j = 1;
ctx::continuation c;
c = ctx::callcc< int, int >( fn17, i, j);
std::tie( i, j) = ctx::get_data< int, int >( c);
c = ctx::callcc< int, int >( std::move( c), ctx::exec_ontop_arg, [](int x,int y) { return std::make_tuple( x - y, x + y); }, i, j);
std::tie( i, j) = ctx::get_data< int, int >( c);
c = ctx::callcc( fn17, i, j);
std::tie( i, j) = ctx::data< int, int >( c);
c = ctx::callcc( std::move( c), ctx::exec_ontop_arg, [](int x,int y) { return std::make_tuple( x - y, x + y); }, i, j);
std::tie( i, j) = ctx::data< int, int >( c);
BOOST_CHECK_EQUAL( i, 2);
BOOST_CHECK_EQUAL( j, 4);
}
{
moveable m1( 7), m2, dummy;
ctx::continuation c = ctx::callcc< moveable >( fn11, std::move( dummy) );
ctx::continuation c = ctx::callcc( fn11, std::move( dummy) );
BOOST_CHECK( 7 == m1.value);
BOOST_CHECK( m1.state);
BOOST_CHECK( -1 == m2.value);
BOOST_CHECK( ! m2.state);
c = ctx::callcc< moveable >( std::move( c),
c = ctx::callcc( std::move( c),
ctx::exec_ontop_arg,
[](moveable m){
BOOST_CHECK( m.state);
@@ -332,7 +336,7 @@ void test_ontop() {
return std::move( m);
},
std::move( m1) );
m2 = ctx::get_data< moveable >( c);
m2 = ctx::data< moveable >( c);
BOOST_CHECK( ! m1.state);
BOOST_CHECK( -1 == m1.value);
BOOST_CHECK( m2.state);
@@ -344,11 +348,11 @@ void test_ontop_exception() {
{
value1 = 0;
value2 = "";
ctx::continuation c = ctx::callcc< void >([](ctx::continuation && c){
ctx::continuation c = ctx::callcc([](ctx::continuation && c){
for (;;) {
value1 = 3;
try {
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
} catch ( ctx::ontop_error const& e) {
try {
std::rethrow_if_nested( e);
@@ -360,10 +364,10 @@ void test_ontop_exception() {
}
return std::move( c);
});
c = ctx::callcc< void >( std::move( c) );
c = ctx::callcc( std::move( c) );
BOOST_CHECK_EQUAL( 3, value1);
const char * what = "hello world";
ctx::callcc< void >( std::move( c), ctx::exec_ontop_arg, [what](){ throw my_exception( what); });
ctx::callcc( std::move( c), ctx::exec_ontop_arg, [what](){ throw my_exception( what); });
BOOST_CHECK_EQUAL( 3, value1);
BOOST_CHECK_EQUAL( std::string( what), value2);
}
@@ -371,11 +375,11 @@ void test_ontop_exception() {
value2 = "";
int i = 3, j = 1;
ctx::continuation c;
c = ctx::callcc< int, int >([]( ctx::continuation && c, int x, int y) {
c = ctx::callcc([]( ctx::continuation && c, int x, int y) {
for (;;) {
try {
c = ctx::callcc< int, int >( std::move( c), x+y,x-y);
std::tie( x, y) = ctx::get_data< int, int >( c);
c = ctx::callcc( std::move( c), x+y,x-y);
std::tie( x, y) = ctx::data< int, int >( c);
} catch ( boost::context::ontop_error const& e) {
try {
std::rethrow_if_nested( e);
@@ -389,11 +393,11 @@ void test_ontop_exception() {
},
i, j);
BOOST_CHECK( c );
std::tie( i, j) = ctx::get_data< int, int >( c);
std::tie( i, j) = ctx::data< int, int >( c);
BOOST_CHECK_EQUAL( i, 4);
BOOST_CHECK_EQUAL( j, 2);
const char * what = "hello world";
c = ctx::callcc< int, int >( std::move( c),
c = ctx::callcc( std::move( c),
ctx::exec_ontop_arg,
[what](int x, int y) {
throw my_exception(what);
@@ -410,14 +414,14 @@ void test_ontop_exception() {
void test_termination() {
{
value1 = 0;
ctx::continuation c = ctx::callcc< void >( fn7);
ctx::continuation c = ctx::callcc( fn7);
BOOST_CHECK_EQUAL( 3, value1);
}
BOOST_CHECK_EQUAL( 7, value1);
{
value1 = 0;
BOOST_CHECK_EQUAL( 0, value1);
ctx::continuation c = ctx::callcc< void >( fn5);
ctx::continuation c = ctx::callcc( fn5);
BOOST_CHECK_EQUAL( 3, value1);
BOOST_CHECK( ! c );
}
@@ -427,13 +431,13 @@ void test_termination() {
int i = 3;
ctx::continuation c;
BOOST_CHECK( ! c );
c = ctx::callcc< int >( fn9, i);
c = ctx::callcc( fn9, i);
BOOST_CHECK( c );
i = ctx::get_data< int >( c);
i = ctx::data< int >( c);
BOOST_CHECK_EQUAL( i, value1);
BOOST_CHECK( c );
i = 7;
c = ctx::callcc< int >( std::move( c), i);
c = ctx::callcc( std::move( c), i);
BOOST_CHECK( ! c );
BOOST_CHECK_EQUAL( i, value1);
}
@@ -444,14 +448,14 @@ void test_one_arg() {
int dummy = 0;
value1 = 0;
ctx::continuation c;
c = ctx::callcc< int >( fn8, 7);
c = ctx::callcc( fn8, 7);
BOOST_CHECK_EQUAL( 7, value1);
}
{
int i = 3, j = 0;
ctx::continuation c;
c = ctx::callcc< int >( fn9, i);
j = ctx::get_data< int >( c);
c = ctx::callcc( fn9, i);
j = ctx::data< int >( c);
BOOST_CHECK_EQUAL( i, j);
}
{
@@ -460,9 +464,11 @@ void test_one_arg() {
int & j = j_;
BOOST_CHECK_EQUAL( i, i_);
BOOST_CHECK_EQUAL( j, j_);
BOOST_CHECK( & i != & j);
ctx::continuation c;
c = ctx::callcc< int & >( fn10, i);
j = ctx::get_data< int & >( c);
c = ctx::callcc( fn10, std::ref( i) );
BOOST_CHECK( ctx::has_data( c) );
j = ctx::data< int & >( c);
BOOST_CHECK_EQUAL( i, i_);
BOOST_CHECK_EQUAL( j, i_);
}
@@ -470,8 +476,8 @@ void test_one_arg() {
Y y;
Y * py = nullptr;
ctx::continuation c;
c = ctx::callcc< Y * >( fn15, & y);
py = ctx::get_data< Y * >( c);
c = ctx::callcc( fn15, & y);
py = ctx::data< Y * >( c);
BOOST_CHECK( py == & y);
}
{
@@ -481,8 +487,8 @@ void test_one_arg() {
BOOST_CHECK( -1 == m2.value);
BOOST_CHECK( ! m2.state);
ctx::continuation c;
c = ctx::callcc< moveable >( fn11, std::move( m1) );
m2 = ctx::get_data< moveable >( c);
c = ctx::callcc( fn11, std::move( m1) );
m2 = ctx::data< moveable >( c);
BOOST_CHECK( -1 == m1.value);
BOOST_CHECK( ! m1.state);
BOOST_CHECK( 7 == m2.value);
@@ -494,9 +500,8 @@ void test_two_args() {
{
int i1 = 3, i2 = 0;
std::string str1("abc"), str2;
ctx::continuation c;
c = ctx::callcc< int, std::string >( fn12, i1, str1);
std::tie( i2, str2) = ctx::get_data< int, std::string >( c);
ctx::continuation c = ctx::callcc( fn12, i1, str1);
std::tie( i2, str2) = ctx::data< int, std::string >( c);
BOOST_CHECK_EQUAL( i1, i2);
BOOST_CHECK_EQUAL( str1, str2);
}
@@ -508,8 +513,8 @@ void test_two_args() {
BOOST_CHECK( -1 == m2.value);
BOOST_CHECK( ! m2.state);
ctx::continuation c;
c = ctx::callcc< int, moveable >( fn13, i1, std::move( m1) );
std::tie( i2, m2) = ctx::get_data< int, moveable >( c);
c = ctx::callcc( fn13, i1, std::move( m1) );
std::tie( i2, m2) = ctx::data< int, moveable >( c);
BOOST_CHECK_EQUAL( i1, i2);
BOOST_CHECK( -1 == m1.value);
BOOST_CHECK( ! m1.state);
@@ -523,8 +528,8 @@ void test_variant() {
int i = 7;
variant_t data1 = i, data2;
ctx::continuation c;
c = ctx::callcc< variant_t >( fn14, data1);
data2 = ctx::get_data< variant_t >( c);
c = ctx::callcc( fn14, data1);
data2 = ctx::data< variant_t >( c);
std::string str = boost::get< std::string >( data2);
BOOST_CHECK_EQUAL( std::string("7"), str);
}
@@ -532,7 +537,7 @@ void test_variant() {
#ifdef BOOST_WINDOWS
void test_bug12215() {
ctx::continuation c = ctx::callcc< void >(
ctx::continuation c = ctx::callcc(
[](ctx::continuation && c) {
char buffer[MAX_PATH];
GetModuleFileName( nullptr, buffer, MAX_PATH);