2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-16 13:22:17 +00:00

add support for signaling a context as ready

This commit is contained in:
Oliver Kowalke
2015-09-19 16:19:02 +02:00
parent 59946d4426
commit 943e21e69b
4 changed files with 52 additions and 3 deletions

View File

@@ -255,6 +255,8 @@ public:
bool wait_until( std::chrono::steady_clock::time_point const&) noexcept;
void set_ready( context *) noexcept;
bool is_main_context() const noexcept {
return 0 != ( flags_ & flag_main_context);
}

View File

@@ -16,6 +16,7 @@
#include <boost/fiber/context.hpp>
#include <boost/fiber/detail/autoreset_event.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/spinlock.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -54,10 +55,12 @@ private:
context * main_ctx_;
intrusive_ptr< context > dispatcher_ctx_;
ready_queue_t ready_queue_;
ready_queue_t remote_ready_queue_;
sleep_queue_t sleep_queue_;
terminated_queue_t terminated_queue_;
bool shutdown_;
detail::autoreset_event ready_queue_ev_;
detail::spinlock remote_ready_splk_;
void resume_( context *, context *);
@@ -83,6 +86,8 @@ public:
void set_ready( context *) noexcept;
void set_remote_ready( context *) noexcept;
void set_terminated( context *) noexcept;
void yield( context *) noexcept;

View File

@@ -171,6 +171,22 @@ context::wait_until( std::chrono::steady_clock::time_point const& tp) noexcept {
return scheduler_->wait_until( this, tp);
}
void
context::set_ready( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
BOOST_ASSERT( this != ctx);
// FIXME: comparing scheduler address' must be synchronized?
// what if ctx is migrated between threads
// (other scheduler assigned)
if ( scheduler_ == ctx->scheduler_) {
// local
scheduler_->set_ready( ctx);
} else {
// remote
scheduler_->set_remote_ready( ctx);
}
}
bool
context::wait_is_linked() {
return wait_hook_.is_linked();

View File

@@ -7,6 +7,7 @@
#include "boost/fiber/scheduler.hpp"
#include <chrono>
#include <mutex>
#include <boost/assert.hpp>
@@ -88,9 +89,11 @@ scheduler::scheduler() noexcept :
main_ctx_( nullptr),
dispatcher_ctx_(),
ready_queue_(),
remote_ready_queue_(),
terminated_queue_(),
shutdown_( false),
ready_queue_ev_() {
ready_queue_ev_(),
remote_ready_splk_() {
}
scheduler::~scheduler() noexcept {
@@ -135,11 +138,19 @@ scheduler::dispatch() {
release_terminated_();
// get sleeping context'
woken_up_();
// protect for concurrent access
std::unique_lock< detail::spinlock > lk( remote_ready_splk_);
// get from remote ready-queue
ready_queue_.splice( ready_queue_.end(), remote_ready_queue_);
lk.unlock();
context * ctx = nullptr;
// loop till we get next ready context
while ( nullptr == ( ctx = get_next_() ) ) {
// TODO: move context' from remote ready-queue to local ready-queue
//
// protect for concurrent access
lk.lock();
// get from remote ready-queue
ready_queue_.splice( ready_queue_.end(), remote_ready_queue_);
lk.unlock();
// no ready context, wait till signaled
// set deadline to highest value
std::chrono::steady_clock::time_point tp =
@@ -181,6 +192,21 @@ scheduler::set_ready( context * ctx) noexcept {
ready_queue_.push_back( * ctx);
}
void
scheduler::set_remote_ready( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
BOOST_ASSERT( ! ctx->is_terminated() );
BOOST_ASSERT( ! ctx->ready_is_linked() );
BOOST_ASSERT( ! ctx->sleep_is_linked() );
BOOST_ASSERT( ! ctx->wait_is_linked() );
// set the scheduler for new context
ctx->set_scheduler( this);
// protect for concurrent access
std::unique_lock< detail::spinlock > lk( remote_ready_splk_);
// push new context to remote ready-queue
remote_ready_queue_.push_back( * ctx);
}
void
scheduler::set_terminated( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);