void scheduler::set_terminated( context * active_ctx) noexcept { #else boost::context::execution_context< detail::data_t * > scheduler::set_terminated( context * active_ctx) noexcept { #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() ); // store the terminated fiber in the terminated-queue // the dispatcher-context will call // intrusive_ptr_release( ctx); active_ctx->terminated_link( terminated_queue_); // resume another fiber #if (BOOST_EXECUTION_CONTEXT==1) get_next_()->resume(); #else return get_next_()->suspend_with_cc(); #endif }
bool scheduler::wait_until( context * active_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 // 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_); // resume another context get_next_()->resume( lk); // context has been resumed // check if deadline has reached return std::chrono::steady_clock::now() < sleep_tp; }
void Player::EnqueueNext() { if (!get_next_.empty()) { QString next = get_next_().path(); LOG("Player") << "Getting next: " << next; media_.enqueue(next); } }
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) { break; } } // release terminated context' release_terminated_(); // get context' from remote ready-queue remote_ready2ready_(); // get sleeping context' sleep2ready_(); // get next ready context context * ctx = get_next_(); if ( nullptr != ctx) { // 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_t::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 #if (BOOST_EXECUTION_CONTEXT==1) main_ctx_->resume(); #else return main_ctx_->suspend_with_cc(); #endif }
void Player::Play() { if (!file_active_) { if (!get_next_.empty()) PlayFile(get_next_()); } else { LOG("Player") << "Play"; media_.play(); } }
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) // resume another fiber get_next_()->resume( active_ctx); }
void scheduler::suspend( detail::spinlock_lock & lk) noexcept { // resume another context get_next_()->resume( lk); }
void scheduler::suspend() noexcept { // resume another context get_next_()->resume(); }