2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-02 20:52:21 +00:00

remove dependency to deprecated execution_context (v1)

This commit is contained in:
Oliver Kowalke
2017-05-20 18:08:37 +02:00
parent a57314c145
commit e86ca17b15
6 changed files with 10 additions and 327 deletions

View File

@@ -22,11 +22,7 @@
#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
#endif
#if (BOOST_EXECUTION_CONTEXT==1)
# include <boost/context/execution_context.hpp>
#else
# include <boost/context/continuation.hpp>
#endif
#include <boost/context/continuation.hpp>
#include <boost/context/stack_context.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/parent_from_member.hpp>
@@ -195,11 +191,7 @@ private:
detail::ready_hook ready_hook_{};
detail::terminated_hook terminated_hook_{};
detail::worker_hook worker_hook_{};
#if (BOOST_EXECUTION_CONTEXT==1)
boost::context::execution_context ctx_;
#else
boost::context::continuation c_;
#endif
fiber_properties * properties_{ nullptr };
std::chrono::steady_clock::time_point tp_{ (std::chrono::steady_clock::time_point::max)() };
type type_;
@@ -208,29 +200,6 @@ private:
void resume_( detail::data_t &) noexcept;
void schedule_( context *) noexcept;
#if (BOOST_EXECUTION_CONTEXT==1)
template< typename Fn, typename Tpl >
void run_( Fn && fn_, Tpl && tpl_, detail::data_t * dp) noexcept {
{
// fn and tpl must be destroyed before calling terminate()
typename std::decay< Fn >::type fn = std::forward< Fn >( fn_);
typename std::decay< Tpl >::type tpl = std::forward< Tpl >( tpl_);
if ( nullptr != dp->lk) {
dp->lk->unlock();
} else if ( nullptr != dp->ctx) {
active()->schedule_( dp->ctx);
}
# if defined(BOOST_NO_CXX17_STD_APPLY)
boost::context::detail::apply( std::move( fn), std::move( tpl) );
# else
std::apply( std::move( fn), std::move( tpl) );
# endif
}
// terminate context
terminate();
BOOST_ASSERT_MSG( false, "fiber already terminated");
}
#else
template< typename Fn, typename Tpl >
boost::context::continuation
run_( boost::context::continuation && c, Fn && fn_, Tpl && tpl_) noexcept {
@@ -247,16 +216,15 @@ private:
} else if ( nullptr != dp->ctx) {
active()->schedule_( dp->ctx);
}
# if defined(BOOST_NO_CXX17_STD_APPLY)
boost::context::detail::apply( std::move( fn), std::move( tpl) );
# else
std::apply( std::move( fn), std::move( tpl) );
# endif
#if defined(BOOST_NO_CXX17_STD_APPLY)
boost::context::detail::apply( std::move( fn), std::move( tpl) );
#else
std::apply( std::move( fn), std::move( tpl) );
#endif
}
// terminate context
return terminate();
}
#endif
public:
class id {
@@ -334,35 +302,9 @@ public:
boost::context::preallocated palloc, StackAlloc salloc,
Fn && fn, Tpl && tpl) :
use_count_{ 1 }, // fiber instance or scheduler owner
#if (BOOST_EXECUTION_CONTEXT==1)
# if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
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 {
run_( std::move( fn), std::move( tpl), static_cast< detail::data_t * >( vp) );
},
std::forward< Fn >( fn),
std::forward< Tpl >( tpl),
boost::context::execution_context::current() )
},
type_{ type::worker_context },
policy_{ policy }
# else
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< detail::data_t * >( vp) );
}},
type_{ type::worker_context },
policy_{ policy }
# endif
{}
#else
c_{},
type_{ type::worker_context },
policy_{ policy }
{
policy_{ policy } {
# if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
c_ = boost::context::callcc(
std::allocator_arg, palloc, salloc,
@@ -381,8 +323,7 @@ public:
return run_( std::forward< boost::context::continuation >( c), std::move( fn), std::move( tpl) );
});
# endif
}
#endif
}
context( context const&) = delete;
context & operator=( context const&) = delete;
@@ -401,11 +342,7 @@ public:
id get_id() const noexcept;
bool is_resumable() const noexcept {
#if (BOOST_EXECUTION_CONTEXT==1)
if ( ctx_) return true;
#else
if ( c_) return true;
#endif
else return false;
}
@@ -416,12 +353,8 @@ public:
void suspend() noexcept;
void suspend( detail::spinlock_lock &) noexcept;
#if (BOOST_EXECUTION_CONTEXT==1)
void terminate() noexcept;
#else
boost::context::continuation suspend_with_cc() noexcept;
boost::context::continuation terminate() noexcept;
#endif
void join();
@@ -528,18 +461,11 @@ public:
BOOST_ASSERT( nullptr != ctx);
if ( 1 == ctx->use_count_.fetch_sub( 1, std::memory_order_release) ) {
std::atomic_thread_fence( std::memory_order_acquire);
#if (BOOST_EXECUTION_CONTEXT==1)
boost::context::execution_context ec = ctx->ctx_;
// destruct context
// deallocates stack (execution_context is ref counted)
ctx->~context();
#else
boost::context::continuation c = std::move( ctx->c_);
// destruct context
ctx->~context();
// deallocated stack
c.resume( nullptr);
#endif
}
}
};

View File

@@ -23,22 +23,6 @@ class context;
namespace detail {
#if (BOOST_EXECUTION_CONTEXT==1)
struct data_t {
spinlock_lock * lk{ nullptr };
context * ctx{ nullptr };
data_t() = 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 };
@@ -60,7 +44,6 @@ struct data_t {
from{ from_ } {
}
};
#endif
}}}

View File

@@ -13,11 +13,7 @@
#if defined(BOOST_NO_CXX17_STD_INVOKE)
#include <boost/context/detail/invoke.hpp>
#endif
#if (BOOST_EXECUTION_CONTEXT==1)
# include <boost/context/execution_context.hpp>
#else
# include <boost/context/continuation.hpp>
#endif
#include <boost/context/continuation.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/data.hpp>
@@ -30,50 +26,6 @@ namespace boost {
namespace fibers {
namespace detail {
#if (BOOST_EXECUTION_CONTEXT==1)
template< typename Fn1, typename Fn2, typename Tpl >
class wrapper {
private:
typename std::decay< Fn1 >::type fn1_;
typename std::decay< Fn2 >::type fn2_;
typename std::decay< Tpl >::type tpl_;
boost::context::execution_context ctx_;
public:
wrapper( Fn1 && fn1, Fn2 && fn2, Tpl && tpl,
boost::context::execution_context const& ctx) :
fn1_( std::move( fn1) ),
fn2_( std::move( fn2) ),
tpl_( std::move( tpl) ),
ctx_( ctx ) {
}
wrapper( wrapper const&) = delete;
wrapper & operator=( wrapper const&) = delete;
wrapper( wrapper && other) = default;
wrapper & operator=( wrapper && other) = default;
void operator()( void * vp) {
#if defined(BOOST_NO_CXX17_STD_INVOKE)
boost::context::detail::invoke( std::move( fn1_), fn2_, tpl_, ctx_, vp);
#else
std::invoke( std::move( fn1_), fn2_, tpl_, ctx_, vp);
#endif
}
};
template< typename Fn1, typename Fn2, typename Tpl >
wrapper< Fn1, Fn2, Tpl >
wrap( Fn1 && fn1, Fn2 && fn2, Tpl && tpl,
boost::context::execution_context const& ctx) {
return wrapper< Fn1, Fn2, Tpl >{
std::forward< Fn1 >( fn1),
std::forward< Fn2 >( fn2),
std::forward< Tpl >( tpl),
ctx };
}
#else
template< typename Fn1, typename Fn2, typename Tpl >
class wrapper {
private:
@@ -120,7 +72,6 @@ wrap( Fn1 && fn1, Fn2 && fn2, Tpl && tpl) {
std::forward< Fn2 >( fn2),
std::forward< Tpl >( tpl) };
}
#endif
}}}

View File

@@ -13,11 +13,7 @@
#include <vector>
#include <boost/config.hpp>
#if (BOOST_EXECUTION_CONTEXT==1)
# include <boost/context/execution_context.hpp>
#else
# include <boost/context/continuation.hpp>
#endif
#include <boost/context/continuation.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/intrusive/set.hpp>
@@ -126,15 +122,9 @@ public:
void schedule_from_remote( context *) noexcept;
#endif
#if (BOOST_EXECUTION_CONTEXT==1)
void dispatch() noexcept;
void terminate( detail::spinlock_lock &, context *) noexcept;
#else
boost::context::continuation dispatch() noexcept;
boost::context::continuation terminate( detail::spinlock_lock &, context *) noexcept;
#endif
void yield( context *) noexcept;

View File

@@ -133,10 +133,6 @@ thread_local std::size_t context_initializer::counter_;
context *
context::active() noexcept {
#if (BOOST_EXECUTION_CONTEXT==1)
// initialized the first time control passes; per thread
thread_local static boost::context::detail::activation_record_initializer rec_initializer;
#endif
// initialized the first time control passes; per thread
thread_local static context_initializer ctx_initializer;
return context_initializer::active_;
@@ -147,17 +143,6 @@ context::reset_active() noexcept {
context_initializer::active_ = nullptr;
}
#if (BOOST_EXECUTION_CONTEXT==1)
void
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) {
active()->schedule_( dp->ctx);
}
}
#else
void
context::resume_( detail::data_t & d) noexcept {
boost::context::continuation c = c_.resume( & d);
@@ -173,7 +158,6 @@ context::resume_( detail::data_t & d) noexcept {
}
}
}
#endif
void
context::schedule_( context * ctx) noexcept {
@@ -183,39 +167,14 @@ context::schedule_( context * ctx) noexcept {
// main fiber context
context::context( main_context_t) noexcept :
use_count_{ 1 }, // allocated on main- or thread-stack
#if (BOOST_EXECUTION_CONTEXT==1)
ctx_{ boost::context::execution_context::current() },
type_{ type::main_context },
policy_{ launch::post } {
}
#else
c_{},
type_{ type::main_context },
policy_{ launch::post } {
}
#endif
// dispatcher fiber context
context::context( dispatcher_context_t, boost::context::preallocated const& palloc,
default_stack const& salloc, scheduler * sched) :
#if (BOOST_EXECUTION_CONTEXT==1)
ctx_{ std::allocator_arg, palloc, salloc,
[this,sched](void * vp) noexcept {
detail::data_t * dp = static_cast< detail::data_t * >( vp);
if ( nullptr != dp->lk) {
dp->lk->unlock();
} else if ( nullptr != dp->ctx) {
active()->schedule_( dp->ctx);
}
// execute scheduler::dispatch()
sched->dispatch();
// dispatcher context should never return from scheduler::dispatch()
BOOST_ASSERT_MSG( false, "disatcher fiber already terminated");
}},
type_{ type::dispatcher_context },
policy_{ launch::post }
{}
#else
c_{},
type_{ type::dispatcher_context },
policy_{ launch::post } {
@@ -235,7 +194,6 @@ context::context( dispatcher_context_t, boost::context::preallocated const& pall
return sched->dispatch();
});
}
#endif
context::~context() {
// protect for concurrent access
@@ -271,11 +229,7 @@ context::resume() noexcept {
// context_initializer::active_ will point to `this`
// prev will point to previous active context
std::swap( context_initializer::active_, prev);
#if (BOOST_EXECUTION_CONTEXT==1)
detail::data_t d;
#else
detail::data_t d{ prev };
#endif
resume_( d);
}
@@ -285,11 +239,7 @@ context::resume( detail::spinlock_lock & lk) noexcept {
// context_initializer::active_ will point to `this`
// prev will point to previous active context
std::swap( context_initializer::active_, prev);
#if (BOOST_EXECUTION_CONTEXT==1)
detail::data_t d{ & lk };
#else
detail::data_t d{ & lk, prev };
#endif
resume_( d);
}
@@ -299,11 +249,7 @@ context::resume( context * ready_ctx) noexcept {
// context_initializer::active_ will point to `this`
// prev will point to previous active context
std::swap( context_initializer::active_, prev);
#if (BOOST_EXECUTION_CONTEXT==1)
detail::data_t d{ ready_ctx };
#else
detail::data_t d{ ready_ctx, prev };
#endif
resume_( d);
}
@@ -342,31 +288,6 @@ context::yield() noexcept {
get_scheduler()->yield( context::active() );
}
#if (BOOST_EXECUTION_CONTEXT==1)
void
context::terminate() noexcept {
// protect for concurrent access
std::unique_lock< detail::spinlock > lk{ splk_ };
// mark as terminated
terminated_ = true;
// notify all waiting fibers
while ( ! wait_queue_.empty() ) {
context * ctx = & wait_queue_.front();
// remove fiber from wait-queue
wait_queue_.pop_front();
// notify scheduler
schedule( ctx);
}
BOOST_ASSERT( wait_queue_.empty() );
// release fiber-specific-data
for ( fss_data_t::value_type & data : fss_data_) {
data.second.do_cleanup();
}
fss_data_.clear();
// switch to another context
get_scheduler()->terminate( lk, this);
}
#else
boost::context::continuation
context::suspend_with_cc() noexcept {
context * prev = this;
@@ -401,7 +322,6 @@ context::terminate() noexcept {
// switch to another context
return get_scheduler()->terminate( lk, this);
}
#endif
bool
context::wait_until( std::chrono::steady_clock::time_point const& tp) noexcept {

View File

@@ -130,63 +130,6 @@ scheduler::~scheduler() {
main_ctx_ = nullptr;
}
#if (BOOST_EXECUTION_CONTEXT==1)
void
scheduler::dispatch() noexcept {
BOOST_ASSERT( context::active() == dispatcher_ctx_);
for (;;) {
if ( shutdown_) {
// notify sched-algorithm about termination
algo_->notify();
if ( worker_queue_.empty() ) {
break;
}
}
// release terminated context'
release_terminated_();
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
// get context' from remote ready-queue
remote_ready2ready_();
#endif
// get sleeping context'
sleep2ready_();
// get next ready context
context * ctx = algo_->pick_next();
if ( nullptr != ctx) {
BOOST_ASSERT( ctx->is_resumable() );
BOOST_ASSERT( ! ctx->ready_is_linked() );
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
BOOST_ASSERT( ! ctx->remote_ready_is_linked() );
#endif
BOOST_ASSERT( ! ctx->sleep_is_linked() );
BOOST_ASSERT( ! ctx->terminated_is_linked() );
// no test for '! ctx->wait_is_linked()' because
// context is registered in wait-queue of sync. primitives
// via wait_for()/wait_until()
// push dispatcher-context to ready-queue
// so that ready-queue never becomes empty
ctx->resume( dispatcher_ctx_.get() );
BOOST_ASSERT( context::active() == dispatcher_ctx_.get() );
} else {
// no ready context, wait till signaled
// set deadline to highest value
std::chrono::steady_clock::time_point suspend_time =
(std::chrono::steady_clock::time_point::max)();
// get lowest deadline from sleep-queue
sleep_queue_type::iterator i = sleep_queue_.begin();
if ( sleep_queue_.end() != i) {
suspend_time = i->tp_;
}
// no ready context, wait till signaled
algo_->suspend_until( suspend_time);
}
}
// release termianted context'
release_terminated_();
// return to main-context
main_ctx_->resume();
}
#else
boost::context::continuation
scheduler::dispatch() noexcept {
BOOST_ASSERT( context::active() == dispatcher_ctx_);
@@ -242,7 +185,6 @@ scheduler::dispatch() noexcept {
// return to main-context
return main_ctx_->suspend_with_cc();
}
#endif
void
scheduler::schedule( context * ctx) noexcept {
@@ -287,34 +229,6 @@ scheduler::schedule_from_remote( context * ctx) noexcept {
}
#endif
#if (BOOST_EXECUTION_CONTEXT==1)
void
scheduler::terminate( detail::spinlock_lock & lk, context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
BOOST_ASSERT( context::active() == ctx);
BOOST_ASSERT( this == ctx->get_scheduler() );
BOOST_ASSERT( ctx->is_context( type::worker_context) );
BOOST_ASSERT( ! ctx->is_context( type::pinned_context) );
BOOST_ASSERT( ! ctx->ready_is_linked() );
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
BOOST_ASSERT( ! ctx->remote_ready_is_linked() );
#endif
BOOST_ASSERT( ! ctx->sleep_is_linked() );
BOOST_ASSERT( ! ctx->terminated_is_linked() );
BOOST_ASSERT( ! ctx->wait_is_linked() );
BOOST_ASSERT( ctx->wait_queue_.empty() );
// store the terminated fiber in the terminated-queue
// the dispatcher-context will call
// intrusive_ptr_release( ctx);
ctx->terminated_link( terminated_queue_);
// remove from the worker-queue
ctx->worker_unlink();
// release lock
lk.unlock();
// resume another fiber
algo_->pick_next()->resume();
}
#else
boost::context::continuation
scheduler::terminate( detail::spinlock_lock & lk, context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
@@ -341,7 +255,6 @@ scheduler::terminate( detail::spinlock_lock & lk, context * ctx) noexcept {
// resume another fiber
return algo_->pick_next()->suspend_with_cc();
}
#endif
void
scheduler::yield( context * ctx) noexcept {