2
0
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:
Oliver Kowalke
2015-09-16 21:07:26 +02:00
parent a8e90aedb8
commit dd0e1d1893
3 changed files with 78 additions and 5 deletions

View 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

View File

@@ -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 *);

View File

@@ -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();