diff --git a/include/boost/fiber/context.hpp b/include/boost/fiber/context.hpp index d23f64c3..993f2603 100644 --- a/include/boost/fiber/context.hpp +++ b/include/boost/fiber/context.hpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -143,7 +144,8 @@ private: void * vp{ nullptr }; detail::fss_cleanup_function::ptr_t cleanup_function{}; - constexpr fss_data() noexcept = default; + fss_data() noexcept { + } fss_data( void * vp_, detail::fss_cleanup_function::ptr_t const& fn) noexcept : @@ -157,65 +159,30 @@ private: } }; -#if (BOOST_EXECUTION_CONTEXT==1) - struct data_t { - detail::spinlock_lock * lk{ nullptr }; - context * ctx{ nullptr }; - - constexpr data_t() noexcept = default; - - explicit data_t( detail::spinlock_lock * lk_) noexcept : - lk{ lk_ } { - } - - explicit data_t( context * ctx_) noexcept : - ctx{ ctx_ } { - } - }; -#else - struct data_t { - detail::spinlock_lock * lk{ nullptr }; - context * ctx{ nullptr }; - context * from; - - explicit data_t( context * from_) noexcept : - from{ from_ } { - } - - explicit data_t( detail::spinlock_lock * lk_, - context * from_) noexcept : - lk{ lk_ }, - from{ from_ } { - } - - explicit data_t( context * ctx_, - context * from_) noexcept : - ctx{ ctx_ }, - from{ from_ } { - } - }; -#endif - typedef std::map< uintptr_t, fss_data > fss_data_t; - static thread_local context * active_; + static thread_local context * active_; #if ! defined(BOOST_FIBERS_NO_ATOMICS) - std::atomic< std::size_t > use_count_{ 0 }; - std::atomic< int > flags_; + std::atomic< std::size_t > use_count_{ 0 }; + std::atomic< int > flags_; #else - std::size_t use_count_{ 0 }; - int flags_; + std::size_t use_count_{ 0 }; + int flags_; +#endif + scheduler * scheduler_{ nullptr }; +#if (BOOST_EXECUTION_CONTEXT==1) + boost::context::execution_context ctx_; +#else + boost::context::execution_context< detail::data_t * > ctx_; #endif - scheduler * scheduler_{ nullptr }; - boost::context::execution_context ctx_; - void resume_( data_t &) noexcept; + void resume_( detail::data_t &) noexcept; void set_ready_( context *) noexcept; #if (BOOST_EXECUTION_CONTEXT==1) template< typename Fn, typename Tpl > - void run_( Fn && fn_, Tpl && tpl_, data_t * dp) noexcept { + void run_( Fn && fn_, Tpl && tpl_, detail::data_t * dp) noexcept { try { typename std::decay< Fn >::type fn = std::forward< Fn >( fn_); typename std::decay< Tpl >::type tpl = std::forward< Tpl >( tpl_); @@ -233,8 +200,8 @@ private: } #else template< typename Fn, typename Tpl > - boost::context::execution_context - run_( boost::context::execution_context ctx, Fn && fn_, Tpl && tpl_, data_t * dp) noexcept { + boost::context::execution_context< detail::data_t * > + run_( boost::context::execution_context< detail::data_t * > ctx, Fn && fn_, Tpl && tpl_, detail::data_t * dp) noexcept { try { typename std::decay< Fn >::type fn = std::forward< Fn >( fn_); typename std::decay< Tpl >::type tpl = std::forward< Tpl >( tpl_); @@ -279,7 +246,8 @@ public: context * impl_{ nullptr }; public: - constexpr id() noexcept = default; + id() noexcept { + } explicit id( context * impl) noexcept : impl_( impl) { @@ -355,7 +323,7 @@ public: detail::wrap( [this]( typename std::decay< Fn >::type & fn, typename std::decay< Tpl >::type & tpl, boost::context::execution_context & ctx, void * vp) mutable noexcept { - run_( std::move( fn), std::move( tpl), static_cast< data_t * >( vp) ); + run_( std::move( fn), std::move( tpl), static_cast< detail::data_t * >( vp) ); }, std::forward< Fn >( fn), std::forward< Tpl >( tpl), @@ -365,7 +333,7 @@ public: ctx_{ std::allocator_arg, palloc, salloc, [this,fn=detail::decay_copy( std::forward< Fn >( fn) ),tpl=std::forward< Tpl >( tpl), ctx=boost::context::execution_context::current()] (void * vp) mutable noexcept { - run_( std::move( fn), std::move( tpl), static_cast< data_t * >( vp) ); + run_( std::move( fn), std::move( tpl), static_cast< detail::data_t * >( vp) ); }} # endif #else @@ -373,8 +341,8 @@ public: ctx_{ std::allocator_arg, palloc, salloc, detail::wrap( [this]( typename std::decay< Fn >::type & fn, typename std::decay< Tpl >::type & tpl, - boost::context::execution_context ctx, void * vp) mutable noexcept { - return run_( std::move( ctx), std::move( fn), std::move( tpl), static_cast< data_t * >( vp) ); + boost::context::execution_context< detail::data_t * > ctx, detail::data_t * dp) mutable noexcept { + return run_( std::move( ctx), std::move( fn), std::move( tpl), dp); }, std::forward< Fn >( fn), std::forward< Tpl >( tpl) )} @@ -382,8 +350,8 @@ public: # else ctx_{ std::allocator_arg, palloc, salloc, [this,fn=detail::decay_copy( std::forward< Fn >( fn) ),tpl=std::forward< Tpl >( tpl)] - (boost::context::execution_context ctx, void * vp) mutable noexcept { - return run_( std::move( ctx), std::move( fn), std::move( tpl), static_cast< data_t * >( vp) ); + (boost::context::execution_context< detail::data_t * > ctx, detail::data_t * dp) mutable noexcept { + return run_( std::move( ctx), std::move( fn), std::move( tpl), dp); }} # endif #endif @@ -408,8 +376,8 @@ public: #if (BOOST_EXECUTION_CONTEXT==1) void set_terminated() noexcept; #else - boost::context::execution_context suspend_with_cc() noexcept; - boost::context::execution_context set_terminated() noexcept; + boost::context::execution_context< detail::data_t * > suspend_with_cc() noexcept; + boost::context::execution_context< detail::data_t * > set_terminated() noexcept; #endif void join(); @@ -539,11 +507,11 @@ public: // deallocates stack (execution_context is ref counted) ctx->~context(); #else - boost::context::execution_context cc( std::move( ctx->ctx_) ); + boost::context::execution_context< detail::data_t * > cc( std::move( ctx->ctx_) ); // destruct context ctx->~context(); // deallocated stack - cc(); + cc( nullptr); #endif } } diff --git a/include/boost/fiber/detail/data.hpp b/include/boost/fiber/detail/data.hpp new file mode 100644 index 00000000..a3e8a7e3 --- /dev/null +++ b/include/boost/fiber/detail/data.hpp @@ -0,0 +1,71 @@ + +// Copyright Oliver Kowalke 2013. +// 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_FIBERS_DETAIL_DATA_H +#define BOOST_FIBERS_DETAIL_DATA_H + +#include + +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace fibers { + +class context; + +namespace detail { + +#if (BOOST_EXECUTION_CONTEXT==1) +struct data_t { + spinlock_lock * lk{ nullptr }; + context * ctx{ nullptr }; + + constexpr data_t() noexcept = default; + + explicit data_t( spinlock_lock * lk_) noexcept : + lk{ lk_ } { + } + + explicit data_t( context * ctx_) noexcept : + ctx{ ctx_ } { + } +}; +#else +struct data_t { + spinlock_lock * lk{ nullptr }; + context * ctx{ nullptr }; + context * from; + + explicit data_t( context * from_) noexcept : + from{ from_ } { + } + + explicit data_t( spinlock_lock * lk_, + context * from_) noexcept : + lk{ lk_ }, + from{ from_ } { + } + + explicit data_t( context * ctx_, + context * from_) noexcept : + ctx{ ctx_ }, + from{ from_ } { + } +}; +#endif + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_FIBERS_DETAIL_DATA_H diff --git a/include/boost/fiber/detail/wrap.hpp b/include/boost/fiber/detail/wrap.hpp index cf3b062a..850763b4 100644 --- a/include/boost/fiber/detail/wrap.hpp +++ b/include/boost/fiber/detail/wrap.hpp @@ -14,6 +14,7 @@ #include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -85,11 +86,11 @@ public: wrapper( wrapper && other) = default; wrapper & operator=( wrapper && other) = default; - boost::context::execution_context - operator()( boost::context::execution_context ctx, void * vp) { + boost::context::execution_context< data_t * > + operator()( boost::context::execution_context< data_t * > ctx, data_t * dp) { return boost::context::detail::invoke( std::move( fn1_), - fn2_, tpl_, std::move( ctx), vp); + fn2_, tpl_, std::move( ctx), dp); } }; diff --git a/include/boost/fiber/scheduler.hpp b/include/boost/fiber/scheduler.hpp index 75998f75..4eb407cd 100644 --- a/include/boost/fiber/scheduler.hpp +++ b/include/boost/fiber/scheduler.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #ifdef BOOST_HAS_ABI_HEADERS @@ -109,9 +110,9 @@ public: void set_terminated( context *) noexcept; #else - boost::context::execution_context dispatch() noexcept; + boost::context::execution_context< detail::data_t * > dispatch() noexcept; - boost::context::execution_context set_terminated( context *) noexcept; + boost::context::execution_context< detail::data_t * > set_terminated( context *) noexcept; #endif void yield( context *) noexcept; diff --git a/src/context.cpp b/src/context.cpp index c9fe6826..fde1d7ee 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -150,8 +150,8 @@ context::reset_active() noexcept { #if (BOOST_EXECUTION_CONTEXT==1) void -context::resume_( data_t & d) noexcept { - data_t * dp = static_cast< data_t * >( ctx_( & d) ); +context::resume_( detail::data_t & d) noexcept { + detail::data_t * dp = static_cast< detail::data_t * >( ctx_( & d) ); if ( nullptr != dp->lk) { dp->lk->unlock(); } else if ( nullptr != dp->ctx) { @@ -160,9 +160,9 @@ context::resume_( data_t & d) noexcept { } #else void -context::resume_( data_t & d) noexcept { +context::resume_( detail::data_t & d) noexcept { auto result = ctx_( & d); - data_t * dp( static_cast< data_t * >( std::get< 1 >( result) ) ); + detail::data_t * dp( std::get< 1 >( result) ); if ( nullptr != dp) { dp->from->ctx_ = std::move( std::get< 0 >( result) ); if ( nullptr != dp->lk) { @@ -186,7 +186,7 @@ context::context( main_context_t) noexcept : #if (BOOST_EXECUTION_CONTEXT==1) ctx_{ boost::context::execution_context::current() } { #else - ctx_() { + ctx_{} { #endif } @@ -197,7 +197,7 @@ context::context( dispatcher_context_t, boost::context::preallocated const& pall #if (BOOST_EXECUTION_CONTEXT==1) ctx_{ std::allocator_arg, palloc, salloc, [this,sched](void * vp) noexcept { - data_t * dp = static_cast< data_t * >( vp); + detail::data_t * dp = static_cast< detail::data_t * >( vp); if ( nullptr != dp->lk) { dp->lk->unlock(); } else if ( nullptr != dp->ctx) { @@ -210,8 +210,7 @@ context::context( dispatcher_context_t, boost::context::preallocated const& pall }} #else ctx_{ std::allocator_arg, palloc, salloc, - [this,sched](boost::context::execution_context ctx, void * vp) noexcept { - data_t * dp = static_cast< data_t * >( vp); + [this,sched](boost::context::execution_context< detail::data_t * > ctx, detail::data_t * dp) noexcept { // update execution_context of calling fiber dp->from->ctx_ = std::move( ctx); if ( nullptr != dp->lk) { @@ -250,9 +249,9 @@ context::resume() noexcept { // prev will point to previous active context std::swap( active_, prev); #if (BOOST_EXECUTION_CONTEXT==1) - data_t d{}; + detail::data_t d{}; #else - data_t d{ prev }; + detail::data_t d{ prev }; #endif resume_( d); } @@ -264,9 +263,9 @@ context::resume( detail::spinlock_lock & lk) noexcept { // prev will point to previous active context std::swap( active_, prev); #if (BOOST_EXECUTION_CONTEXT==1) - data_t d{ & lk }; + detail::data_t d{ & lk }; #else - data_t d{ & lk, prev }; + detail::data_t d{ & lk, prev }; #endif resume_( d); } @@ -278,9 +277,9 @@ context::resume( context * ready_ctx) noexcept { // prev will point to previous active context std::swap( active_, prev); #if (BOOST_EXECUTION_CONTEXT==1) - data_t d{ ready_ctx }; + detail::data_t d{ ready_ctx }; #else - data_t d{ ready_ctx, prev }; + detail::data_t d{ ready_ctx, prev }; #endif resume_( d); } @@ -328,13 +327,13 @@ context::yield() noexcept { } #if (BOOST_EXECUTION_CONTEXT>1) -boost::context::execution_context +boost::context::execution_context< detail::data_t * > context::suspend_with_cc() noexcept { context * prev = this; // active_ will point to `this` // prev will point to previous active context std::swap( active_, prev); - data_t d{ prev }; + detail::data_t d{ prev }; // context switch return std::move( std::get< 0 >( ctx_( & d) ) ); } @@ -343,7 +342,7 @@ context::suspend_with_cc() noexcept { #if (BOOST_EXECUTION_CONTEXT==1) void #else -boost::context::execution_context +boost::context::execution_context< detail::data_t * > #endif context::set_terminated() noexcept { // protect for concurrent access diff --git a/src/scheduler.cpp b/src/scheduler.cpp index cc32510f..364b6c87 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -129,7 +129,7 @@ scheduler::~scheduler() { void scheduler::dispatch() noexcept { #else -boost::context::execution_context +boost::context::execution_context< detail::data_t * > scheduler::dispatch() noexcept { #endif BOOST_ASSERT( context::active() == dispatcher_ctx_); @@ -246,7 +246,7 @@ scheduler::set_remote_ready( context * ctx) noexcept { void scheduler::set_terminated( context * active_ctx) noexcept { #else -boost::context::execution_context +boost::context::execution_context< detail::data_t * > scheduler::set_terminated( context * active_ctx) noexcept { #endif BOOST_ASSERT( nullptr != active_ctx);