summaryrefslogtreecommitdiff
path: root/boost/context
diff options
context:
space:
mode:
Diffstat (limited to 'boost/context')
-rw-r--r--boost/context/continuation.hpp551
-rw-r--r--boost/context/continuation_fcontext.hpp382
-rw-r--r--boost/context/continuation_ucontext.hpp525
-rw-r--r--boost/context/continuation_winfib.hpp453
-rw-r--r--boost/context/detail/config.hpp11
-rw-r--r--boost/context/detail/exception.hpp4
-rw-r--r--boost/context/detail/fcontext_arm.hpp68
-rw-r--r--boost/context/detail/fcontext_arm_mac.hpp70
-rw-r--r--boost/context/detail/fcontext_arm_win.hpp71
-rw-r--r--boost/context/detail/fcontext_i386.hpp59
-rw-r--r--boost/context/detail/fcontext_i386_win.hpp88
-rw-r--r--boost/context/detail/fcontext_mips.hpp70
-rw-r--r--boost/context/detail/fcontext_ppc.hpp72
-rw-r--r--boost/context/detail/fcontext_sparc.hpp90
-rw-r--r--boost/context/detail/fcontext_x86_64.hpp68
-rw-r--r--boost/context/detail/fcontext_x86_64_win.hpp77
-rw-r--r--boost/context/detail/prefetch.hpp78
-rw-r--r--boost/context/fixedsize_stack.hpp75
-rw-r--r--boost/context/pooled_fixedsize_stack.hpp1
-rw-r--r--boost/context/posix/fixedsize_stack.hpp80
-rw-r--r--boost/context/posix/protected_fixedsize_stack.hpp14
-rw-r--r--boost/context/windows/fixedsize_stack.hpp80
-rw-r--r--boost/context/windows/protected_fixedsize_stack.hpp14
23 files changed, 1541 insertions, 1460 deletions
diff --git a/boost/context/continuation.hpp b/boost/context/continuation.hpp
index 6a50713158..8db62a9506 100644
--- a/boost/context/continuation.hpp
+++ b/boost/context/continuation.hpp
@@ -4,551 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXT_CONTINUATION_H
-#define BOOST_CONTEXT_CONTINUATION_H
-
-#include <boost/context/detail/config.hpp>
-
-#include <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-#include <exception>
-#include <functional>
-#include <memory>
-#include <ostream>
-#include <tuple>
-#include <utility>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/intrusive_ptr.hpp>
-
-#if defined(BOOST_NO_CXX17_STD_APPLY)
-#include <boost/context/detail/apply.hpp>
-#endif
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
-#include <boost/context/detail/exchange.hpp>
-#endif
-#if defined(BOOST_NO_CXX17_STD_INVOKE)
-#include <boost/context/detail/invoke.hpp>
-#endif
-#include <boost/context/detail/disable_overload.hpp>
-#include <boost/context/detail/exception.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
-
-#if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable: 4702)
-#endif
-
-namespace boost {
-namespace context {
-namespace detail {
-
-template< int N >
-struct helper {
- template< typename T >
- static T convert( T && t) noexcept {
- return std::forward< T >( t);
- }
-};
-
-template<>
-struct helper< 1 > {
- template< typename T >
- static std::tuple< T > convert( T && t) noexcept {
- return std::make_tuple( std::forward< T >( t) );
- }
-};
-
-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 != t_.fctx);
- 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 StackAlloc,
- typename Fn
->
-class record {
-private:
- StackAlloc salloc_;
- stack_context sctx_;
- typename std::decay< Fn >::type fn_;
-
- 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) noexcept :
- salloc_( salloc),
- sctx_( sctx),
- fn_( std::forward< Fn >( fn) ) {
- }
-
- record( record const&) = delete;
- record & operator=( record const&) = delete;
-
- void deallocate() noexcept {
- destroy( this);
- }
-
- transfer_t run( transfer_t t) {
- Ctx from{ t };
- // invoke context-function
-#if defined(BOOST_NO_CXX17_STD_INVOKE)
- Ctx cc = invoke( fn_, std::move( from) );
-#else
- Ctx cc = std::invoke( fn_, std::move( from) );
-#endif
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- return { exchange( cc.t_.fctx, nullptr), nullptr };
+#if defined(BOOST_USE_UCONTEXT)
+#include <boost/context/continuation_ucontext.hpp>
+#elif defined(BOOST_USE_WINFIB)
+#include <boost/context/continuation_winfib.hpp>
#else
- return { std::exchange( cc.t_.fctx, nullptr), nullptr };
+#include <boost/context/continuation_fcontext.hpp>
#endif
- }
-};
-
-template< typename Record, typename StackAlloc, typename Fn >
-fcontext_t context_create( StackAlloc salloc, Fn && fn) {
- 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);
- void * sp = static_cast< char * >( sctx.sp) - sizeof( Record);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( Record);
- constexpr std::size_t func_size = sizeof( Record);
- // 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 >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) Record{
- sctx, salloc, std::forward< Fn >( fn) };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
-template< typename Record, typename StackAlloc, typename Fn >
-fcontext_t context_create( preallocated palloc, StackAlloc salloc, Fn && fn) {
- // 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);
- void * sp = static_cast< char * >( palloc.sp) - sizeof( Record);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( Record);
- constexpr std::size_t func_size = sizeof( Record);
- // 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 >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) Record{
- palloc.sctx, salloc, std::forward< Fn >( fn) };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
-template< typename ... Arg >
-struct result_type {
- typedef std::tuple< Arg ... > type;
-
- static
- type get( detail::transfer_t & t) {
- auto p = static_cast< std::tuple< Arg ... > * >( t.data);
- return std::move( * p);
- }
-};
-
-template< typename Arg >
-struct result_type< Arg > {
- typedef Arg type;
-
- static
- type get( detail::transfer_t & t) {
- auto p = static_cast< std::tuple< Arg > * >( t.data);
- return std::forward< Arg >( std::get< 0 >( * p) );
- }
-};
-
-}
-
-template< typename Ctx, typename Fn, typename ... Arg >
-detail::transfer_t context_ontop( detail::transfer_t t) {
- auto p = static_cast< std::tuple< Fn, std::tuple< Arg ... > > * >( t.data);
- BOOST_ASSERT( nullptr != p);
- typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
- t.data = & std::get< 1 >( * p);
- Ctx c{ t };
- // execute function, pass continuation via reference
- std::get< 1 >( * p) = detail::helper< sizeof ... (Arg) >::convert( fn( std::move( c) ) );
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- return { detail::exchange( c.t_.fctx, nullptr), & std::get< 1 >( * p) };
-#else
- return { std::exchange( c.t_.fctx, nullptr), & std::get< 1 >( * p) };
-#endif
-}
-
-template< typename Ctx, typename Fn >
-detail::transfer_t context_ontop_void( detail::transfer_t t) {
- auto p = static_cast< std::tuple< Fn > * >( t.data);
- BOOST_ASSERT( nullptr != p);
- typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
- Ctx c{ t };
- // execute function, pass continuation via reference
- fn( std::move( c) );
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- return { detail::exchange( c.t_.fctx, nullptr), nullptr };
-#else
- return { std::exchange( c.t_.fctx, nullptr), nullptr };
-#endif
-}
-
-class continuation {
-private:
- template< typename Ctx, typename StackAlloc, typename Fn >
- friend class detail::record;
-
- template< typename Ctx, typename Fn, typename ... Arg >
- friend detail::transfer_t
- context_ontop( detail::transfer_t);
-
- template< typename Ctx, typename Fn >
- friend detail::transfer_t
- context_ontop_void( detail::transfer_t);
-
- template< typename StackAlloc, typename Fn, typename ... Arg >
- friend continuation
- callcc( std::allocator_arg_t, StackAlloc, Fn &&, Arg ...);
-
- template< typename StackAlloc, typename Fn, typename ... Arg >
- friend continuation
- callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&, Arg ...);
-
- template< typename StackAlloc, typename Fn >
- friend continuation
- callcc( std::allocator_arg_t, StackAlloc, Fn &&);
-
- template< typename StackAlloc, typename Fn >
- friend continuation
- callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
-
- detail::transfer_t t_{ nullptr, nullptr };
-
- continuation( detail::fcontext_t fctx) noexcept :
- t_{ fctx, nullptr } {
- }
-
- continuation( detail::transfer_t t) noexcept :
- t_{ t.fctx, t.data } {
- }
-
-public:
- continuation() noexcept = default;
-
- ~continuation() {
- if ( nullptr != t_.fctx) {
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::ontop_fcontext( detail::exchange( t_.fctx, nullptr), nullptr, detail::context_unwind);
-#else
- detail::ontop_fcontext( std::exchange( t_.fctx, nullptr), nullptr, detail::context_unwind);
-#endif
- }
- }
-
- continuation( continuation && other) noexcept :
- t_{ other.t_.fctx, other.t_.data } {
- other.t_ = { nullptr, nullptr };
- }
-
- continuation & operator=( continuation && other) noexcept {
- if ( this != & other) {
- continuation tmp = std::move( other);
- swap( tmp);
- }
- return * this;
- }
-
- continuation( continuation const& other) noexcept = delete;
- continuation & operator=( continuation const& other) noexcept = delete;
-
- template< typename ... Arg >
- continuation resume( Arg ... arg) {
- BOOST_ASSERT( nullptr != t_.fctx);
- auto tpl = std::make_tuple( std::forward< Arg >( arg) ... );
- return detail::jump_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- & tpl);
- }
-
- template< typename Fn, typename ... Arg >
- continuation resume_with( Fn && fn, Arg ... arg) {
- BOOST_ASSERT( nullptr != t_.fctx);
- auto tpl = std::make_tuple( std::forward< Fn >( fn), std::forward< Arg >( arg) ... );
- return detail::ontop_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- & tpl,
- context_ontop< continuation, Fn, Arg ... >);
- }
-
- continuation resume() {
- BOOST_ASSERT( nullptr != t_.fctx);
- return detail::jump_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- nullptr);
- }
-
- template< typename Fn >
- continuation resume_with( Fn && fn) {
- BOOST_ASSERT( nullptr != t_.fctx);
- auto p = std::make_tuple( std::forward< Fn >( fn) );
- return detail::ontop_fcontext(
-#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
- detail::exchange( t_.fctx, nullptr),
-#else
- std::exchange( t_.fctx, nullptr),
-#endif
- & p,
- context_ontop_void< continuation, Fn >);
- }
-
- bool data_available() noexcept {
- return * this && nullptr != t_.data;
- }
-
- template< typename ... Arg >
- typename detail::result_type< Arg ... >::type get_data() {
- BOOST_ASSERT( nullptr != t_.data);
- return detail::result_type< Arg ... >::get( t_);
- }
-
- explicit operator bool() const noexcept {
- return nullptr != t_.fctx;
- }
-
- bool operator!() const noexcept {
- return nullptr == t_.fctx;
- }
-
- bool operator==( continuation const& other) const noexcept {
- return t_.fctx == other.t_.fctx;
- }
-
- bool operator!=( continuation const& other) const noexcept {
- return t_.fctx != other.t_.fctx;
- }
-
- bool operator<( continuation const& other) const noexcept {
- return t_.fctx < other.t_.fctx;
- }
-
- bool operator>( continuation const& other) const noexcept {
- return other.t_.fctx < t_.fctx;
- }
-
- bool operator<=( continuation const& other) const noexcept {
- return ! ( * this > other);
- }
-
- bool operator>=( continuation 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, continuation const& other) {
- if ( nullptr != other.t_.fctx) {
- return os << other.t_.fctx;
- } else {
- return os << "{not-a-context}";
- }
- }
-
- void swap( continuation & other) noexcept {
- std::swap( t_, other.t_);
- }
-};
-
-// Arg
-template<
- typename Fn,
- typename ... Arg,
- typename = detail::disable_overload< continuation, Fn >
->
-continuation
-callcc( Fn && fn, Arg ... arg) {
- return callcc(
- std::allocator_arg, fixedsize_stack(),
- std::forward< Fn >( fn), std::forward< Arg >( arg) ...);
-}
-
-template<
- typename StackAlloc,
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Arg ... arg) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- salloc, std::forward< Fn >( fn) ) }.resume(
- std::forward< Arg >( arg) ... );
-}
-
-template<
- typename StackAlloc,
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Arg ... arg) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- palloc, salloc, std::forward< Fn >( fn) ) }.resume(
- std::forward< Arg >( arg) ... );
-}
-
-// void
-template<
- typename Fn,
- typename = detail::disable_overload< continuation, Fn >
->
-continuation
-callcc( Fn && fn) {
- return callcc(
- std::allocator_arg, fixedsize_stack(),
- std::forward< Fn >( fn) );
-}
-
-template< typename StackAlloc, typename Fn >
-continuation
-callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- salloc, std::forward< Fn >( fn) ) }.resume();
-}
-
-template< typename StackAlloc, typename Fn >
-continuation
-callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
- using Record = detail::record< continuation, StackAlloc, Fn >;
- return continuation{
- detail::context_create< Record >(
- palloc, salloc, std::forward< Fn >( fn) ) }.resume();
-}
-
-#if defined(BOOST_USE_SEGMENTED_STACKS)
-template<
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, segmented_stack, Fn &&, Arg ...);
-
-template<
- typename StackAlloc,
- typename Fn,
- typename ... Arg
->
-continuation
-callcc( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Arg ...);
-#endif
-
-// swap
-inline
-void swap( continuation & l, continuation & r) noexcept {
- l.swap( r);
-}
-
-}}
-
-#if defined(BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/continuation_fcontext.hpp b/boost/context/continuation_fcontext.hpp
new file mode 100644
index 0000000000..5c309c3fed
--- /dev/null
+++ b/boost/context/continuation_fcontext.hpp
@@ -0,0 +1,382 @@
+
+// Copyright Oliver Kowalke 2017.
+// 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_CONTINUATION_H
+#define BOOST_CONTEXT_CONTINUATION_H
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <exception>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+#include <boost/context/detail/exchange.hpp>
+#endif
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+#include <boost/context/detail/invoke.hpp>
+#endif
+#include <boost/context/detail/disable_overload.hpp>
+#include <boost/context/detail/exception.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
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4702)
+#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 != t.fctx);
+ BOOST_ASSERT( nullptr != rec);
+ try {
+ // jump back to `create_context()`
+ t = jump_fcontext( t.fctx, nullptr);
+ // start executing
+ t.fctx = rec->run( t.fctx);
+ } 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 >
+transfer_t context_ontop( transfer_t t) {
+ auto p = static_cast< std::tuple< Fn > * >( t.data);
+ BOOST_ASSERT( nullptr != p);
+ typename std::decay< Fn >::type fn = std::get< 0 >( * p);
+ t.data = nullptr;
+ Ctx c{ t.fctx };
+ // execute function, pass continuation via reference
+ fn( std::move( c) );
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return { exchange( c.fctx_, nullptr), nullptr };
+#else
+ return { std::exchange( c.fctx_, nullptr), nullptr };
+#endif
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+class record {
+private:
+ stack_context sctx_;
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+
+ 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) noexcept :
+ sctx_( sctx),
+ salloc_( salloc),
+ fn_( std::forward< Fn >( fn) ) {
+ }
+
+ record( record const&) = delete;
+ record & operator=( record const&) = delete;
+
+ void deallocate() noexcept {
+ destroy( this);
+ }
+
+ fcontext_t run( fcontext_t fctx) {
+ Ctx c{ fctx };
+ // invoke context-function
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+ c = invoke( fn_, std::move( c) );
+#else
+ c = std::invoke( fn_, std::move( c) );
+#endif
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( c.fctx_, nullptr);
+#else
+ return std::exchange( c.fctx_, nullptr);
+#endif
+ }
+};
+
+template< typename Record, typename StackAlloc, typename Fn >
+fcontext_t create_context1( StackAlloc salloc, Fn && fn) {
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( Record) ) )
+ & ~static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ Record * record = new ( storage) Record{
+ sctx, salloc, std::forward< Fn >( fn) };
+ // 64byte gab between control structure and stack top
+ // should be 16byte aligned
+ void * stack_top = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) );
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
+ // create fast-context
+ const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom);
+ const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >);
+ BOOST_ASSERT( nullptr != fctx);
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, record).fctx;
+}
+
+template< typename Record, typename StackAlloc, typename Fn >
+fcontext_t create_context2( preallocated palloc, StackAlloc salloc, Fn && fn) {
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( Record) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context-stack
+ Record * record = new ( storage) Record{
+ palloc.sctx, salloc, std::forward< Fn >( fn) };
+ // 64byte gab between control structure and stack top
+ void * stack_top = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) );
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) );
+ // create fast-context
+ const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom);
+ const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >);
+ BOOST_ASSERT( nullptr != fctx);
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, record).fctx;
+}
+
+}
+
+class continuation {
+private:
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend class detail::record;
+
+ template< typename Ctx, typename Fn >
+ friend detail::transfer_t
+ detail::context_ontop( detail::transfer_t);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
+
+ detail::fcontext_t fctx_{ nullptr };
+
+ continuation( detail::fcontext_t fctx) noexcept :
+ fctx_{ fctx } {
+ }
+
+public:
+ continuation() noexcept = default;
+
+ ~continuation() {
+ if ( BOOST_UNLIKELY( nullptr != fctx_) ) {
+ detail::ontop_fcontext(
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::exchange( fctx_, nullptr),
+#else
+ std::exchange( fctx_, nullptr),
+#endif
+ nullptr,
+ detail::context_unwind);
+ }
+ }
+
+ continuation( continuation && other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+
+ continuation & operator=( continuation && other) noexcept {
+ if ( BOOST_LIKELY( this != & other) ) {
+ continuation tmp = std::move( other);
+ swap( tmp);
+ }
+ return * this;
+ }
+
+ continuation( continuation const& other) noexcept = delete;
+ continuation & operator=( continuation const& other) noexcept = delete;
+
+ continuation resume() {
+ BOOST_ASSERT( nullptr != fctx_);
+ return detail::jump_fcontext(
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::exchange( fctx_, nullptr),
+#else
+ std::exchange( fctx_, nullptr),
+#endif
+ nullptr).fctx;
+ }
+
+ template< typename Fn >
+ continuation resume_with( Fn && fn) {
+ BOOST_ASSERT( nullptr != fctx_);
+ auto p = std::make_tuple( std::forward< Fn >( fn) );
+ return detail::ontop_fcontext(
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::exchange( fctx_, nullptr),
+#else
+ std::exchange( fctx_, nullptr),
+#endif
+ & p,
+ detail::context_ontop< continuation, Fn >).fctx;
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != fctx_;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == fctx_;
+ }
+
+ bool operator==( continuation const& other) const noexcept {
+ return fctx_ == other.fctx_;
+ }
+
+ bool operator!=( continuation const& other) const noexcept {
+ return fctx_ != other.fctx_;
+ }
+
+ bool operator<( continuation const& other) const noexcept {
+ return fctx_ < other.fctx_;
+ }
+
+ bool operator>( continuation const& other) const noexcept {
+ return other.fctx_ < fctx_;
+ }
+
+ bool operator<=( continuation const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( continuation 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, continuation const& other) {
+ if ( nullptr != other.fctx_) {
+ return os << other.fctx_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( continuation & other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+};
+
+template<
+ typename Fn,
+ typename = detail::disable_overload< continuation, Fn >
+>
+continuation
+callcc( Fn && fn) {
+ return callcc(
+ std::allocator_arg, fixedsize_stack(),
+ std::forward< Fn >( fn) );
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
+ using Record = detail::record< continuation, StackAlloc, Fn >;
+ return continuation{
+ detail::create_context1< Record >(
+ salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
+ using Record = detail::record< continuation, StackAlloc, Fn >;
+ return continuation{
+ detail::create_context2< Record >(
+ palloc, salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+template< typename Fn >
+continuation
+callcc( std::allocator_arg_t, segmented_stack, Fn &&);
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated, segmented_stack, Fn &&);
+#endif
+
+// swap
+inline
+void swap( continuation & l, continuation & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/continuation_ucontext.hpp b/boost/context/continuation_ucontext.hpp
new file mode 100644
index 0000000000..6f964dc6f6
--- /dev/null
+++ b/boost/context/continuation_ucontext.hpp
@@ -0,0 +1,525 @@
+
+// Copyright Oliver Kowalke 2017.
+// 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_CONTINUATION_H
+#define BOOST_CONTEXT_CONTINUATION_H
+
+#include <boost/predef.h>
+#if BOOST_OS_MACOS
+#define _XOPEN_SOURCE 600
+#endif
+
+extern "C" {
+#include <ucontext.h>
+}
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <system_error>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/disable_overload.hpp>
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+#include <boost/context/detail/exchange.hpp>
+#endif
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+#include <boost/context/detail/invoke.hpp>
+#endif
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+#include <boost/context/segmented_stack.hpp>
+#endif
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_USE_ASAN)
+extern "C" {
+void __sanitizer_start_switch_fiber( void **, const void *, size_t);
+void __sanitizer_finish_switch_fiber( void *, const void **, size_t *);
+}
+#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 {
+
+// tampoline function
+// entered if the execution context
+// is resumed for the first time
+template< typename Record >
+static void entry_func( void * data) noexcept {
+ Record * record = static_cast< Record * >( data);
+ BOOST_ASSERT( nullptr != record);
+ // start execution of toplevel context-function
+ record->run();
+}
+
+struct BOOST_CONTEXT_DECL activation_record {
+ thread_local static activation_record * current_rec;
+
+ ucontext_t uctx{};
+ stack_context sctx{};
+ bool main_ctx{ true };
+ activation_record * from{ nullptr };
+ std::function< void(activation_record*&) > ontop{};
+ bool terminated{ false };
+ bool force_unwind{ false };
+#if defined(BOOST_USE_ASAN)
+ void * fake_stack{ nullptr };
+ void * stack_bottom{ nullptr };
+ std::size_t stack_size{ 0 };
+ bool started{ false };
+#endif
+
+ static activation_record *& current() noexcept;
+
+ // used for toplevel-context
+ // (e.g. main context, thread-entry context)
+ activation_record() {
+ if ( BOOST_UNLIKELY( 0 != ::getcontext( & uctx) ) ) {
+ throw std::system_error(
+ std::error_code( errno, std::system_category() ),
+ "getcontext() failed");
+ }
+#if defined(BOOST_USE_ASAN)
+ stack_bottom = uctx.uc_stack.ss_sp;
+ stack_size = uctx.uc_stack.ss_size;
+#endif
+ }
+
+ activation_record( stack_context sctx_) noexcept :
+ sctx( sctx_ ),
+ main_ctx( false ) {
+ }
+
+ virtual ~activation_record() {
+ }
+
+ activation_record( activation_record const&) = delete;
+ activation_record & operator=( activation_record const&) = delete;
+
+ bool is_main_context() const noexcept {
+ return main_ctx;
+ }
+
+ activation_record * resume() {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ current() = this;
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+#if defined(BOOST_USE_ASAN)
+ if ( from->started) {
+ __sanitizer_finish_switch_fiber( from->fake_stack, (const void **) & from->stack_bottom,
+ & from->stack_size);
+ from->started = false;
+ }
+ __sanitizer_start_switch_fiber( & fake_stack, stack_bottom, stack_size);
+ started = true;
+#endif
+ // context switch from parent context to `this`-context
+ ::swapcontext( & from->uctx, & uctx);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ template< typename Ctx, typename Fn >
+ activation_record * resume_with( Fn && fn) {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by continuation::current()
+ current() = this;
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ current()->ontop = std::bind(
+ [](typename std::decay< Fn >::type & fn, activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1);
+#else
+ current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ };
+#endif
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+#if defined(BOOST_USE_ASAN)
+ if ( from->started) {
+ __sanitizer_finish_switch_fiber( from->fake_stack, (const void **) & from->stack_bottom,
+ & from->stack_size);
+ from->started = false;
+ }
+ __sanitizer_start_switch_fiber( & fake_stack, stack_bottom, stack_size);
+ started = true;
+#endif
+ // context switch from parent context to `this`-context
+ ::swapcontext( & from->uctx, & uctx);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ virtual void deallocate() noexcept {
+ }
+};
+
+struct BOOST_CONTEXT_DECL activation_record_initializer {
+ activation_record_initializer() noexcept;
+ ~activation_record_initializer();
+};
+
+struct forced_unwind {
+ activation_record * from{ nullptr };
+
+ forced_unwind( activation_record * from_) noexcept :
+ from{ from_ } {
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+class capture_record : public activation_record {
+private:
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+
+ 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, Fn && fn) noexcept :
+ activation_record{ sctx },
+ salloc_{ salloc },
+ fn_( std::forward< Fn >( fn) ) {
+ }
+
+ void deallocate() noexcept override final {
+ BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
+ destroy( this);
+ }
+
+ void run() {
+ Ctx c{ from };
+ try {
+ // invoke context-function
+#if defined(BOOST_NO_CXX17_STD_APPLY)
+ c = invoke( fn_, std::move( c) );
+#else
+ c = std::invoke( fn_, std::move( c) );
+#endif
+ } catch ( forced_unwind const& ex) {
+ c = Ctx{ ex.from };
+ }
+ // this context has finished its task
+ from = nullptr;
+ ontop = nullptr;
+ terminated = true;
+ force_unwind = false;
+ c.resume();
+ BOOST_ASSERT_MSG( false, "continuation already terminated");
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context1( StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ sctx, salloc, std::forward< Fn >( fn) };
+ // stack bottom
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
+ // create user-context
+ if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
+ throw std::system_error(
+ std::error_code( errno, std::system_category() ),
+ "getcontext() failed");
+ }
+ record->uctx.uc_stack.ss_sp = stack_bottom;
+ // 64byte gap between control structure and stack top
+ record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
+ reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
+ record->uctx.uc_link = nullptr;
+ ::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record);
+#if defined(BOOST_USE_ASAN)
+ record->stack_bottom = record->uctx.uc_stack.ss_sp;
+ record->stack_size = record->uctx.uc_stack.ss_size;
+#endif
+ return record;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context2( preallocated palloc, StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn) };
+ // stack bottom
+ void * stack_bottom = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) );
+ // create user-context
+ if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
+ throw std::system_error(
+ std::error_code( errno, std::system_category() ),
+ "getcontext() failed");
+ }
+ record->uctx.uc_stack.ss_sp = stack_bottom;
+ // 64byte gap between control structure and stack top
+ record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
+ reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
+ record->uctx.uc_link = nullptr;
+ ::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record);
+#if defined(BOOST_USE_ASAN)
+ record->stack_bottom = record->uctx.uc_stack.ss_sp;
+ record->stack_size = record->uctx.uc_stack.ss_size;
+#endif
+ return record;
+}
+
+}
+
+class BOOST_CONTEXT_DECL continuation {
+private:
+ friend struct detail::activation_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend class detail::capture_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context1( StackAlloc, Fn &&);
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context2( preallocated, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
+
+ detail::activation_record * ptr_{ nullptr };
+
+ continuation( detail::activation_record * ptr) noexcept :
+ ptr_{ ptr } {
+ }
+
+public:
+ continuation() = default;
+
+ ~continuation() {
+ if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
+ if ( BOOST_LIKELY( ! ptr_->terminated) ) {
+ ptr_->force_unwind = true;
+ ptr_->resume();
+ BOOST_ASSERT( ptr_->terminated);
+ }
+ ptr_->deallocate();
+ }
+ }
+
+ continuation( continuation const&) = delete;
+ continuation & operator=( continuation const&) = delete;
+
+ continuation( continuation && other) noexcept :
+ ptr_{ nullptr } {
+ swap( other);
+ }
+
+ continuation & operator=( continuation && other) noexcept {
+ if ( BOOST_LIKELY( this != & other) ) {
+ ptr_ = other.ptr_;
+ other.ptr_ = nullptr;
+ }
+ return * this;
+ }
+
+ continuation resume() {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
+#else
+ detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ template< typename Fn >
+ continuation resume_with( Fn && fn) {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr =
+ detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#else
+ detail::activation_record * ptr =
+ std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != ptr_ && ! ptr_->terminated;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == ptr_ || ptr_->terminated;
+ }
+
+ bool operator==( continuation const& other) const noexcept {
+ return ptr_ == other.ptr_;
+ }
+
+ bool operator!=( continuation const& other) const noexcept {
+ return ptr_ != other.ptr_;
+ }
+
+ bool operator<( continuation const& other) const noexcept {
+ return ptr_ < other.ptr_;
+ }
+
+ bool operator>( continuation const& other) const noexcept {
+ return other.ptr_ < ptr_;
+ }
+
+ bool operator<=( continuation const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( continuation 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, continuation const& other) {
+ if ( nullptr != other.ptr_) {
+ return os << other.ptr_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( continuation & other) noexcept {
+ std::swap( ptr_, other.ptr_);
+ }
+};
+
+template<
+ typename Fn,
+ typename = detail::disable_overload< continuation, Fn >
+>
+continuation
+callcc( Fn && fn) {
+ return callcc(
+ std::allocator_arg,
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ segmented_stack(),
+#else
+ fixedsize_stack(),
+#endif
+ std::forward< Fn >( fn) );
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context1< continuation >(
+ salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context2< continuation >(
+ palloc, salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+inline
+void swap( continuation & l, continuation & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/continuation_winfib.hpp b/boost/context/continuation_winfib.hpp
new file mode 100644
index 0000000000..8a814b0bd8
--- /dev/null
+++ b/boost/context/continuation_winfib.hpp
@@ -0,0 +1,453 @@
+
+// Copyright Oliver Kowalke 2017.
+// 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_CONTINUATION_H
+#define BOOST_CONTEXT_CONTINUATION_H
+
+#include <windows.h>
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <system_error>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/disable_overload.hpp>
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+#include <boost/context/detail/exchange.hpp>
+#endif
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+#include <boost/context/detail/invoke.hpp>
+#endif
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4702)
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+// tampoline function
+// entered if the execution context
+// is resumed for the first time
+template< typename Record >
+static VOID WINAPI entry_func( LPVOID data) noexcept {
+ Record * record = static_cast< Record * >( data);
+ BOOST_ASSERT( nullptr != record);
+ // start execution of toplevel context-function
+ record->run();
+}
+
+struct BOOST_CONTEXT_DECL activation_record {
+ thread_local static activation_record * current_rec;
+
+ LPVOID fiber{ nullptr };
+ stack_context sctx{};
+ bool main_ctx{ true };
+ activation_record * from{ nullptr };
+ std::function< void(activation_record*&) > ontop{};
+ bool terminated{ false };
+ bool force_unwind{ false };
+
+ static activation_record *& current() noexcept;
+
+ // used for toplevel-context
+ // (e.g. main context, thread-entry context)
+ activation_record() noexcept {
+#if ( _WIN32_WINNT > 0x0600)
+ if ( ::IsThreadAFiber() ) {
+ fiber = ::GetCurrentFiber();
+ } else {
+ fiber = ::ConvertThreadToFiber( nullptr);
+ }
+#else
+ fiber = ::ConvertThreadToFiber( nullptr);
+ if ( BOOST_UNLIKELY( nullptr == fiber) ) {
+ DWORD err = ::GetLastError();
+ BOOST_ASSERT( ERROR_ALREADY_FIBER == err);
+ fiber = ::GetCurrentFiber();
+ BOOST_ASSERT( nullptr != fiber);
+ BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != fiber);
+ }
+#endif
+ }
+
+ activation_record( stack_context sctx_) noexcept :
+ sctx{ sctx_ },
+ main_ctx{ false } {
+ }
+
+ virtual ~activation_record() {
+ if ( BOOST_UNLIKELY( main_ctx) ) {
+ ::ConvertFiberToThread();
+ } else {
+ ::DeleteFiber( fiber);
+ }
+ }
+
+ activation_record( activation_record const&) = delete;
+ activation_record & operator=( activation_record const&) = delete;
+
+ bool is_main_context() const noexcept {
+ return main_ctx;
+ }
+
+ activation_record * resume() {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ current() = this;
+ // context switch from parent context to `this`-context
+ // context switch
+ ::SwitchToFiber( fiber);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return detail::exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ template< typename Ctx, typename Fn >
+ activation_record * resume_with( Fn && fn) {
+ from = current();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by continuation::current()
+ current() = this;
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ current()->ontop = std::bind(
+ [](typename std::decay< Fn >::type & fn, activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1);
+#else
+ current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
+ Ctx c{ ptr };
+ fn( std::move( c) );
+ if ( ! c) {
+ ptr = nullptr;
+ }
+ };
+#endif
+ // context switch
+ ::SwitchToFiber( fiber);
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return detail::exchange( current()->from, nullptr);
+#else
+ return std::exchange( current()->from, nullptr);
+#endif
+ }
+
+ virtual void deallocate() noexcept {
+ }
+};
+
+struct BOOST_CONTEXT_DECL activation_record_initializer {
+ activation_record_initializer() noexcept;
+ ~activation_record_initializer();
+};
+
+struct forced_unwind {
+ activation_record * from{ nullptr };
+
+ explicit forced_unwind( activation_record * from_) :
+ from{ from_ } {
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+class capture_record : public activation_record {
+private:
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+
+ 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 salloc, Fn && fn) noexcept :
+ activation_record( sctx),
+ salloc_( salloc),
+ fn_( std::forward< Fn >( fn) ) {
+ }
+
+ void deallocate() noexcept override final {
+ BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
+ destroy( this);
+ }
+
+ void run() {
+ Ctx c{ from };
+ try {
+ // invoke context-function
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
+ c = invoke( fn_, std::move( c) );
+#else
+ c = std::invoke( fn_, std::move( c) );
+#endif
+ } catch ( forced_unwind const& ex) {
+ c = Ctx{ ex.from };
+ }
+ // this context has finished its task
+ from = nullptr;
+ ontop = nullptr;
+ terminated = true;
+ force_unwind = false;
+ c.resume();
+ BOOST_ASSERT_MSG( false, "continuation already terminated");
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context1( StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ auto sctx = salloc.allocate();
+ BOOST_ASSERT( ( sizeof( capture_t) ) < sctx.size);
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ sctx, salloc, std::forward< Fn >( fn) };
+ // create user-context
+ record->fiber = ::CreateFiber( sctx.size, & detail::entry_func< capture_t >, record);
+ return record;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn >
+static activation_record * create_context2( preallocated palloc, StackAlloc salloc, Fn && fn) {
+ typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
+
+ BOOST_ASSERT( ( sizeof( capture_t) ) < palloc.size);
+ // reserve space for control structure
+ void * storage = reinterpret_cast< void * >(
+ ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
+ & ~ static_cast< uintptr_t >( 0xff) );
+ // placment new for control structure on context stack
+ capture_t * record = new ( storage) capture_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn) };
+ // create user-context
+ record->fiber = ::CreateFiber( palloc.sctx.size, & detail::entry_func< capture_t >, record);
+ return record;
+}
+
+}
+
+class BOOST_CONTEXT_DECL continuation {
+private:
+ friend struct detail::activation_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend class detail::capture_record;
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context1( StackAlloc, Fn &&);
+
+ template< typename Ctx, typename StackAlloc, typename Fn >
+ friend detail::activation_record * detail::create_context2( preallocated, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, StackAlloc, Fn &&);
+
+ template< typename StackAlloc, typename Fn >
+ friend continuation
+ callcc( std::allocator_arg_t, preallocated, StackAlloc, Fn &&);
+
+ detail::activation_record * ptr_{ nullptr };
+
+ continuation( detail::activation_record * ptr) noexcept :
+ ptr_{ ptr } {
+ }
+
+public:
+ continuation() = default;
+
+ ~continuation() {
+ if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
+ if ( BOOST_LIKELY( ! ptr_->terminated) ) {
+ ptr_->force_unwind = true;
+ ptr_->resume();
+ BOOST_ASSERT( ptr_->terminated);
+ }
+ ptr_->deallocate();
+ }
+ }
+
+ continuation( continuation const&) = delete;
+ continuation & operator=( continuation const&) = delete;
+
+ continuation( continuation && other) noexcept :
+ ptr_{ nullptr } {
+ swap( other);
+ }
+
+ continuation & operator=( continuation && other) noexcept {
+ if ( BOOST_LIKELY( this != & other) ) {
+ ptr_ = other.ptr_;
+ other.ptr_ = nullptr;
+ }
+ return * this;
+ }
+
+ continuation resume() {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
+#else
+ detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ template< typename Fn >
+ continuation resume_with( Fn && fn) {
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ detail::activation_record * ptr =
+ detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#else
+ detail::activation_record * ptr =
+ std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
+#endif
+ if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
+ throw detail::forced_unwind{ ptr};
+ } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
+ detail::activation_record::current()->ontop( ptr);
+ detail::activation_record::current()->ontop = nullptr;
+ }
+ return continuation{ ptr };
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != ptr_ && ! ptr_->terminated;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == ptr_ || ptr_->terminated;
+ }
+
+ bool operator==( continuation const& other) const noexcept {
+ return ptr_ == other.ptr_;
+ }
+
+ bool operator!=( continuation const& other) const noexcept {
+ return ptr_ != other.ptr_;
+ }
+
+ bool operator<( continuation const& other) const noexcept {
+ return ptr_ < other.ptr_;
+ }
+
+ bool operator>( continuation const& other) const noexcept {
+ return other.ptr_ < ptr_;
+ }
+
+ bool operator<=( continuation const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( continuation 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, continuation const& other) {
+ if ( nullptr != other.ptr_) {
+ return os << other.ptr_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( continuation & other) noexcept {
+ std::swap( ptr_, other.ptr_);
+ }
+};
+
+template<
+ typename Fn,
+ typename = detail::disable_overload< continuation, Fn >
+>
+continuation
+callcc( Fn && fn) {
+ return callcc(
+ std::allocator_arg,
+ fixedsize_stack(),
+ std::forward< Fn >( fn) );
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context1< continuation >(
+ salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+template< typename StackAlloc, typename Fn >
+continuation
+callcc( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn) {
+ return continuation{
+ detail::create_context2< continuation >(
+ palloc, salloc, std::forward< Fn >( fn) ) }.resume();
+}
+
+inline
+void swap( continuation & l, continuation & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_CONTINUATION_H
diff --git a/boost/context/detail/config.hpp b/boost/context/detail/config.hpp
index 84dd238100..15d03574b1 100644
--- a/boost/context/detail/config.hpp
+++ b/boost/context/detail/config.hpp
@@ -104,4 +104,15 @@
# endif
#endif
+#if ! defined(BOOST_NO_CXX11_CONSTEXPR)
+// modern architectures have cachelines with 64byte length
+// ARM Cortex-A15 32/64byte, Cortex-A9 16/32/64bytes
+// MIPS 74K: 32byte, 4KEc: 16byte
+// ist should be safe to use 64byte for all
+static constexpr std::size_t cache_alignment{ 64 };
+static constexpr std::size_t cacheline_length{ 64 };
+// lookahead size for prefetching
+static constexpr std::size_t prefetch_stride{ 4 * cacheline_length };
+#endif
+
#endif // BOOST_CONTEXT_DETAIL_CONFIG_H
diff --git a/boost/context/detail/exception.hpp b/boost/context/detail/exception.hpp
index 8ffff6780a..14b4ab5217 100644
--- a/boost/context/detail/exception.hpp
+++ b/boost/context/detail/exception.hpp
@@ -20,7 +20,9 @@ namespace context {
namespace detail {
struct forced_unwind {
- fcontext_t fctx;
+ fcontext_t fctx{ nullptr };
+
+ forced_unwind() = default;
forced_unwind( fcontext_t fctx_) :
fctx( fctx_) {
diff --git a/boost/context/detail/fcontext_arm.hpp b/boost/context/detail/fcontext_arm.hpp
deleted file mode 100644
index 8b88ccfdd4..0000000000
--- a/boost/context/detail/fcontext_arm.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[16];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[11];
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_H
diff --git a/boost/context/detail/fcontext_arm_mac.hpp b/boost/context/detail/fcontext_arm_mac.hpp
deleted file mode 100644
index a8416efd0c..0000000000
--- a/boost/context/detail/fcontext_arm_mac.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[16];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[11];
- stack_t fc_stack;
- fp_t fc_fp;
- void * fc_unwind_sjlj;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp(),
- fc_unwind_sjlj( 0)
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H
diff --git a/boost/context/detail/fcontext_arm_win.hpp b/boost/context/detail/fcontext_arm_win.hpp
deleted file mode 100644
index 5449ae763f..0000000000
--- a/boost/context/detail/fcontext_arm_win.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
- void * limit;
-
- stack_t() :
- sp( 0), size( 0), limit( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[16];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[11];
- stack_t fc_stack;
- fp_t fc_fp;
- boost::uint32_t fc_dealloc;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp(),
- fc_dealloc( 0)
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H
diff --git a/boost/context/detail/fcontext_i386.hpp b/boost/context/detail/fcontext_i386.hpp
deleted file mode 100644
index 2e01323556..0000000000
--- a/boost/context/detail/fcontext_i386.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_I386H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_I386H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL __attribute__((cdecl))
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[6];
- stack_t fc_stack;
- boost::uint32_t fc_freg[2];
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_freg()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_I386_H
diff --git a/boost/context/detail/fcontext_i386_win.hpp b/boost/context/detail/fcontext_i386_win.hpp
deleted file mode 100644
index 44c6b0ef56..0000000000
--- a/boost/context/detail/fcontext_i386_win.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_I386H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_I386H
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4351)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL __cdecl
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
- void * limit;
-
- stack_t() :
- sp( 0), size( 0), limit( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[2];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[6];
- stack_t fc_stack;
- void * fc_excpt_lst;
- void * fc_local_storage;
- fp_t fc_fp;
- boost::uint32_t fc_dealloc;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_excpt_lst( 0),
- fc_local_storage( 0),
- fc_fp(),
- fc_dealloc( 0)
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_I386_H
diff --git a/boost/context/detail/fcontext_mips.hpp b/boost/context/detail/fcontext_mips.hpp
deleted file mode 100644
index d3cd60de48..0000000000
--- a/boost/context/detail/fcontext_mips.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_MIPS_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_MIPS_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-// on MIPS we assume 64bit regsiters - even for 32bit ABIs
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint64_t fc_freg[6];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint32_t fc_greg[12];
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_MIPS_H
diff --git a/boost/context/detail/fcontext_ppc.hpp b/boost/context/detail/fcontext_ppc.hpp
deleted file mode 100644
index 6cb019f54f..0000000000
--- a/boost/context/detail/fcontext_ppc.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_PPC_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_PPC_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint64_t fc_freg[19];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
-# if defined(__powerpc64__)
- boost::uint64_t fc_greg[23];
-# else
- boost::uint32_t fc_greg[23];
-# endif
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_PPC_H
diff --git a/boost/context/detail/fcontext_sparc.hpp b/boost/context/detail/fcontext_sparc.hpp
deleted file mode 100644
index 9264714aee..0000000000
--- a/boost/context/detail/fcontext_sparc.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright Martin Husemann 2012
-// 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_CTX_DETAIL_FCONTEXT_SPARC_H
-#define BOOST_CTX_DETAIL_FCONTEXT_SPARC_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-// if defined(_LP64) we are compiling for sparc64, otherwise it is 32 bit
-// sparc.
-
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
-#ifdef _LP64
- boost::uint64_t fp_freg[32];
- boost::uint64_t fp_fprs, fp_fsr;
-#else
- boost::uint64_t fp_freg[16];
- boost::uint32_t fp_fsr;
-#endif
-
- fp_t() :
- fp_freg(),
-#ifdef _LP64
- fp_fprs(),
-#endif
- fp_fsr()
- {}
-}
-#ifdef _LP64
- __attribute__((__aligned__(64))) // allow VIS instructions to be used
-#endif
-;
-
-struct fcontext_t
-{
- fp_t fc_fp; // fpu stuff first, for easier alignement
-#ifdef _LP64
- boost::uint64_t
-#else
- boost::uint32_t
-#endif
- fc_greg[8];
- stack_t fc_stack;
-
- fcontext_t() :
- fc_fp(),
- fc_greg(),
- fc_stack()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CTX_DETAIL_FCONTEXT_SPARC_H
diff --git a/boost/context/detail/fcontext_x86_64.hpp b/boost/context/detail/fcontext_x86_64.hpp
deleted file mode 100644
index 6e8d93c0cb..0000000000
--- a/boost/context/detail/fcontext_x86_64.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
-
- stack_t() :
- sp( 0), size( 0)
- {}
-};
-
-struct fp_t
-{
- boost::uint32_t fc_freg[2];
-
- fp_t() :
- fc_freg()
- {}
-};
-
-struct fcontext_t
-{
- boost::uint64_t fc_greg[8];
- stack_t fc_stack;
- fp_t fc_fp;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_fp()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
diff --git a/boost/context/detail/fcontext_x86_64_win.hpp b/boost/context/detail/fcontext_x86_64_win.hpp
deleted file mode 100644
index 7bcea55fb3..0000000000
--- a/boost/context/detail/fcontext_x86_64_win.hpp
+++ /dev/null
@@ -1,77 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-#define BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4351)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-extern "C" {
-
-#define BOOST_CONTEXT_CALLDECL
-
-struct stack_t
-{
- void * sp;
- std::size_t size;
- void * limit;
-
- stack_t() :
- sp( 0), size( 0), limit( 0)
- {}
-};
-
-struct fcontext_t
-{
- boost::uint64_t fc_greg[10];
- stack_t fc_stack;
- void * fc_local_storage;
- boost::uint64_t fc_fp[24];
- boost::uint64_t fc_dealloc;
-
- fcontext_t() :
- fc_greg(),
- fc_stack(),
- fc_local_storage( 0),
- fc_fp(),
- fc_dealloc()
- {}
-};
-
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H
diff --git a/boost/context/detail/prefetch.hpp b/boost/context/detail/prefetch.hpp
new file mode 100644
index 0000000000..a479450c74
--- /dev/null
+++ b/boost/context/detail/prefetch.hpp
@@ -0,0 +1,78 @@
+// Copyright Oliver Kowalke 2017.
+// 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_PREFETCH_H
+#define BOOST_CONTEXT_DETAIL_PREFETCH_H
+
+#include <cstddef>
+#include <cstdint>
+
+#include <boost/config.hpp>
+#include <boost/predef.h>
+
+#include <boost/context/detail/config.hpp>
+
+#if BOOST_COMP_INTEL || BOOST_COMP_INTEL_EMULATED
+#include <immintrin.h>
+#endif
+
+#if BOOST_COMP_MSVC
+#include <mmintrin.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+#if BOOST_COMP_GNUC || BOOST_COMP_CLANG
+#define BOOST_HAS_PREFETCH 1
+BOOST_FORCEINLINE
+void prefetch( void * addr) {
+ // L1 cache : hint == 1
+ __builtin_prefetch( addr, 1, 1);
+}
+#elif BOOST_COMP_INTEL || BOOST_COMP_INTEL_EMULATED
+#define BOOST_HAS_PREFETCH 1
+BOOST_FORCEINLINE
+void prefetch( void * addr) {
+ // L1 cache : hint == _MM_HINT_T0
+ _mm_prefetch( (const char *)addr, _MM_HINT_T0);
+}
+#elif BOOST_COMP_MSVC
+#define BOOST_HAS_PREFETCH 1
+BOOST_FORCEINLINE
+void prefetch( void * addr) {
+ // L1 cache : hint == _MM_HINT_T0
+ _mm_prefetch( (const char *)addr, _MM_HINT_T0);
+}
+#endif
+
+inline
+void prefetch_range( void * addr, std::size_t len) {
+#if defined(BOOST_HAS_PREFETCH)
+ void * vp = addr;
+ void * end = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( addr) + static_cast< uintptr_t >( len) );
+ while ( vp < end) {
+ prefetch( vp);
+ vp = reinterpret_cast< void * >(
+ reinterpret_cast< uintptr_t >( vp) + static_cast< uintptr_t >( prefetch_stride) );
+ }
+#endif
+}
+
+#undef BOOST_HAS_PREFETCH
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_PREFETCH_H
diff --git a/boost/context/fixedsize_stack.hpp b/boost/context/fixedsize_stack.hpp
index 46e7866891..756b260bda 100644
--- a/boost/context/fixedsize_stack.hpp
+++ b/boost/context/fixedsize_stack.hpp
@@ -4,10 +4,77 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_CONTEXT_FIXEDSIZE_H
+#define BOOST_CONTEXT_FIXEDSIZE_H
+
+#include <cstddef>
+#include <cstdlib>
+#include <new>
+
+#include <boost/assert.hpp>
#include <boost/config.hpp>
-#if defined(BOOST_WINDOWS)
-# include <boost/context/windows/fixedsize_stack.hpp>
-#else
-# include <boost/context/posix/fixedsize_stack.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_fixedsize_stack {
+private:
+ std::size_t size_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
+ size_( size) {
+ }
+
+ stack_context allocate() {
+ void * vp = std::malloc( size_);
+ if ( ! vp) {
+ throw std::bad_alloc();
+ }
+ stack_context sctx;
+ sctx.size = 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);
+
+#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);
+ }
+};
+
+typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
+# if ! defined(BOOST_USE_SEGMENTED_STACKS)
+typedef fixedsize_stack default_stack;
+# endif
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_FIXEDSIZE_H
diff --git a/boost/context/pooled_fixedsize_stack.hpp b/boost/context/pooled_fixedsize_stack.hpp
index 3c0953cd07..9c417fd7ce 100644
--- a/boost/context/pooled_fixedsize_stack.hpp
+++ b/boost/context/pooled_fixedsize_stack.hpp
@@ -14,6 +14,7 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
#include <boost/pool/pool.hpp>
#include <boost/context/detail/config.hpp>
diff --git a/boost/context/posix/fixedsize_stack.hpp b/boost/context/posix/fixedsize_stack.hpp
deleted file mode 100644
index 756b260bda..0000000000
--- a/boost/context/posix/fixedsize_stack.hpp
+++ /dev/null
@@ -1,80 +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_FIXEDSIZE_H
-#define BOOST_CONTEXT_FIXEDSIZE_H
-
-#include <cstddef>
-#include <cstdlib>
-#include <new>
-
-#include <boost/assert.hpp>
-#include <boost/config.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_fixedsize_stack {
-private:
- std::size_t size_;
-
-public:
- typedef traitsT traits_type;
-
- basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
- size_( size) {
- }
-
- stack_context allocate() {
- void * vp = std::malloc( size_);
- if ( ! vp) {
- throw std::bad_alloc();
- }
- stack_context sctx;
- sctx.size = 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);
-
-#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);
- }
-};
-
-typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
-# if ! defined(BOOST_USE_SEGMENTED_STACKS)
-typedef fixedsize_stack default_stack;
-# endif
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_FIXEDSIZE_H
diff --git a/boost/context/posix/protected_fixedsize_stack.hpp b/boost/context/posix/protected_fixedsize_stack.hpp
index f36d451b40..b0c7f7e675 100644
--- a/boost/context/posix/protected_fixedsize_stack.hpp
+++ b/boost/context/posix/protected_fixedsize_stack.hpp
@@ -49,15 +49,13 @@ public:
}
stack_context allocate() {
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
+ // calculate how many pages are required
+ const std::size_t pages(
+ static_cast< std::size_t >(
+ std::ceil(
static_cast< float >( size_) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
- const std::size_t size__( pages * traits_type::page_size() );
- BOOST_ASSERT( 0 != size_ && 0 != size__);
- BOOST_ASSERT( size__ <= size_);
+ // add one page at bottom that will be used as guard-page
+ const std::size_t size__ = ( pages + 1) * traits_type::page_size();
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
#if defined(MAP_ANON)
diff --git a/boost/context/windows/fixedsize_stack.hpp b/boost/context/windows/fixedsize_stack.hpp
deleted file mode 100644
index a67c315c47..0000000000
--- a/boost/context/windows/fixedsize_stack.hpp
+++ /dev/null
@@ -1,80 +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_FIXEDSIZE_H
-#define BOOST_CONTEXT_FIXEDSIZE_H
-
-extern "C" {
-#include <windows.h>
-}
-
-#include <cmath>
-#include <cstddef>
-#include <new>
-
-#include <boost/config.hpp>
-
-#include <boost/context/detail/config.hpp>
-#include <boost/context/stack_context.hpp>
-#include <boost/context/stack_traits.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-
-template< typename traitsT >
-class basic_fixedsize_stack {
-private:
- std::size_t size_;
-
-public:
- typedef traitsT traits_type;
-
- basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
- size_( size) {
- }
-
- stack_context allocate() {
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
- static_cast< float >( size_) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 1 <= pages, "at least one page must fit into stack");
- const std::size_t size__( pages * traits_type::page_size() );
- BOOST_ASSERT( 0 != size_ && 0 != size__);
- BOOST_ASSERT( size__ <= size_);
-
- void * vp = ::VirtualAlloc( 0, size__, MEM_COMMIT, PAGE_READWRITE);
- if ( ! vp) throw std::bad_alloc();
-
- stack_context sctx;
- sctx.size = size__;
- sctx.sp = static_cast< char * >( vp) + sctx.size;
- return sctx;
- }
-
- void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
- BOOST_ASSERT( sctx.sp);
-
- void * vp = static_cast< char * >( sctx.sp) - sctx.size;
- ::VirtualFree( vp, 0, MEM_RELEASE);
- }
-};
-
-typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
-typedef fixedsize_stack default_stack;
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXT_FIXEDSIZE_H
diff --git a/boost/context/windows/protected_fixedsize_stack.hpp b/boost/context/windows/protected_fixedsize_stack.hpp
index 437f091088..26d2086095 100644
--- a/boost/context/windows/protected_fixedsize_stack.hpp
+++ b/boost/context/windows/protected_fixedsize_stack.hpp
@@ -41,15 +41,13 @@ public:
}
stack_context allocate() {
- // page at bottom will be used as guard-page
- const std::size_t pages(
- static_cast< std::size_t >(
- std::floor(
+ // calculate how many pages are required
+ const std::size_t pages(
+ static_cast< std::size_t >(
+ std::ceil(
static_cast< float >( size_) / traits_type::page_size() ) ) );
- BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
- const std::size_t size__( pages * traits_type::page_size() );
- BOOST_ASSERT( 0 != size_ && 0 != size__);
- BOOST_ASSERT( size__ <= size_);
+ // add one page at bottom that will be used as guard-page
+ const std::size_t size__ = ( pages + 1) * traits_type::page_size();
void * vp = ::VirtualAlloc( 0, size__, MEM_COMMIT, PAGE_READWRITE);
if ( ! vp) throw std::bad_alloc();