namespace boost {
namespace fibers {
-context *
-scheduler::get_next_() noexcept {
- context * ctx = algo_->pick_next();
- //BOOST_ASSERT( nullptr == ctx);
- //BOOST_ASSERT( this == ctx->get_scheduler() );
- return ctx;
-}
-
void
scheduler::release_terminated_() noexcept {
- terminated_queue_t::iterator e( terminated_queue_.end() );
- for ( terminated_queue_t::iterator i( terminated_queue_.begin() );
- i != e;) {
- context * ctx = & ( * i);
- BOOST_ASSERT( ! ctx->is_context( type::main_context) );
- BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) );
- //BOOST_ASSERT( ctx->worker_is_linked() );
- BOOST_ASSERT( ctx->is_terminated() );
+ while ( ! terminated_queue_.empty() ) {
+ context * ctx = & terminated_queue_.front();
+ terminated_queue_.pop_front();
+ BOOST_ASSERT( ctx->is_context( type::worker_context) );
+ BOOST_ASSERT( ! ctx->is_context( type::pinned_context) );
+ BOOST_ASSERT( this == ctx->get_scheduler() );
+ BOOST_ASSERT( ctx->is_resumable() );
+ BOOST_ASSERT( ! ctx->worker_is_linked() );
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() );
- // remove context from worker-queue
- ctx->worker_unlink();
- // remove context from terminated-queue
- i = terminated_queue_.erase( i);
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ BOOST_ASSERT( ctx->wait_queue_.empty() );
+ BOOST_ASSERT( ctx->terminated_);
// if last reference, e.g. fiber::join() or fiber::detach()
// have been already called, this will call ~context(),
// the context is automatically removeid from worker-queue
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
void
scheduler::remote_ready2ready_() noexcept {
- context * ctx = nullptr;
+ remote_ready_queue_type tmp;
+ detail::spinlock_lock lk{ remote_ready_splk_ };
+ remote_ready_queue_.swap( tmp);
+ lk.unlock();
// get context from remote ready-queue
- while ( nullptr != ( ctx = remote_ready_queue_.pop() ) ) {
+ while ( ! tmp.empty() ) {
+ context * ctx = & tmp.front();
+ tmp.pop_front();
// store context in local queues
- set_ready( ctx);
+ schedule( ctx);
}
}
#endif
// move context which the deadline has reached
// to ready-queue
// sleep-queue is sorted (ascending)
- std::chrono::steady_clock::time_point now =
- std::chrono::steady_clock::now();
- sleep_queue_t::iterator e = sleep_queue_.end();
- for ( sleep_queue_t::iterator i = sleep_queue_.begin(); i != e;) {
+ std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+ sleep_queue_type::iterator e = sleep_queue_.end();
+ for ( sleep_queue_type::iterator i = sleep_queue_.begin(); i != e;) {
context * ctx = & ( * i);
+ // dipatcher context must never be pushed to sleep-queue
BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) );
- //BOOST_ASSERT( main_ctx_ == ctx || ctx->worker_is_linked() );
- BOOST_ASSERT( ! ctx->is_terminated() );
+ BOOST_ASSERT( main_ctx_ == ctx || ctx->worker_is_linked() );
BOOST_ASSERT( ! ctx->ready_is_linked() );
- BOOST_ASSERT( ctx->sleep_is_linked() );
- // ctx->wait_is_linked() might return true if
- // context is waiting in time_mutex::try_lock_until()
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ BOOST_ASSERT( ! ctx->remote_ready_is_linked() );
+#endif
+ BOOST_ASSERT( ! ctx->terminated_is_linked() );
+ // no test for wait-queue because ctx
+ // might be waiting in time_mutex::try_lock_until()
// set fiber to state_ready if deadline was reached
if ( ctx->tp_ <= now) {
// remove context from sleep-queue
BOOST_ASSERT( nullptr != main_ctx_);
BOOST_ASSERT( nullptr != dispatcher_ctx_.get() );
BOOST_ASSERT( context::active() == main_ctx_);
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ // protect for concurrent access
+ // required because main-context might have been
+ // signaled from remote and algorithm::notify()
+ // must be called fro mremote too
+ detail::spinlock_lock lk{ remote_ready_splk_ };
+#endif
// signal dispatcher-context termination
shutdown_ = true;
// resume pending fibers
// no context' in worker-queue
BOOST_ASSERT( worker_queue_.empty() );
BOOST_ASSERT( terminated_queue_.empty() );
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
-#endif
BOOST_ASSERT( sleep_queue_.empty() );
// set active context to nullptr
context::reset_active();
#if (BOOST_EXECUTION_CONTEXT==1)
void
scheduler::dispatch() noexcept {
-#else
-boost::context::execution_context< detail::data_t * >
-scheduler::dispatch() noexcept {
-#endif
BOOST_ASSERT( context::active() == dispatcher_ctx_);
for (;;) {
- bool no_worker = worker_queue_.empty();
if ( shutdown_) {
// notify sched-algorithm about termination
algo_->notify();
- if ( no_worker) {
+ if ( worker_queue_.empty() ) {
break;
}
}
// get sleeping context'
sleep2ready_();
// get next ready context
- context * ctx = get_next_();
+ 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() );
std::chrono::steady_clock::time_point suspend_time =
(std::chrono::steady_clock::time_point::max)();
// get lowest deadline from sleep-queue
- sleep_queue_t::iterator i = sleep_queue_.begin();
+ sleep_queue_type::iterator i = sleep_queue_.begin();
if ( sleep_queue_.end() != i) {
suspend_time = i->tp_;
}
// release termianted context'
release_terminated_();
// return to main-context
-#if (BOOST_EXECUTION_CONTEXT==1)
main_ctx_->resume();
+}
#else
- return main_ctx_->suspend_with_cc();
+boost::context::continuation
+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
+ return main_ctx_->suspend_with_cc();
}
+#endif
void
-scheduler::set_ready( context * ctx) noexcept {
+scheduler::schedule( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
- BOOST_ASSERT( ! ctx->is_terminated() );
- // we do not test for wait-queue because
- // context::wait_is_linked() is not synchronized
- // with other threads
- //BOOST_ASSERT( active_ctx->wait_is_linked() );
+ BOOST_ASSERT( ! ctx->ready_is_linked() );
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ BOOST_ASSERT( ! ctx->remote_ready_is_linked() );
+#endif
+ BOOST_ASSERT( ! ctx->terminated_is_linked() );
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
// remove context ctx from sleep-queue
// (might happen if blocked in timed_mutex::try_lock_until())
if ( ctx->sleep_is_linked() ) {
// unlink it from sleep-queue
ctx->sleep_unlink();
}
- // for safety unlink it from ready-queue
- ctx->ready_unlink();
// push new context to ready-queue
algo_->awakened( ctx);
}
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
void
-scheduler::set_remote_ready( context * ctx) noexcept {
+scheduler::schedule_from_remote( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
+ // another thread might signal the main-context of this thread
BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) );
BOOST_ASSERT( this == ctx->get_scheduler() );
- // another thread might signal the main-context
- // from this thread
- //BOOST_ASSERT( ! ctx->is_context( type::main_context) );
- // context ctx might in wait-/ready-/sleep-queue
- // we do not test this in this function
- // scheduler::dispatcher() has to take care
+ BOOST_ASSERT( ! ctx->ready_is_linked() );
+ BOOST_ASSERT( ! ctx->remote_ready_is_linked() );
+ BOOST_ASSERT( ! ctx->sleep_is_linked() );
+ BOOST_ASSERT( ! ctx->terminated_is_linked() );
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ // protect for concurrent access
+ detail::spinlock_lock lk{ remote_ready_splk_ };
+ BOOST_ASSERT( ! shutdown_);
+ BOOST_ASSERT( nullptr != main_ctx_);
+ BOOST_ASSERT( nullptr != dispatcher_ctx_.get() );
// push new context to remote ready-queue
- remote_ready_queue_.push( ctx);
+ ctx->remote_ready_link( remote_ready_queue_);
// notify scheduler
algo_->notify();
}
#if (BOOST_EXECUTION_CONTEXT==1)
void
-scheduler::set_terminated( context * active_ctx) noexcept {
-#else
-boost::context::execution_context< detail::data_t * >
-scheduler::set_terminated( context * active_ctx) noexcept {
+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( nullptr != active_ctx);
- BOOST_ASSERT( context::active() == active_ctx);
- BOOST_ASSERT( ! active_ctx->is_context( type::main_context) );
- BOOST_ASSERT( ! active_ctx->is_context( type::dispatcher_context) );
- //BOOST_ASSERT( active_ctx->worker_is_linked() );
- BOOST_ASSERT( active_ctx->is_terminated() );
- BOOST_ASSERT( ! active_ctx->ready_is_linked() );
- BOOST_ASSERT( ! active_ctx->sleep_is_linked() );
- BOOST_ASSERT( ! active_ctx->wait_is_linked() );
+ 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
+ // the dispatcher-context will call
// intrusive_ptr_release( ctx);
- active_ctx->terminated_link( terminated_queue_);
+ ctx->terminated_link( terminated_queue_);
+ // remove from the worker-queue
+ ctx->worker_unlink();
+ // release lock
+ lk.unlock();
// resume another fiber
-#if (BOOST_EXECUTION_CONTEXT==1)
- get_next_()->resume();
+ algo_->pick_next()->resume();
+}
#else
- return get_next_()->suspend_with_cc();
+boost::context::continuation
+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
+ return algo_->pick_next()->suspend_with_cc();
}
+#endif
void
-scheduler::yield( context * active_ctx) noexcept {
- BOOST_ASSERT( nullptr != active_ctx);
- //BOOST_ASSERT( main_ctx_ == active_ctx || dispatcher_ctx_.get() == active_ctx || active_ctx->worker_is_linked() );
- BOOST_ASSERT( ! active_ctx->is_terminated() );
- BOOST_ASSERT( ! active_ctx->ready_is_linked() );
- BOOST_ASSERT( ! active_ctx->sleep_is_linked() );
- // we do not test for wait-queue because
- // context::wait_is_linked() is not sychronized
- // with other threads
- // defer passing active context to set_ready()
- // in work-sharing context (multiple threads read
- // from one ready-queue) the context must be
- // already suspended until another thread resumes it
- // (== maked as ready)
+scheduler::yield( context * ctx) noexcept {
+ BOOST_ASSERT( nullptr != ctx);
+ BOOST_ASSERT( context::active() == ctx);
+ BOOST_ASSERT( ctx->is_context( type::worker_context) || ctx->is_context( type::main_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() );
// resume another fiber
- get_next_()->resume( active_ctx);
+ algo_->pick_next()->resume( ctx);
}
bool
-scheduler::wait_until( context * active_ctx,
+scheduler::wait_until( context * ctx,
std::chrono::steady_clock::time_point const& sleep_tp) noexcept {
- BOOST_ASSERT( nullptr != active_ctx);
- //BOOST_ASSERT( main_ctx_ == active_ctx || dispatcher_ctx_.get() == active_ctx || active_ctx->worker_is_linked() );
- BOOST_ASSERT( ! active_ctx->is_terminated() );
- // if the active-fiber running in this thread calls
- // condition_variable:wait() and code in another thread calls
- // condition_variable::notify_one(), it might happen that the
- // other thread pushes the fiber to remote ready-queue first
- // the dispatcher-context migh have been moved the fiber from
- // the remote ready-queue to the local ready-queue
- // so we do not check
- //BOOST_ASSERT( active_ctx->ready_is_linked() );
- BOOST_ASSERT( ! active_ctx->sleep_is_linked() );
- // active_ctx->wait_is_linked() might return true
- // if context was locked inside timed_mutex::try_lock_until()
- // context::wait_is_linked() is not sychronized
- // with other threads
- // push active context to sleep-queue
- active_ctx->tp_ = sleep_tp;
- active_ctx->sleep_link( sleep_queue_);
+ BOOST_ASSERT( nullptr != ctx);
+ BOOST_ASSERT( context::active() == ctx);
+ BOOST_ASSERT( ctx->is_context( type::worker_context) || ctx->is_context( type::main_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() );
+ ctx->tp_ = sleep_tp;
+ ctx->sleep_link( sleep_queue_);
// resume another context
- get_next_()->resume();
+ algo_->pick_next()->resume();
// context has been resumed
// check if deadline has reached
return std::chrono::steady_clock::now() < sleep_tp;
}
bool
-scheduler::wait_until( context * active_ctx,
+scheduler::wait_until( context * ctx,
std::chrono::steady_clock::time_point const& sleep_tp,
detail::spinlock_lock & lk) noexcept {
- BOOST_ASSERT( nullptr != active_ctx);
- //BOOST_ASSERT( main_ctx_ == active_ctx || dispatcher_ctx_.get() == active_ctx || active_ctx->worker_is_linked() );
- BOOST_ASSERT( ! active_ctx->is_terminated() );
- // if the active-fiber running in this thread calls
- // condition_variable:wait() and code in another thread calls
- // condition_variable::notify_one(), it might happen that the
- // other thread pushes the fiber to remote ready-queue first
- // the dispatcher-context migh have been moved the fiber from
- // the remote ready-queue to the local ready-queue
- // so we do not check
- //BOOST_ASSERT( active_ctx->ready_is_linked() );
- BOOST_ASSERT( ! active_ctx->sleep_is_linked() );
- // active_ctx->wait_is_linked() might return true
+ BOOST_ASSERT( nullptr != ctx);
+ BOOST_ASSERT( context::active() == ctx);
+ BOOST_ASSERT( ctx->is_context( type::worker_context) || ctx->is_context( type::main_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() );
+ // ctx->wait_is_linked() might return true
// if context was locked inside timed_mutex::try_lock_until()
- // context::wait_is_linked() is not sychronized
- // with other threads
// push active context to sleep-queue
- active_ctx->tp_ = sleep_tp;
- active_ctx->sleep_link( sleep_queue_);
+ ctx->tp_ = sleep_tp;
+ ctx->sleep_link( sleep_queue_);
// resume another context
- get_next_()->resume( lk);
+ algo_->pick_next()->resume( lk);
// context has been resumed
// check if deadline has reached
return std::chrono::steady_clock::now() < sleep_tp;
void
scheduler::suspend() noexcept {
// resume another context
- get_next_()->resume();
+ algo_->pick_next()->resume();
}
void
scheduler::suspend( detail::spinlock_lock & lk) noexcept {
// resume another context
- get_next_()->resume( lk);
+ algo_->pick_next()->resume( lk);
}
bool
}
void
-scheduler::attach_main_context( context * main_ctx) noexcept {
- BOOST_ASSERT( nullptr != main_ctx);
+scheduler::attach_main_context( context * ctx) noexcept {
+ BOOST_ASSERT( nullptr != ctx);
// main-context represents the execution context created
// by the system, e.g. main()- or thread-context
// should not be in worker-queue
- main_ctx_ = main_ctx;
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- main_ctx_->scheduler_.store( this, std::memory_order_relaxed);
-#else
+ main_ctx_ = ctx;
main_ctx_->scheduler_ = this;
-#endif
}
void
-scheduler::attach_dispatcher_context( intrusive_ptr< context > dispatcher_ctx) noexcept {
- BOOST_ASSERT( dispatcher_ctx);
+scheduler::attach_dispatcher_context( intrusive_ptr< context > ctx) noexcept {
+ BOOST_ASSERT( ctx);
// dispatcher context has to handle
// - remote ready context'
// - sleeping context'
// - extern event-loops
// - suspending the thread if ready-queue is empty (waiting on external event)
// should not be in worker-queue
- dispatcher_ctx_.swap( dispatcher_ctx);
+ dispatcher_ctx_.swap( ctx);
// add dispatcher-context to ready-queue
// so it is the first element in the ready-queue
// if the main context tries to suspend the first time
// the dispatcher-context is resumed and
// scheduler::dispatch() is executed
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- dispatcher_ctx_->scheduler_.store( this, std::memory_order_relaxed);
-#else
dispatcher_ctx_->scheduler_ = this;
-#endif
algo_->awakened( dispatcher_ctx_.get() );
}
void
scheduler::attach_worker_context( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
+ BOOST_ASSERT( nullptr == ctx->get_scheduler() );
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->worker_is_linked() );
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- std::atomic_thread_fence( std::memory_order_acquire);
- BOOST_ASSERT( nullptr == ctx->scheduler_.load( std::memory_order_relaxed) );
- ctx->scheduler_.store( this, std::memory_order_relaxed);
-#else
- BOOST_ASSERT( nullptr == ctx->scheduler_);
- ctx->scheduler_ = this;
-#endif
ctx->worker_link( worker_queue_);
+ ctx->scheduler_ = this;
}
void
scheduler::detach_worker_context( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
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_is_linked() );
+ BOOST_ASSERT( ctx->worker_is_linked() );
BOOST_ASSERT( ! ctx->is_context( type::pinned_context) );
ctx->worker_unlink();
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- ctx->scheduler_.store( nullptr, std::memory_order_relaxed);
- std::atomic_thread_fence( std::memory_order_release);
-#else
ctx->scheduler_ = nullptr;
-#endif
}
}}