2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-19 02:12:24 +00:00

Merge branch 'develop' of github.com:olk/boost-fiber into develop

This commit is contained in:
Nat Goodspeed
2016-02-12 10:23:57 -05:00
6 changed files with 126 additions and 86 deletions

View File

@@ -26,6 +26,7 @@
#include <boost/intrusive/set.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/data.hpp>
#include <boost/fiber/detail/decay_copy.hpp>
#include <boost/fiber/detail/fss.hpp>
#include <boost/fiber/detail/spinlock.hpp>
@@ -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
}
}

View File

@@ -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 <boost/config.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/spinlock.hpp>
#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

View File

@@ -14,6 +14,7 @@
#include <boost/context/execution_context.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/data.hpp>
#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);
}
};

View File

@@ -20,6 +20,7 @@
#include <boost/fiber/algorithm.hpp>
#include <boost/fiber/context.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/data.hpp>
#include <boost/fiber/detail/spinlock.hpp>
#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;

View File

@@ -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

View File

@@ -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);