mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-17 13:42:21 +00:00
add autoreset_event for waling up dispatcher context
- dispatcher waits on autoreset_event if ready-queue is empty - autoreset_event is set if a ready context is pushed to the ready-queue
This commit is contained in:
60
include/boost/fiber/detail/autoreset_event.hpp
Normal file
60
include/boost/fiber/detail/autoreset_event.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
// 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_AUTORESET_EVENT_H
|
||||
#define BOOST_FIBERS_DETAIL_AUTORESET_EVENT_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
class autoreset_event {
|
||||
private:
|
||||
std::mutex mtx_;
|
||||
std::condition_variable cnd_;
|
||||
bool flag_;
|
||||
|
||||
public:
|
||||
autoreset_event() :
|
||||
mtx_(), cnd_(), flag_( false) {
|
||||
}
|
||||
|
||||
autoreset_event( autoreset_event const&) = delete;
|
||||
autoreset_event & operator=( autoreset_event const&) = delete;
|
||||
|
||||
void set() {
|
||||
std::unique_lock< std::mutex > lk( mtx_);
|
||||
flag_ = true;
|
||||
lk.unlock();
|
||||
cnd_.notify_all();
|
||||
}
|
||||
|
||||
void reset( std::chrono::steady_clock::time_point const& time_point) {
|
||||
std::unique_lock< std::mutex > lk( mtx_);
|
||||
cnd_.wait_until( lk, time_point, [=](){ return flag_; });
|
||||
flag_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_AUTORESET_EVENT_H
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
#include <boost/fiber/context.hpp>
|
||||
#include <boost/fiber/detail/autoreset_event.hpp>
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
@@ -38,6 +39,7 @@ private:
|
||||
ready_queue_t ready_queue_;
|
||||
terminated_queue_t terminated_queue_;
|
||||
bool shutdown_;
|
||||
detail::autoreset_event ready_queue_ev_;
|
||||
|
||||
void resume_( context *, context *);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include "boost/fiber/scheduler.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include "boost/fiber/context.hpp"
|
||||
@@ -35,9 +37,11 @@ scheduler::resume_( context * actx, context * ctx) {
|
||||
|
||||
context *
|
||||
scheduler::get_next_() noexcept {
|
||||
BOOST_ASSERT( ! ready_queue_.empty() );
|
||||
context * ctx = & ready_queue_.front();
|
||||
ready_queue_.pop_front();
|
||||
context * ctx( nullptr);
|
||||
if ( ! ready_queue_.empty() ) {
|
||||
ctx = & ready_queue_.front();
|
||||
ready_queue_.pop_front();
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -57,7 +61,8 @@ scheduler::scheduler() noexcept :
|
||||
dispatcher_ctx_(),
|
||||
ready_queue_(),
|
||||
terminated_queue_(),
|
||||
shutdown_( false) {
|
||||
shutdown_( false),
|
||||
ready_queue_ev_() {
|
||||
}
|
||||
|
||||
scheduler::~scheduler() noexcept {
|
||||
@@ -99,7 +104,13 @@ void
|
||||
scheduler::dispatch() {
|
||||
while ( ! shutdown_) {
|
||||
release_terminated_();
|
||||
auto ctx = get_next_();
|
||||
context * ctx( nullptr);
|
||||
// loop till we get next ready context
|
||||
while ( nullptr == ( ctx = get_next_() ) ) {
|
||||
// no ready context, wait till signaled
|
||||
ready_queue_ev_.reset(
|
||||
(std::chrono::steady_clock::time_point::max)());
|
||||
}
|
||||
// push dispatcher context to ready-queue
|
||||
// so that ready-queue never becomes empty
|
||||
auto active_ctx = context::active();
|
||||
|
||||
Reference in New Issue
Block a user