summaryrefslogtreecommitdiff
path: root/boost/context
diff options
context:
space:
mode:
Diffstat (limited to 'boost/context')
-rw-r--r--boost/context/all.hpp4
-rw-r--r--boost/context/detail/apply.hpp55
-rw-r--r--boost/context/detail/config.hpp59
-rw-r--r--boost/context/detail/disable_overload.hpp40
-rw-r--r--boost/context/detail/exception.hpp36
-rw-r--r--boost/context/detail/exchange.hpp36
-rw-r--r--boost/context/detail/fcontext.hpp (renamed from boost/context/fcontext.hpp)31
-rw-r--r--boost/context/detail/index_sequence.hpp72
-rw-r--r--boost/context/detail/invoke.hpp58
-rw-r--r--boost/context/detail/tuple.hpp129
-rw-r--r--boost/context/execution_context.hpp12
-rw-r--r--boost/context/execution_context.ipp452
-rw-r--r--boost/context/execution_context_v1.hpp487
-rw-r--r--boost/context/execution_context_v2.hpp395
-rw-r--r--boost/context/execution_context_v2_void.ipp290
-rw-r--r--boost/context/execution_context_winfib.ipp361
-rw-r--r--boost/context/fixedsize_stack.hpp11
-rw-r--r--boost/context/flags.hpp28
-rw-r--r--boost/context/pooled_fixedsize_stack.hpp115
-rw-r--r--boost/context/posix/protected_fixedsize_stack.hpp4
-rw-r--r--boost/context/posix/segmented_stack.hpp4
-rw-r--r--boost/context/preallocated.hpp39
-rw-r--r--boost/context/stack_context.hpp55
-rw-r--r--boost/context/stack_traits.hpp10
-rw-r--r--boost/context/windows/protected_fixedsize_stack.hpp10
25 files changed, 1839 insertions, 954 deletions
diff --git a/boost/context/all.hpp b/boost/context/all.hpp
index 152f299089..44b734cdb8 100644
--- a/boost/context/all.hpp
+++ b/boost/context/all.hpp
@@ -4,10 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/context/fcontext.hpp>
+#include <boost/context/execution_context.hpp>
#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/pooled_fixedsize_stack.hpp>
#include <boost/context/protected_fixedsize_stack.hpp>
#include <boost/context/segmented_stack.hpp>
#include <boost/context/stack_context.hpp>
#include <boost/context/stack_traits.hpp>
-#include <boost/context/execution_context.hpp>
diff --git a/boost/context/detail/apply.hpp b/boost/context/detail/apply.hpp
new file mode 100644
index 0000000000..54db844b9e
--- /dev/null
+++ b/boost/context/detail/apply.hpp
@@ -0,0 +1,55 @@
+
+// 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_APPLY_H
+#define BOOST_CONTEXT_DETAIL_APPLY_H
+
+#include <functional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/detail/invoke.hpp>
+#include <boost/context/detail/index_sequence.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename Fn, typename Tpl, std::size_t ... I >
+auto
+apply_impl( Fn && fn, Tpl && tpl, index_sequence< I ... >)
+ -> decltype( invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ) )
+{
+ return invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... );
+}
+
+template< typename Fn, typename Tpl >
+auto
+apply( Fn && fn, Tpl && tpl)
+ -> decltype( apply_impl( std::forward< Fn >( fn),
+ std::forward< Tpl >( tpl),
+ make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{}) )
+{
+ return apply_impl( std::forward< Fn >( fn),
+ std::forward< Tpl >( tpl),
+ make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{});
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_APPLY_H
diff --git a/boost/context/detail/config.hpp b/boost/context/detail/config.hpp
index 0d5fa757fa..84dd238100 100644
--- a/boost/context/detail/config.hpp
+++ b/boost/context/detail/config.hpp
@@ -57,32 +57,51 @@
# define BOOST_CONTEXT_SEGMENTS 10
#endif
-#undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || \
- defined(BOOST_NO_CXX11_DECLTYPE) || \
- defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || \
- defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || \
+
+#define BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
+// use rd6 macros for std::integer_sequence
+#if defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304
+# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
+#endif
+// workaroud: MSVC 14 does not provide macros to test for compile-time integer sequence
+#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013
+# undef BOOST_CONTEXT_NO_INDEX_SEQUENCE
+#endif
+// workaround: Xcode clang feature detection
+#if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304
+# if _LIBCPP_STD_VER > 11
+# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
+# endif
+#endif
+
+// workaroud: MSVC 14 does support constexpr
+#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013
+# undef BOOST_NO_CXX11_CONSTEXPR
+#endif
+
+#undef BOOST_CONTEXT_NO_CXX11
+#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \
+ defined(BOOST_NO_CXX11_CONSTEXPR) || \
+ defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \
+ defined(BOOST_NO_CXX11_FINAL) || \
defined(BOOST_NO_CXX11_HDR_TUPLE) || \
- defined(BOOST_NO_CXX11_LAMBDAS) || \
defined(BOOST_NO_CXX11_NOEXCEPT) || \
defined(BOOST_NO_CXX11_NULLPTR) || \
- defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \
defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
- defined(BOOST_NO_CXX11_VARIADIC_MACROS) || \
+ defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \
+ defined(BOOST_NO_CXX11_UNIFIED_INITIALISATION_SYNTAX) || \
defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
- defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES) || \
- ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence < 201304
-# define BOOST_CONTEXT_NO_EXECUTION_CONTEXT
-#endif
-// workaroud: MSVC 14 does not provide macros to test for compile-time integer sequence
-#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013
-# undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT
+ defined(BOOST_NO_HDR_ATOMIC) || \
+ defined(BOOST_NO_HDR_TUPLE)
+# define BOOST_CONTEXT_NO_CXX11
#endif
-// workaround: Xcode clang feature detection
-#if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence < 201304
-# if _LIBCPP_STD_VER > 11
-# undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT
-# endif
+
+#if ! defined(BOOST_EXECUTION_CONTEXT)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+# define BOOST_EXECUTION_CONTEXT 1
+# else
+# define BOOST_EXECUTION_CONTEXT 2
+# endif
#endif
#endif // BOOST_CONTEXT_DETAIL_CONFIG_H
diff --git a/boost/context/detail/disable_overload.hpp b/boost/context/detail/disable_overload.hpp
new file mode 100644
index 0000000000..c88f916e39
--- /dev/null
+++ b/boost/context/detail/disable_overload.hpp
@@ -0,0 +1,40 @@
+
+// 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_DISABLE_OVERLOAD_H
+#define BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_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 context {
+namespace detail {
+
+// http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
+template< typename X, typename Y >
+using disable_overload =
+ typename std::enable_if<
+ ! std::is_base_of<
+ X,
+ typename std::decay< Y >::type
+ >::value
+ >::type;
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H
diff --git a/boost/context/detail/exception.hpp b/boost/context/detail/exception.hpp
new file mode 100644
index 0000000000..8ffff6780a
--- /dev/null
+++ b/boost/context/detail/exception.hpp
@@ -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_EXCEPTION_H
+#define BOOST_CONTEXT_DETAIL_EXCEPTION_H
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/fcontext.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+struct forced_unwind {
+ fcontext_t fctx;
+
+ forced_unwind( fcontext_t fctx_) :
+ fctx( fctx_) {
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_EXCEPTION_H
diff --git a/boost/context/detail/exchange.hpp b/boost/context/detail/exchange.hpp
new file mode 100644
index 0000000000..c5ee91284e
--- /dev/null
+++ b/boost/context/detail/exchange.hpp
@@ -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_EXCHANGE_H
+#define BOOST_CONTEXT_DETAIL_EXCHANGE_H
+
+#include <algorithm>
+#include <utility>
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename T, typename U = T >
+T exchange( T & t, U && nv) {
+ T ov = std::move( t);
+ t = std::forward< U >( nv);
+ return ov;
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_EXCHANGE_H
diff --git a/boost/context/fcontext.hpp b/boost/context/detail/fcontext.hpp
index 2ebcd46e38..00cb24d941 100644
--- a/boost/context/fcontext.hpp
+++ b/boost/context/detail/fcontext.hpp
@@ -4,16 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXT_FCONTEXT_H
-#define BOOST_CONTEXT_FCONTEXT_H
-
-#if defined(__PGI)
-#include <stdint.h>
-#endif
-
-#if defined(_WIN32_WCE)
-typedef int intptr_t;
-#endif
+#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_H
+#define BOOST_CONTEXT_DETAIL_FCONTEXT_H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -26,20 +18,29 @@ typedef int intptr_t;
namespace boost {
namespace context {
+namespace detail {
typedef void* fcontext_t;
+struct transfer_t {
+ fcontext_t fctx;
+ void * data;
+};
+
+extern "C" BOOST_CONTEXT_DECL
+transfer_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t const to, void * vp);
extern "C" BOOST_CONTEXT_DECL
-intptr_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t * ofc, fcontext_t nfc,
- intptr_t vp, bool preserve_fpu = false);
+fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( transfer_t) );
+
+// based on an idea of Giovanni Derreta
extern "C" BOOST_CONTEXT_DECL
-fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) );
+transfer_t BOOST_CONTEXT_CALLDECL ontop_fcontext( fcontext_t const to, void * vp, transfer_t (* fn)( transfer_t) );
-}}
+}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXT_FCONTEXT_H
+#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_H
diff --git a/boost/context/detail/index_sequence.hpp b/boost/context/detail/index_sequence.hpp
new file mode 100644
index 0000000000..2d484ba062
--- /dev/null
+++ b/boost/context/detail/index_sequence.hpp
@@ -0,0 +1,72 @@
+
+// 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_INDEX_SEQUENCE_H
+#define BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+#if ! defined(BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE)
+template< std::size_t ... I >
+using index_sequence = std::index_sequence< I ... >;
+template< std::size_t I >
+using make_index_sequence = std::make_index_sequence< I >;
+template< typename ... T >
+using index_sequence_for = std::index_sequence_for< T ... >;
+#else
+//http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
+
+template< std::size_t ... I >
+struct index_sequence {
+ using type = index_sequence;
+ using value_type = std::size_t;
+ static constexpr std::size_t size() {
+ return sizeof ... (I);
+ }
+};
+
+template< typename Seq1, typename Seq2 >
+struct concat_sequence;
+
+template< std::size_t ... I1, std::size_t ... I2 >
+struct concat_sequence< index_sequence< I1 ... >, index_sequence< I2 ... > > : public index_sequence< I1 ..., (sizeof ... (I1)+I2) ... > {
+};
+
+template< std::size_t I >
+struct make_index_sequence : public concat_sequence< typename make_index_sequence< I/2 >::type,
+ typename make_index_sequence< I-I/2 >::type > {
+};
+
+template<>
+struct make_index_sequence< 0 > : public index_sequence<> {
+};
+template<>
+struct make_index_sequence< 1 > : public index_sequence< 0 > {
+};
+
+template< typename ... T >
+using index_sequence_for = make_index_sequence< sizeof ... (T) >;
+#endif
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H
diff --git a/boost/context/detail/invoke.hpp b/boost/context/detail/invoke.hpp
index f63d22c3ff..5ec54800e3 100644
--- a/boost/context/detail/invoke.hpp
+++ b/boost/context/detail/invoke.hpp
@@ -13,6 +13,8 @@
#include <boost/config.hpp>
+#include <boost/context/detail/config.hpp>
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
@@ -21,61 +23,27 @@ namespace boost {
namespace context {
namespace detail {
-# if _MSC_VER > 1800
+#if _MSC_VER > 1800
using std::invoke;
-# else
-template< typename Fn, typename ... Args >
-typename std::enable_if<
- ( ! std::is_member_pointer< Fn >::value &&
- ! std::is_function< Fn >::value &&
- ! std::is_function< typename std::remove_pointer< Fn >::type >::value
- ),
- typename std::result_of< Fn( Args ... ) >::type
->::type
-invoke( Fn & fn, Args && ... args) {
- return fn( std::forward< Args >( args) ... );
-}
-
+#else
template< typename Fn, typename ... Args >
typename std::enable_if<
- ( std::is_member_pointer< Fn >::value &&
- ! std::is_function< Fn >::value &&
- ! std::is_function< typename std::remove_pointer< Fn >::type >::value
- ),
- typename std::result_of< Fn( Args ... ) >::type
+ std::is_member_pointer< typename std::decay< Fn >::type >::value,
+ typename std::result_of< Fn &&( Args && ... ) >::type
>::type
-invoke( Fn & fn, Args && ... args) {
- return std::mem_fn( fn)( std::forward< Args >( args) ... );
+invoke( Fn && fn, Args && ... args) {
+ return std::mem_fn( fn)( std::forward< Args >( args) ... );
}
template< typename Fn, typename ... Args >
typename std::enable_if<
- ( std::is_pointer< Fn >::value &&
- std::is_function< typename std::remove_pointer< Fn >::type >::value
- ),
- typename std::result_of< Fn( Args ... ) >::type
+ ! std::is_member_pointer< typename std::decay< Fn >::type >::value,
+ typename std::result_of< Fn &&( Args && ... ) >::type
>::type
-invoke( Fn fn, Args && ... args) {
- return fn( std::forward< Args >( args) ... );
-}
-# endif
-
-template< typename Fn, typename Tpl, std::size_t... I >
-decltype( auto) do_invoke( Fn && fn, Tpl && tpl, std::index_sequence< I ... >) {
- return invoke( fn,
- // std::tuple_element<> does not perfect forwarding
- std::forward< decltype( std::get< I >( std::declval< typename std::decay< Tpl >::type >() ) ) >(
- std::get< I >( std::forward< typename std::decay< Tpl >::type >( tpl) ) ) ... );
-}
-
-
-template< typename Fn, typename Tpl >
-decltype( auto) do_invoke( Fn && fn, Tpl && tpl) {
- constexpr auto Size = std::tuple_size< typename std::decay< Tpl >::type >::value;
- return do_invoke( std::forward< Fn >( fn),
- std::forward< Tpl >( tpl),
- std::make_index_sequence< Size >{});
+invoke( Fn && fn, Args && ... args) {
+ return std::forward< Fn >( fn)( std::forward< Args >( args) ... );
}
+#endif
}}}
diff --git a/boost/context/detail/tuple.hpp b/boost/context/detail/tuple.hpp
new file mode 100644
index 0000000000..e1b2f867a7
--- /dev/null
+++ b/boost/context/detail/tuple.hpp
@@ -0,0 +1,129 @@
+
+// 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_TUPLE_H
+#define BOOST_CONTEXT_DETAIL_TUPLE_H
+
+#include <tuple>
+#include <utility>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/detail/index_sequence.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename ... S, typename ... T, std::size_t ... I >
+void
+head_impl( std::tuple< S ... > & s,
+ std::tuple< T ... > & t, index_sequence< I ... >) {
+ t = std::tuple< T ... >{ std::get< I >( s) ... };
+}
+
+template< typename ... S, typename ... T, std::size_t ... I >
+void
+head_impl( std::tuple< S ... > && s,
+ std::tuple< T ... > & t, index_sequence< I ... >) {
+ t = std::tuple< T ... >{ std::get< I >( std::move( s) ) ... };
+}
+
+template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 >
+void
+tail_impl( std::tuple< S ... > & s, index_sequence< I1 ... >,
+ std::tuple< T ... > & t, index_sequence< I2 ... >) {
+ constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2));
+ t = std::tuple< T ... >{ std::get< (Idx + I2) >( s) ... };
+}
+
+template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 >
+void
+tail_impl( std::tuple< S ... > && s, index_sequence< I1 ... >,
+ std::tuple< T ... > & t, index_sequence< I2 ... >) {
+ constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2));
+ t = std::tuple< T ... >{ std::get< (Idx + I2) >( std::move( s) ) ... };
+}
+
+template< typename ... T >
+class tuple_head;
+
+template< typename ... T >
+class tuple_head< std::tuple< T ... > > {
+private:
+ std::tuple< T ... > & t_;
+
+public:
+ tuple_head( std::tuple< T ... > & t) noexcept :
+ t_( t) {
+ }
+
+ template< typename ... S >
+ void operator=( std::tuple< S ... > & s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ head_impl( s,
+ t_, index_sequence_for< T ... >{} );
+ }
+ template< typename ... S >
+ void operator=( std::tuple< S ... > && s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ head_impl( std::move( s),
+ t_, index_sequence_for< T ... >{} );
+ }
+};
+
+template< typename ... T >
+class tuple_tail;
+
+template< typename ... T >
+class tuple_tail< std::tuple< T ... > > {
+private:
+ std::tuple< T ... > & t_;
+
+public:
+ tuple_tail( std::tuple< T ... > & t) noexcept :
+ t_( t) {
+ }
+
+ template< typename ... S >
+ void operator=( std::tuple< S ... > & s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ tail_impl( s, index_sequence_for< S ... >{},
+ t_, index_sequence_for< T ... >{} );
+ }
+
+ template< typename ... S >
+ void operator=( std::tuple< S ... > && s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ tail_impl( std::move( s), index_sequence_for< S ... >{},
+ t_, index_sequence_for< T ... >{} );
+ }
+};
+
+template< typename ... T >
+detail::tuple_head< std::tuple< T ... > >
+head( std::tuple< T ... > & tpl) {
+ return tuple_head< std::tuple< T ... > >{ tpl };
+}
+
+template< typename ... T >
+detail::tuple_tail< std::tuple< T ... > >
+tail( std::tuple< T ... > & tpl) {
+ return tuple_tail< std::tuple< T ... > >{ tpl };
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_TUPLE_H
diff --git a/boost/context/execution_context.hpp b/boost/context/execution_context.hpp
index 97b1d4e70a..9d9294f91d 100644
--- a/boost/context/execution_context.hpp
+++ b/boost/context/execution_context.hpp
@@ -4,8 +4,12 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#if defined(BOOST_USE_WINFIBERS)
-#include <boost/context/execution_context_winfib.ipp>
-#else
-#include <boost/context/execution_context.ipp>
+#include <boost/context/detail/config.hpp>
+
+#if ! defined(BOOST_CONTEXT_NO_CXX11)
+# if (defined(BOOST_EXECUTION_CONTEXT) && (BOOST_EXECUTION_CONTEXT == 1))
+# include <boost/context/execution_context_v1.hpp>
+# else
+# include <boost/context/execution_context_v2.hpp>
+# endif
#endif
diff --git a/boost/context/execution_context.ipp b/boost/context/execution_context.ipp
deleted file mode 100644
index ec5443297f..0000000000
--- a/boost/context/execution_context.ipp
+++ /dev/null
@@ -1,452 +0,0 @@
-
-// 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_EXECUTION_CONTEXT_H
-#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
-
-#include <boost/context/detail/config.hpp>
-
-#if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT)
-
-# include <algorithm>
-# include <atomic>
-# include <cstddef>
-# include <cstdint>
-# include <cstdlib>
-# include <functional>
-# include <memory>
-# include <ostream>
-# include <tuple>
-# include <utility>
-
-# include <boost/assert.hpp>
-# include <boost/config.hpp>
-# include <boost/context/fcontext.hpp>
-# include <boost/intrusive_ptr.hpp>
-
-# include <boost/context/detail/invoke.hpp>
-# include <boost/context/fixedsize_stack.hpp>
-# include <boost/context/stack_context.hpp>
-# include <boost/context/segmented_stack.hpp>
-
-# ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-# endif
-
-# if defined(BOOST_USE_SEGMENTED_STACKS)
-extern "C" {
-
-void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
-
-void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
-
-}
-# endif
-
-namespace boost {
-namespace context {
-namespace detail {
-
-struct activation_record {
- typedef boost::intrusive_ptr< activation_record > ptr_t;
-
- enum flag_t {
- flag_main_ctx = 1 << 1,
- flag_preserve_fpu = 1 << 2
- };
-
- thread_local static ptr_t current_rec;
-
- std::atomic< std::size_t > use_count;
- fcontext_t fctx;
- stack_context sctx;
- int flags;
-
- // used for toplevel-context
- // (e.g. main context, thread-entry context)
- activation_record() noexcept :
- use_count( 0),
- fctx( nullptr),
- sctx(),
- flags( flag_main_ctx) {
- }
-
- activation_record( fcontext_t fctx_, stack_context sctx_) noexcept :
- use_count( 0),
- fctx( fctx_),
- sctx( sctx_),
- flags( 0) {
- }
-
- virtual ~activation_record() noexcept = default;
-
- void * resume( void * vp, bool fpu) noexcept {
- // store current activation record in local variable
- activation_record * from = current_rec.get();
- // store `this` in static, thread local pointer
- // `this` will become the active (running) context
- // returned by execution_context::current()
- current_rec = this;
- // set FPU flag
- if (fpu) {
- from->flags |= flag_preserve_fpu;
- this->flags |= flag_preserve_fpu;
- } else {
- from->flags &= ~flag_preserve_fpu;
- this->flags &= ~flag_preserve_fpu;
- }
-# if defined(BOOST_USE_SEGMENTED_STACKS)
- // adjust segmented stack properties
- __splitstack_getcontext( from->sctx.segments_ctx);
- __splitstack_setcontext( sctx.segments_ctx);
-# endif
- // context switch from parent context to `this`-context
- intptr_t ret = jump_fcontext( & from->fctx, fctx, reinterpret_cast< intptr_t >( vp), fpu);
- // parent context resumed
- return reinterpret_cast< void * >( ret);
- }
-
- virtual void deallocate() {
- delete this;
- }
-
- friend void intrusive_ptr_add_ref( activation_record * ar) {
- ++ar->use_count;
- }
-
- friend void intrusive_ptr_release( activation_record * ar) {
- BOOST_ASSERT( nullptr != ar);
-
- if ( 0 == --ar->use_count) {
- ar->deallocate();
- }
- }
-};
-
-struct activation_record_initializer {
- activation_record_initializer();
- ~activation_record_initializer();
-};
-
-template< typename Fn, typename Tpl, typename StackAlloc >
-class capture_record : public activation_record {
-private:
- StackAlloc salloc_;
- Fn fn_;
- Tpl tpl_;
- activation_record * caller_;
-
- static void destroy( capture_record * p) {
- StackAlloc salloc( p->salloc_);
- stack_context sctx( p->sctx);
- // deallocate activation record
- p->~capture_record();
- // destroy stack with stack allocator
- salloc.deallocate( sctx);
- }
-
-public:
- explicit capture_record(
- stack_context sctx, StackAlloc const& salloc,
- fcontext_t fctx,
- Fn && fn, Tpl && tpl,
- activation_record * caller) noexcept :
- activation_record( fctx, sctx),
- salloc_( salloc),
- fn_( std::forward< Fn >( fn) ),
- tpl_( std::forward< Tpl >( tpl) ),
- caller_( caller) {
- }
-
- void deallocate() override final {
- destroy( this);
- }
-
- void run() noexcept {
- try {
- void * vp = caller_->resume( caller_, true);
- do_invoke( fn_, std::tuple_cat( tpl_, std::tie( vp) ) );
- } catch (...) {
- std::terminate();
- }
- BOOST_ASSERT( 0 == (flags & flag_main_ctx) );
- }
-};
-
-}
-
-struct preallocated {
- void * sp;
- std::size_t size;
- stack_context sctx;
-
- preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
- sp( sp_), size( size_), sctx( sctx_) {
- }
-};
-
-class BOOST_CONTEXT_DECL execution_context {
-private:
- // tampoline function
- // entered if the execution context
- // is resumed for the first time
- template< typename AR >
- static void entry_func( intptr_t p) noexcept {
- BOOST_ASSERT( 0 != p);
-
- AR * ar( reinterpret_cast< AR * >( p) );
- BOOST_ASSERT( nullptr != ar);
-
- // start execution of toplevel context-function
- ar->run();
- }
-
- typedef boost::intrusive_ptr< detail::activation_record > ptr_t;
-
- ptr_t ptr_;
-
- template< typename StackAlloc, typename Fn ,typename Tpl >
- static detail::activation_record * create_context(
- StackAlloc salloc,
- Fn && fn, Tpl && tpl) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- std::size_t size = sctx.size - sizeof( capture_t);
- void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( capture_t);
- constexpr std::size_t func_size = sizeof( capture_t);
- // 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
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
- BOOST_ASSERT( nullptr != fctx);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placment new for control structure on fast-context stack
- return new ( sp) capture_t(
- sctx, salloc, fctx, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get() );
- }
-
- template< typename StackAlloc, typename Fn , typename Tpl >
- static detail::activation_record * create_context(
- preallocated palloc, StackAlloc salloc,
- Fn && fn, Tpl && tpl) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- std::size_t size = palloc.size - sizeof( capture_t);
- void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( capture_t);
- constexpr std::size_t func_size = sizeof( capture_t);
- // reserve space on stack
- void * sp = static_cast< char * >( palloc.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
- std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
- BOOST_ASSERT( nullptr != fctx);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placment new for control structure on fast-context stack
- return new ( sp) capture_t(
- palloc.sctx, salloc, fctx, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get() );
- }
-
- execution_context() :
- // default constructed with current activation_record
- ptr_( detail::activation_record::current_rec) {
- }
-
-public:
- static execution_context current() noexcept;
-
-# if defined(BOOST_USE_SEGMENTED_STACKS)
- template< typename Fn, typename ... Args >
- explicit execution_context( Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( segmented_stack(),
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, segmented_stack salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( palloc, salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-# else
- template< typename Fn, typename ... Args >
- explicit execution_context( Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( fixedsize_stack(),
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( palloc, salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-# endif
-
- execution_context( execution_context const& other) noexcept :
- ptr_( other.ptr_) {
- }
-
- execution_context( execution_context && other) noexcept :
- ptr_( other.ptr_) {
- other.ptr_.reset();
- }
-
- execution_context & operator=( execution_context const& other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- }
- return * this;
- }
-
- execution_context & operator=( execution_context && other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- other.ptr_.reset();
- }
- return * this;
- }
-
- void * operator()( void * vp = nullptr, bool preserve_fpu = false) noexcept {
- return ptr_->resume( vp, preserve_fpu);
- }
-
- explicit operator bool() const noexcept {
- return nullptr != ptr_.get();
- }
-
- bool operator!() const noexcept {
- return nullptr == ptr_.get();
- }
-
- bool operator==( execution_context const& other) const noexcept {
- return ptr_ == other.ptr_;
- }
-
- bool operator!=( execution_context const& other) const noexcept {
- return ptr_ != other.ptr_;
- }
-
- bool operator<( execution_context const& other) const noexcept {
- return ptr_ < other.ptr_;
- }
-
- bool operator>( execution_context const& other) const noexcept {
- return other.ptr_ < ptr_;
- }
-
- bool operator<=( execution_context const& other) const noexcept {
- return ! ( * this > other);
- }
-
- bool operator>=( execution_context const& other) const noexcept {
- return ! ( * this < other);
- }
-
- template< typename charT, class traitsT >
- friend std::basic_ostream< charT, traitsT > &
- operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
- if ( nullptr != other.ptr_) {
- return os << other.ptr_;
- } else {
- return os << "{not-valid}";
- }
- }
-
- void swap( execution_context & other) noexcept {
- ptr_.swap( other.ptr_);
- }
-};
-
-inline
-void swap( execution_context & l, execution_context & r) noexcept {
- l.swap( r);
-}
-
-}}
-
-# ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-# endif
-
-#endif
-
-#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/execution_context_v1.hpp b/boost/context/execution_context_v1.hpp
new file mode 100644
index 0000000000..6881354c88
--- /dev/null
+++ b/boost/context/execution_context_v1.hpp
@@ -0,0 +1,487 @@
+
+// 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_EXECUTION_CONTEXT_H
+#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#include <boost/context/detail/apply.hpp>
+#include <boost/context/detail/disable_overload.hpp>
+#include <boost/context/detail/fcontext.hpp>
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#include <boost/context/segmented_stack.hpp>
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+extern "C" {
+void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+}
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename Fn >
+transfer_t context_ontop( transfer_t);
+
+struct activation_record;
+
+struct data_t {
+ activation_record * from;
+ void * data;
+};
+
+struct activation_record {
+ typedef boost::intrusive_ptr< activation_record > ptr_t;
+
+ thread_local static ptr_t current_rec;
+
+ std::atomic< std::size_t > use_count{ 0 };
+ fcontext_t fctx{ nullptr };
+ stack_context sctx{};
+ bool main_ctx{ true };
+
+ // used for toplevel-context
+ // (e.g. main context, thread-entry context)
+ constexpr activation_record() = default;
+
+ activation_record( fcontext_t fctx_, stack_context sctx_) noexcept :
+ fctx{ fctx_ },
+ sctx( sctx_ ), // sctx{ sctx_ } - clang-3.6: no viable conversion from 'boost::context::stack_context' to 'std::size_t'
+ main_ctx{ false } {
+ }
+
+ virtual ~activation_record() = default;
+
+ bool is_main_context() const noexcept {
+ return main_ctx;
+ }
+
+ void * resume( void * vp) {
+ // store current activation record in local variable
+ auto from = current_rec.get();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by execution_context::current()
+ current_rec = this;
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+ data_t d = { from, vp };
+ // context switch from parent context to `this`-context
+ transfer_t t = jump_fcontext( fctx, & d);
+ data_t * dp = reinterpret_cast< data_t * >( t.data);
+ dp->from->fctx = t.fctx;
+ // parent context resumed
+ return dp->data;
+ }
+
+ template< typename Fn >
+ void * resume_ontop( void * data, Fn && fn) {
+ // store current activation record in local variable
+ activation_record * from = current_rec.get();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by execution_context::current()
+ current_rec = this;
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+ std::tuple< void *, Fn > p = std::forward_as_tuple( data, fn);
+ data_t d = { from, & p };
+ // context switch from parent context to `this`-context
+ // execute Fn( Tpl) on top of `this`
+ transfer_t t = ontop_fcontext( fctx, & d, context_ontop< Fn >);
+ data_t * dp = reinterpret_cast< data_t * >( t.data);
+ dp->from->fctx = t.fctx;
+ // parent context resumed
+ return dp->data;
+ }
+
+ virtual void deallocate() noexcept {
+ }
+
+ friend void intrusive_ptr_add_ref( activation_record * ar) noexcept {
+ ++ar->use_count;
+ }
+
+ friend void intrusive_ptr_release( activation_record * ar) noexcept {
+ BOOST_ASSERT( nullptr != ar);
+ if ( 0 == --ar->use_count) {
+ ar->deallocate();
+ }
+ }
+};
+
+struct activation_record_initializer {
+ activation_record_initializer() noexcept;
+ ~activation_record_initializer();
+};
+
+template< typename Fn >
+transfer_t context_ontop( transfer_t t) {
+ data_t * dp = reinterpret_cast< data_t * >( t.data);
+ dp->from->fctx = t.fctx;
+ auto tpl = reinterpret_cast< std::tuple< void *, Fn > * >( dp->data);
+ BOOST_ASSERT( nullptr != tpl);
+ auto data = std::get< 0 >( * tpl);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 1 >( * tpl) );
+ dp->data = apply( fn, std::tie( data) );
+ return { t.fctx, dp };
+}
+
+template< typename StackAlloc, typename Fn, typename ... Args >
+class capture_record : public activation_record {
+private:
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+ std::tuple< typename std::decay< Args >::type ... > args_;
+ activation_record * caller_;
+
+ static void destroy( capture_record * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx;
+ // deallocate activation record
+ p->~capture_record();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ capture_record( stack_context sctx, StackAlloc const& salloc,
+ fcontext_t fctx,
+ activation_record * caller,
+ Fn && fn, Args && ... args) noexcept :
+ activation_record{ fctx, sctx },
+ salloc_{ salloc },
+ fn_( std::forward< Fn >( fn) ),
+ args_( std::forward< Args >( args) ... ),
+ caller_{ caller } {
+ }
+
+ void deallocate() noexcept override final {
+ destroy( this);
+ }
+
+ void run() {
+ auto data = caller_->resume( nullptr);
+ apply( fn_, std::tuple_cat( args_, std::tie( data) ) );
+ BOOST_ASSERT_MSG( ! main_ctx, "main-context does not execute activation-record::run()");
+ }
+};
+
+}
+
+class BOOST_CONTEXT_DECL execution_context {
+private:
+ // tampoline function
+ // entered if the execution context
+ // is resumed for the first time
+ template< typename AR >
+ static void entry_func( detail::transfer_t t) noexcept {
+ detail::data_t * dp = reinterpret_cast< detail::data_t * >( t.data);
+ AR * ar = static_cast< AR * >( dp->data);
+ BOOST_ASSERT( nullptr != ar);
+ dp->from->fctx = t.fctx;
+ // start execution of toplevel context-function
+ ar->run();
+ }
+
+ typedef boost::intrusive_ptr< detail::activation_record > ptr_t;
+
+ ptr_t ptr_;
+
+ template< typename StackAlloc, typename Fn, typename ... Args >
+ static detail::activation_record * create_context( StackAlloc salloc,
+ Fn && fn, Args && ... args) {
+ typedef detail::capture_record<
+ StackAlloc, Fn, Args ...
+ > capture_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( capture_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( capture_t);
+ constexpr std::size_t func_size = sizeof( capture_t);
+ // 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
+ // create fast-context
+ const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // get current activation record
+ auto curr = execution_context::current().ptr_;
+ // placment new for control structure on fast-context stack
+ return ::new ( sp) capture_t{
+ sctx, salloc, fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
+ }
+
+ template< typename StackAlloc, typename Fn, typename ... Args >
+ static detail::activation_record * create_context( preallocated palloc, StackAlloc salloc,
+ Fn && fn, Args && ... args) {
+ typedef detail::capture_record<
+ StackAlloc, Fn, Args ...
+ > capture_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( capture_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( capture_t);
+ constexpr std::size_t func_size = sizeof( capture_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.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 = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // get current activation record
+ auto curr = execution_context::current().ptr_;
+ // placment new for control structure on fast-context stack
+ return ::new ( sp) capture_t{
+ palloc.sctx, salloc, fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
+ }
+
+ execution_context() noexcept :
+ // default constructed with current activation_record
+ ptr_{ detail::activation_record::current_rec } {
+ }
+
+public:
+ static execution_context current() noexcept;
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ template< typename Fn,
+ typename ... Args,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( segmented_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, segmented_stack salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+#else
+ template< typename Fn,
+ typename ... Args,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( fixedsize_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+#endif
+
+ execution_context( execution_context const& other) noexcept :
+ ptr_{ other.ptr_ } {
+ }
+
+ execution_context( execution_context && other) noexcept :
+ ptr_{ other.ptr_ } {
+ other.ptr_.reset();
+ }
+
+ execution_context & operator=( execution_context const& other) noexcept {
+ // intrusive_ptr<> does not test for self-assignment
+ if ( this == & other) return * this;
+ ptr_ = other.ptr_;
+ return * this;
+ }
+
+ execution_context & operator=( execution_context && other) noexcept {
+ if ( this == & other) return * this;
+ execution_context tmp{ std::move( other) };
+ swap( tmp);
+ return * this;
+ }
+
+ void * operator()( void * vp = nullptr) {
+ return ptr_->resume( vp);
+ }
+
+ template< typename Fn >
+ void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr) {
+ return ptr_->resume_ontop( vp,
+ std::forward< Fn >( fn) );
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != ptr_.get();
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == ptr_.get();
+ }
+
+ bool operator==( execution_context const& other) const noexcept {
+ return ptr_ == other.ptr_;
+ }
+
+ bool operator!=( execution_context const& other) const noexcept {
+ return ptr_ != other.ptr_;
+ }
+
+ bool operator<( execution_context const& other) const noexcept {
+ return ptr_ < other.ptr_;
+ }
+
+ bool operator>( execution_context const& other) const noexcept {
+ return other.ptr_ < ptr_;
+ }
+
+ bool operator<=( execution_context const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( execution_context const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
+ if ( nullptr != other.ptr_) {
+ return os << other.ptr_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( execution_context & other) noexcept {
+ ptr_.swap( other.ptr_);
+ }
+};
+
+inline
+void swap( execution_context & l, execution_context & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/execution_context_v2.hpp b/boost/context/execution_context_v2.hpp
new file mode 100644
index 0000000000..1bc5f868d0
--- /dev/null
+++ b/boost/context/execution_context_v2.hpp
@@ -0,0 +1,395 @@
+
+// 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_EXECUTION_CONTEXT_H
+#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#include <boost/context/detail/apply.hpp>
+#include <boost/context/detail/disable_overload.hpp>
+#include <boost/context/detail/exception.hpp>
+#include <boost/context/detail/exchange.hpp>
+#include <boost/context/detail/fcontext.hpp>
+#include <boost/context/detail/tuple.hpp>
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#include <boost/context/segmented_stack.hpp>
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+inline
+transfer_t context_unwind( transfer_t t) {
+ throw forced_unwind( t.fctx);
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+transfer_t context_exit( transfer_t t) noexcept {
+ Rec * rec = static_cast< Rec * >( t.data);
+ // destroy context stack
+ rec->deallocate();
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+void context_entry( transfer_t t_) noexcept {
+ // transfer control structure to the context-stack
+ Rec * rec = static_cast< Rec * >( t_.data);
+ BOOST_ASSERT( nullptr != rec);
+ transfer_t t = { nullptr, nullptr };
+ try {
+ // jump back to `context_create()`
+ t = jump_fcontext( t_.fctx, nullptr);
+ // start executing
+ t = rec->run( t);
+ } catch ( forced_unwind const& e) {
+ t = { e.fctx, nullptr };
+ }
+ BOOST_ASSERT( nullptr != t.fctx);
+ // destroy context-stack of `this`context on next context
+ ontop_fcontext( t.fctx, rec, context_exit< Rec >);
+ BOOST_ASSERT_MSG( false, "context already terminated");
+}
+
+template< typename Ctx, typename Fn, typename ... Args >
+transfer_t context_ontop( transfer_t t) {
+ auto tpl = static_cast< std::tuple< Fn, std::tuple< Args ... > > * >( t.data);
+ BOOST_ASSERT( nullptr != tpl);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * tpl) );
+ auto args = std::move( std::get< 1 >( * tpl) );
+ Ctx ctx{ t.fctx };
+ // execute function
+ auto result = apply(
+ fn,
+ std::tuple_cat(
+ std::forward_as_tuple( std::move( ctx) ),
+ std::move( args) ) );
+ ctx = std::move( std::get< 0 >( result) );
+ // apply returned data
+ detail::tail( args) = std::move( result);
+ std::get< 1 >( * tpl) = std::move( args);
+ return { exchange( ctx.fctx_, nullptr), & std::get< 1 >( * tpl) };
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+class record {
+private:
+ StackAlloc salloc_;
+ stack_context sctx_;
+ typename std::decay< Fn >::type fn_;
+ std::tuple< typename std::decay< Params >::type ... > params_;
+
+ static void destroy( record * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx_;
+ // deallocate record
+ p->~record();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ record( stack_context sctx, StackAlloc const& salloc,
+ Fn && fn, Params && ... params) noexcept :
+ salloc_( salloc),
+ sctx_( sctx),
+ fn_( std::forward< Fn >( fn) ),
+ params_( std::forward< Params >( params) ... ) {
+ }
+
+ record( record const&) = delete;
+ record & operator=( record const&) = delete;
+
+ void deallocate() noexcept {
+ destroy( this);
+ }
+
+ transfer_t run( transfer_t t) {
+ Ctx from{ t.fctx };
+ typename Ctx::args_tpl_t args = std::move( * static_cast< typename Ctx::args_tpl_t * >( t.data) );
+ auto tpl = std::tuple_cat(
+ params_,
+ std::forward_as_tuple( std::move( from) ),
+ std::move( args) );
+ // invoke context-function
+ Ctx cc = apply( std::move( fn_), std::move( tpl) );
+ return { exchange( cc.fctx_, nullptr), nullptr };
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( record_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // 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
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( record_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.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 = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+}
+
+template< typename ... Args >
+class execution_context {
+private:
+ typedef std::tuple< Args ... > args_tpl_t;
+ typedef std::tuple< execution_context, typename std::decay< Args >::type ... > ret_tpl_t;
+
+ template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+ friend class detail::record;
+
+ template< typename Ctx, typename Fn, typename ... ArgsT >
+ friend detail::transfer_t detail::context_ontop( detail::transfer_t);
+
+ detail::fcontext_t fctx_{ nullptr };
+
+ execution_context( detail::fcontext_t fctx) noexcept :
+ fctx_( fctx) {
+ }
+
+public:
+ constexpr execution_context() noexcept = default;
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // segmented-stack requires to preserve the segments of the `current` context
+ // which is not possible (no global pointer to current context)
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, segmented_stack, Fn &&, Params && ...) = delete;
+
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Params && ...) = delete;
+#else
+ template< typename Fn,
+ typename ... Params,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create< execution_context >(
+ fixedsize_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create< execution_context >(
+ salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create< execution_context >(
+ palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+#endif
+
+ ~execution_context() {
+ if ( nullptr != fctx_) {
+ detail::ontop_fcontext( detail::exchange( fctx_, nullptr), nullptr, detail::context_unwind);
+ }
+ }
+
+ execution_context( execution_context && other) noexcept :
+ fctx_( other.fctx_) {
+ other.fctx_ = nullptr;
+ }
+
+ execution_context & operator=( execution_context && other) noexcept {
+ if ( this != & other) {
+ execution_context tmp = std::move( other);
+ swap( tmp);
+ }
+ return * this;
+ }
+
+ execution_context( execution_context const& other) noexcept = delete;
+ execution_context & operator=( execution_context const& other) noexcept = delete;
+
+ ret_tpl_t operator()( Args ... args) {
+ BOOST_ASSERT( nullptr != fctx_);
+ args_tpl_t data( std::forward< Args >( args) ... );
+ detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), & data);
+ if ( nullptr != t.data) {
+ data = std::move( * static_cast< args_tpl_t * >( t.data) );
+ }
+ return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
+ }
+
+ template< typename Fn >
+ ret_tpl_t operator()( exec_ontop_arg_t, Fn && fn, Args ... args) {
+ BOOST_ASSERT( nullptr != fctx_);
+ args_tpl_t data{ std::forward< Args >( args) ... };
+ auto p = std::make_tuple( fn, std::move( data) );
+ detail::transfer_t t = detail::ontop_fcontext(
+ detail::exchange( fctx_, nullptr),
+ & p,
+ detail::context_ontop< execution_context, Fn, Args ... >);
+ if ( nullptr != t.data) {
+ data = std::move( * static_cast< args_tpl_t * >( t.data) );
+ }
+ return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != fctx_;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == fctx_;
+ }
+
+ bool operator==( execution_context const& other) const noexcept {
+ return fctx_ == other.fctx_;
+ }
+
+ bool operator!=( execution_context const& other) const noexcept {
+ return fctx_ != other.fctx_;
+ }
+
+ bool operator<( execution_context const& other) const noexcept {
+ return fctx_ < other.fctx_;
+ }
+
+ bool operator>( execution_context const& other) const noexcept {
+ return other.fctx_ < fctx_;
+ }
+
+ bool operator<=( execution_context const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( execution_context const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
+ if ( nullptr != other.fctx_) {
+ return os << other.fctx_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( execution_context & other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+};
+
+#include <boost/context/execution_context_v2_void.ipp>
+
+template< typename ... Args >
+void swap( execution_context< Args ... > & l, execution_context< Args ... > & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/execution_context_v2_void.ipp b/boost/context/execution_context_v2_void.ipp
new file mode 100644
index 0000000000..d0659beafb
--- /dev/null
+++ b/boost/context/execution_context_v2_void.ipp
@@ -0,0 +1,290 @@
+
+// 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)
+
+namespace detail {
+
+template< typename Ctx, typename Fn >
+transfer_t context_ontop_void( transfer_t t) {
+ auto tpl = static_cast< std::tuple< Fn > * >( t.data);
+ BOOST_ASSERT( nullptr != tpl);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * tpl) );
+ Ctx ctx{ t.fctx };
+ // execute function
+ ctx = apply(
+ fn,
+ std::forward_as_tuple( std::move( ctx) ) );
+ return { exchange( ctx.fctx_, nullptr), nullptr };
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+class record_void {
+private:
+ StackAlloc salloc_;
+ stack_context sctx_;
+ typename std::decay< Fn >::type fn_;
+ std::tuple< typename std::decay< Params >::type ... > params_;
+
+ static void destroy( record_void * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx_;
+ // deallocate record
+ p->~record_void();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ record_void( stack_context sctx, StackAlloc const& salloc,
+ Fn && fn, Params && ... params) noexcept :
+ salloc_( salloc),
+ sctx_( sctx),
+ fn_( std::forward< Fn >( fn) ),
+ params_( std::forward< Params >( params) ... ) {
+ }
+
+ record_void( record_void const&) = delete;
+ record_void & operator=( record_void const&) = delete;
+
+ void deallocate() noexcept {
+ destroy( this);
+ }
+
+ transfer_t run( transfer_t t) {
+ Ctx from{ t.fctx };
+ // invoke context-function
+ Ctx cc = apply(
+ fn_,
+ std::tuple_cat(
+ params_,
+ std::forward_as_tuple( std::move( from) ) ) );
+ return { exchange( cc.fctx_, nullptr), nullptr };
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( record_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // 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
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( record_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.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 = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+}
+
+template<>
+class execution_context< void > {
+private:
+ template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+ friend class detail::record_void;
+
+ template< typename Ctx, typename Fn >
+ friend detail::transfer_t detail::context_ontop_void( detail::transfer_t);
+
+ detail::fcontext_t fctx_{ nullptr };
+
+ execution_context( detail::fcontext_t fctx) noexcept :
+ fctx_( fctx) {
+ }
+
+public:
+ constexpr execution_context() noexcept = default;
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // segmented-stack requires to preserve the segments of the `current` context
+ // which is not possible (no global pointer to current context)
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, segmented_stack, Fn &&, Params && ...) = delete;
+
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Params && ...) = delete;
+#else
+ template< typename Fn,
+ typename ... Params,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create_void< execution_context >(
+ fixedsize_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create_void< execution_context >(
+ salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create_void< execution_context >(
+ palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+#endif
+
+ ~execution_context() {
+ if ( nullptr != fctx_) {
+ detail::ontop_fcontext( detail::exchange( fctx_, nullptr), nullptr, detail::context_unwind);
+ }
+ }
+
+ execution_context( execution_context && other) noexcept :
+ fctx_( other.fctx_) {
+ other.fctx_ = nullptr;
+ }
+
+ execution_context & operator=( execution_context && other) noexcept {
+ if ( this != & other) {
+ execution_context tmp = std::move( other);
+ swap( tmp);
+ }
+ return * this;
+ }
+
+ execution_context( execution_context const& other) noexcept = delete;
+ execution_context & operator=( execution_context const& other) noexcept = delete;
+
+ execution_context operator()() {
+ BOOST_ASSERT( nullptr != fctx_);
+ detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), nullptr);
+ return execution_context( t.fctx);
+ }
+
+ template< typename Fn >
+ execution_context operator()( exec_ontop_arg_t, Fn && fn) {
+ BOOST_ASSERT( nullptr != fctx_);
+ std::tuple< Fn > p = std::forward_as_tuple( fn);
+ detail::transfer_t t = detail::ontop_fcontext(
+ detail::exchange( fctx_, nullptr),
+ & p,
+ detail::context_ontop_void< execution_context, Fn >);
+ return execution_context( t.fctx);
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != fctx_;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == fctx_;
+ }
+
+ bool operator==( execution_context const& other) const noexcept {
+ return fctx_ == other.fctx_;
+ }
+
+ bool operator!=( execution_context const& other) const noexcept {
+ return fctx_ != other.fctx_;
+ }
+
+ bool operator<( execution_context const& other) const noexcept {
+ return fctx_ < other.fctx_;
+ }
+
+ bool operator>( execution_context const& other) const noexcept {
+ return other.fctx_ < fctx_;
+ }
+
+ bool operator<=( execution_context const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( execution_context const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
+ if ( nullptr != other.fctx_) {
+ return os << other.fctx_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( execution_context & other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+};
diff --git a/boost/context/execution_context_winfib.ipp b/boost/context/execution_context_winfib.ipp
deleted file mode 100644
index 1b106fa245..0000000000
--- a/boost/context/execution_context_winfib.ipp
+++ /dev/null
@@ -1,361 +0,0 @@
-
-// 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_EXECUTION_CONTEXT_H
-#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
-
-#include <boost/context/detail/config.hpp>
-
-#if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT)
-
-#include <windows.h>
-
-#include <algorithm>
-#include <atomic>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-#include <memory>
-#include <tuple>
-#include <utility>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/intrusive_ptr.hpp>
-
-#include <boost/context/detail/invoke.hpp>
-#include <boost/context/fixedsize_stack.hpp>
-#include <boost/context/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-namespace detail {
-
-struct activation_record {
- typedef boost::intrusive_ptr< activation_record > ptr_t;
-
- enum flag_t {
- flag_main_ctx = 1 << 1,
- flag_preserve_fpu = 1 << 2,
- flag_segmented_stack = 1 << 3
- };
-
- thread_local static ptr_t current_rec;
-
- std::atomic< std::size_t > use_count;
- LPVOID fiber;
- stack_context sctx;
- void * data;
- int flags;
-
- // used for toplevel-context
- // (e.g. main context, thread-entry context)
- activation_record() noexcept :
- use_count( 0),
- fiber( nullptr),
- sctx(),
- flags( flag_main_ctx
-# if defined(BOOST_USE_SEGMENTED_STACKS)
- | flag_segmented_stack
-# endif
- ) {
- }
-
- activation_record( stack_context sctx_, bool use_segmented_stack) noexcept :
- use_count( 0),
- fiber( nullptr),
- sctx( sctx_),
- data( nullptr),
- flags( use_segmented_stack ? flag_segmented_stack : 0) {
- }
-
- virtual ~activation_record() noexcept = default;
-
- void * resume( void * vp, bool fpu) noexcept {
- // store current activation record in local variable
- activation_record * from = current_rec.get();
- // store `this` in static, thread local pointer
- // `this` will become the active (running) context
- // returned by execution_context::current()
- current_rec = this;
- // context switch from parent context to `this`-context
-#if ( _WIN32_WINNT > 0x0600)
- if ( ::IsThreadAFiber() ) {
- from->fiber = ::GetCurrentFiber();
- } else {
- from->fiber = ::ConvertThreadToFiber( nullptr);
- }
-#else
- from->fiber = ::ConvertThreadToFiber( nullptr);
- if ( nullptr == from->fiber) {
- DWORD err = ::GetLastError();
- BOOST_ASSERT( ERROR_ALREADY_FIBER == err);
- from->fiber = ::GetCurrentFiber();
- BOOST_ASSERT( nullptr != from->fiber);
- BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != from->fiber);
- }
-#endif
- // store passed argument (void pointer)
- data = vp;
- // context switch
- ::SwitchToFiber( fiber);
- // access the activation-record of the current fiber
- activation_record * ar = static_cast< activation_record * >( GetFiberData() );
- return nullptr != ar ? ar->data : nullptr;
- }
-
- virtual void deallocate() {
- delete this;
- }
-
- friend void intrusive_ptr_add_ref( activation_record * ar) {
- ++ar->use_count;
- }
-
- friend void intrusive_ptr_release( activation_record * ar) {
- BOOST_ASSERT( nullptr != ar);
-
- if ( 0 == --ar->use_count) {
- ar->deallocate();
- }
- }
-};
-
-struct activation_record_initializer {
- activation_record_initializer();
- ~activation_record_initializer();
-};
-
-template< typename Fn, typename Tpl, typename StackAlloc >
-class capture_record : public activation_record {
-private:
- StackAlloc salloc_;
- Fn fn_;
- Tpl tpl_;
- activation_record * caller_;
-
- static void destroy( capture_record * p) {
- StackAlloc salloc( p->salloc_);
- stack_context sctx( p->sctx);
- // deallocate activation record
- p->~capture_record();
- // destroy stack with stack allocator
- salloc.deallocate( sctx);
- }
-
-public:
- explicit capture_record(
- stack_context sctx, StackAlloc const& salloc,
- Fn && fn, Tpl && tpl,
- activation_record * caller,
- bool use_segmented_stack) noexcept :
- activation_record( sctx, use_segmented_stack),
- salloc_( salloc),
- fn_( std::forward< Fn >( fn) ),
- tpl_( std::forward< Tpl >( tpl) ),
- caller_( caller) {
- }
-
- void deallocate() override final {
- destroy( this);
- }
-
- void run() noexcept {
- try {
- void * vp = caller_->resume( caller_, true);
- do_invoke( fn_, std::tuple_cat( tpl_, std::tie( vp) ) );
- } catch (...) {
- std::terminate();
- }
- BOOST_ASSERT( 0 == (flags & flag_main_ctx) );
- }
-};
-
-}
-
-struct preallocated {
- void * sp;
- std::size_t size;
- stack_context sctx;
-
- preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
- sp( sp_), size( size_), sctx( sctx_) {
- }
-};
-
-class BOOST_CONTEXT_DECL execution_context {
-private:
- // tampoline function
- // entered if the execution context
- // is resumed for the first time
- template< typename AR >
- static VOID WINAPI entry_func( LPVOID p) {
- BOOST_ASSERT( 0 != p);
-
- AR * ar( reinterpret_cast< AR * >( p) );
- // start execution of toplevel context-function
- ar->run();
- //ctx->fn_(ctx->param_);
- ::DeleteFiber( ar->fiber);
- }
-
- typedef boost::intrusive_ptr< detail::activation_record > ptr_t;
-
- ptr_t ptr_;
-
- template< typename StackAlloc, typename Fn ,typename Tpl >
- static detail::activation_record * create_context(
- StackAlloc salloc,
- Fn && fn, Tpl && tpl,
- bool use_segmented_stack) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- // hackish
- std::size_t fsize = salloc.size_;
- // protected_fixedsize_stack needs at least 2*page-size
- salloc.size_ = ( std::max)( sizeof( capture_t), 2 * stack_traits::page_size() );
-
- stack_context sctx( salloc.allocate() );
- // reserve space for control structure
- void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placement new for control structure on fast-context stack
- capture_t * cr = new ( sp) capture_t(
- sctx, salloc, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get(), use_segmented_stack);
- // create fiber
- // use default stacksize
- cr->fiber = ::CreateFiber( fsize, execution_context::entry_func< capture_t >, cr);
- BOOST_ASSERT( nullptr != cr->fiber);
- return cr;
- }
-
- template< typename StackAlloc, typename Fn , typename Tpl >
- static detail::activation_record * create_context(
- preallocated palloc, StackAlloc salloc,
- Fn && fn, Tpl && tpl,
- bool use_segmented_stack) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- // hackish
- std::size_t fsize = salloc.size_;
- // protected_fixedsize_stack needs at least 2*page-size
- salloc.size_ = ( std::max)( sizeof( capture_t), 2 * stack_traits::page_size() );
-
- // reserve space for control structure
- void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placement new for control structure on fast-context stack
- capture_t * cr = new ( sp) capture_t(
- palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get(), use_segmented_stack);
- // create fiber
- // use default stacksize
- cr->fiber = ::CreateFiber( fsize, execution_context::entry_func< capture_t >, cr);
- BOOST_ASSERT( nullptr != cr->fiber);
- return cr;
- }
-
- execution_context() :
- // default constructed with current activation_record
- ptr_( detail::activation_record::current_rec) {
- }
-
-public:
- static execution_context current() noexcept;
-
- template< typename Fn, typename ... Args >
- explicit execution_context( Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( fixedsize_stack(),
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...),
- false) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...),
- false) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( palloc, salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...),
- false) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- execution_context( execution_context const& other) noexcept :
- ptr_( other.ptr_) {
- }
-
- execution_context( execution_context && other) noexcept :
- ptr_( other.ptr_) {
- other.ptr_.reset();
- }
-
- execution_context & operator=( execution_context const& other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- }
- return * this;
- }
-
- execution_context & operator=( execution_context && other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- other.ptr_.reset();
- }
- return * this;
- }
-
- explicit operator bool() const noexcept {
- return nullptr != ptr_.get();
- }
-
- bool operator!() const noexcept {
- return nullptr == ptr_.get();
- }
-
- void * operator()( void * vp = nullptr, bool preserve_fpu = false) noexcept {
- return ptr_->resume( vp, preserve_fpu);
- }
-};
-
-}}
-
-# ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-# endif
-
-#endif
-
-#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/fixedsize_stack.hpp b/boost/context/fixedsize_stack.hpp
index b27d785d08..681de40576 100644
--- a/boost/context/fixedsize_stack.hpp
+++ b/boost/context/fixedsize_stack.hpp
@@ -32,16 +32,12 @@ namespace context {
template< typename traitsT >
class basic_fixedsize_stack {
private:
-#if defined(BOOST_USE_WINFIBERS)
- friend class execution_context;
-#endif
-
std::size_t size_;
public:
typedef traitsT traits_type;
- basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -60,17 +56,14 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
-#if ! defined(BOOST_USE_WINFIBERS)
BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
-#endif
#if defined(BOOST_USE_VALGRIND)
VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
#endif
-
void * vp = static_cast< char * >( sctx.sp) - sctx.size;
std::free( vp);
}
diff --git a/boost/context/flags.hpp b/boost/context/flags.hpp
new file mode 100644
index 0000000000..c7ff1179da
--- /dev/null
+++ b/boost/context/flags.hpp
@@ -0,0 +1,28 @@
+
+// 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_FLAGS_H
+#define BOOST_CONTEXT_FLAGS_H
+
+# include <boost/config.hpp>
+
+# ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+# endif
+
+namespace boost {
+namespace context {
+
+struct exec_ontop_arg_t {};
+const exec_ontop_arg_t exec_ontop_arg{};
+
+}}
+
+# ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+# endif
+
+#endif // BOOST_CONTEXT_FLAGS_H
diff --git a/boost/context/pooled_fixedsize_stack.hpp b/boost/context/pooled_fixedsize_stack.hpp
new file mode 100644
index 0000000000..3c0953cd07
--- /dev/null
+++ b/boost/context/pooled_fixedsize_stack.hpp
@@ -0,0 +1,115 @@
+
+// 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_POOLED_pooled_fixedsize_H
+#define BOOST_CONTEXT_POOLED_pooled_fixedsize_H
+
+#include <atomic>
+#include <cstddef>
+#include <cstdlib>
+#include <new>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/pool/pool.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#if defined(BOOST_USE_VALGRIND)
+#include <valgrind/valgrind.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_pooled_fixedsize_stack {
+private:
+ class storage {
+ private:
+ std::atomic< std::size_t > use_count_;
+ std::size_t stack_size_;
+ boost::pool< boost::default_user_allocator_malloc_free > storage_;
+
+ public:
+ storage( std::size_t stack_size, std::size_t next_size, std::size_t max_size) :
+ use_count_( 0),
+ stack_size_( stack_size),
+ storage_( stack_size, next_size, max_size) {
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size_) );
+ }
+
+ stack_context allocate() {
+ void * vp = storage_.malloc();
+ if ( ! vp) {
+ throw std::bad_alloc();
+ }
+ stack_context sctx;
+ sctx.size = stack_size_;
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+#if defined(BOOST_USE_VALGRIND)
+ sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
+#endif
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
+ BOOST_ASSERT( sctx.sp);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
+
+#if defined(BOOST_USE_VALGRIND)
+ VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
+#endif
+ void * vp = static_cast< char * >( sctx.sp) - sctx.size;
+ storage_.free( vp);
+ }
+
+ friend void intrusive_ptr_add_ref( storage * s) noexcept {
+ ++s->use_count_;
+ }
+
+ friend void intrusive_ptr_release( storage * s) noexcept {
+ if ( 0 == --s->use_count_) {
+ delete s;
+ }
+ }
+ };
+
+ intrusive_ptr< storage > storage_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_pooled_fixedsize_stack( std::size_t stack_size = traits_type::default_size(),
+ std::size_t next_size = 32,
+ std::size_t max_size = 0) BOOST_NOEXCEPT_OR_NOTHROW :
+ storage_( new storage( stack_size, next_size, max_size) ) {
+ }
+
+ stack_context allocate() {
+ return storage_->allocate();
+ }
+
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
+ storage_->deallocate( sctx);
+ }
+};
+
+typedef basic_pooled_fixedsize_stack< stack_traits > pooled_fixedsize_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_POOLED_pooled_fixedsize_H
diff --git a/boost/context/posix/protected_fixedsize_stack.hpp b/boost/context/posix/protected_fixedsize_stack.hpp
index 25ce9a6828..7d1b789d01 100644
--- a/boost/context/posix/protected_fixedsize_stack.hpp
+++ b/boost/context/posix/protected_fixedsize_stack.hpp
@@ -44,7 +44,7 @@ private:
public:
typedef traitsT traits_type;
- basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -86,7 +86,7 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
diff --git a/boost/context/posix/segmented_stack.hpp b/boost/context/posix/segmented_stack.hpp
index 93f4210fd4..25842b6d32 100644
--- a/boost/context/posix/segmented_stack.hpp
+++ b/boost/context/posix/segmented_stack.hpp
@@ -45,7 +45,7 @@ private:
public:
typedef traitsT traits_type;
- basic_segmented_stack( std::size_t size = traits_type::default_size() ) :
+ basic_segmented_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -65,7 +65,7 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
__splitstack_releasecontext( sctx.segments_ctx);
}
};
diff --git a/boost/context/preallocated.hpp b/boost/context/preallocated.hpp
new file mode 100644
index 0000000000..862a6a5060
--- /dev/null
+++ b/boost/context/preallocated.hpp
@@ -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_CONTEXT_PREALLOCATED_H
+#define BOOST_CONTEXT_PREALLOCATED_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+struct preallocated {
+ void * sp;
+ std::size_t size;
+ stack_context sctx;
+
+ preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
+ sp( sp_), size( size_), sctx( sctx_) {
+ }
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_PREALLOCATED_H
diff --git a/boost/context/stack_context.hpp b/boost/context/stack_context.hpp
index 24a54e5748..6e516a3adf 100644
--- a/boost/context/stack_context.hpp
+++ b/boost/context/stack_context.hpp
@@ -20,49 +20,46 @@
namespace boost {
namespace context {
-#if defined(BOOST_USE_SEGMENTED_STACKS)
+#if ! defined(BOOST_CONTEXT_NO_CXX11)
struct stack_context {
+# if defined(BOOST_USE_SEGMENTED_STACKS)
typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
+# endif
- std::size_t size;
- void * sp;
- segments_context segments_ctx;
-#if defined(BOOST_USE_VALGRIND)
- unsigned valgrind_stack_id;
-#endif
-
-#if defined(BOOST_NO_CXX11_CONSTEXPR)
- stack_context() :
-#else
- constexpr stack_context() :
-#endif
- size( 0),
- sp( 0),
- segments_ctx()
-#if defined(BOOST_USE_VALGRIND)
- , valgrind_stack_id( 0)
-#endif
- {}
+ std::size_t size{ 0 };
+ void * sp{ nullptr };
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ segments_context segments_ctx{};
+# endif
+# if defined(BOOST_USE_VALGRIND)
+ unsigned valgrind_stack_id{ 0 };
+# endif
};
#else
struct stack_context {
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
+# endif
+
std::size_t size;
void * sp;
-#if defined(BOOST_USE_VALGRIND)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ segments_context segments_ctx;
+# endif
+# if defined(BOOST_USE_VALGRIND)
unsigned valgrind_stack_id;
-#endif
+# endif
-#if defined(BOOST_NO_CXX11_CONSTEXPR)
stack_context() :
-#else
- constexpr stack_context() :
-#endif
size( 0),
sp( 0)
-#if defined(BOOST_USE_VALGRIND)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ , segments_ctx()
+# endif
+# if defined(BOOST_USE_VALGRIND)
, valgrind_stack_id( 0)
-#endif
- {}
+# endif
+ {}
};
#endif
diff --git a/boost/context/stack_traits.hpp b/boost/context/stack_traits.hpp
index 9b8a70636d..d5320f509d 100644
--- a/boost/context/stack_traits.hpp
+++ b/boost/context/stack_traits.hpp
@@ -22,15 +22,15 @@ namespace context {
struct BOOST_CONTEXT_DECL stack_traits
{
- static bool is_unbounded() BOOST_NOEXCEPT;
+ static bool is_unbounded() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t page_size() BOOST_NOEXCEPT;
+ static std::size_t page_size() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t default_size() BOOST_NOEXCEPT;
+ static std::size_t default_size() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t minimum_size() BOOST_NOEXCEPT;
+ static std::size_t minimum_size() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t maximum_size() BOOST_NOEXCEPT;
+ static std::size_t maximum_size() BOOST_NOEXCEPT_OR_NOTHROW;
};
}}
diff --git a/boost/context/windows/protected_fixedsize_stack.hpp b/boost/context/windows/protected_fixedsize_stack.hpp
index 548bcda31f..cd59764c93 100644
--- a/boost/context/windows/protected_fixedsize_stack.hpp
+++ b/boost/context/windows/protected_fixedsize_stack.hpp
@@ -31,16 +31,12 @@ namespace context {
template< typename traitsT >
class basic_protected_fixedsize_stack {
private:
-#if defined(BOOST_USE_WINFIBERS)
- friend class execution_context;
-#endif
-
std::size_t size_;
public:
typedef traitsT traits_type;
- basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -76,12 +72,10 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
-#if ! defined(BOOST_USE_WINFIBERS)
BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
-#endif
void * vp = static_cast< char * >( sctx.sp) - sctx.size;
::VirtualFree( vp, 0, MEM_RELEASE);