X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FScheduler.cc;h=adbb6a6b5f0fe5d3101084f4ee4f081973a23acb;hb=82ad2ed94c12c3e53097fef92978de8c28239fab;hp=b6485b1fa0770aa06d75a4250852d20d2f498743;hpb=0327b3f303ea2a61d44a30bfaac022874dcf2a0d;p=senf.git diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index b6485b1..adbb6a6 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -78,7 +78,7 @@ // Custom includes #include #include -#include "Utils/Exception.hh" +#include "../Utils/Exception.hh" static const int EPollInitialSize = 16; @@ -155,40 +155,57 @@ prefix_ void senf::Scheduler::process() { terminate_ = false; eventTime_ = ClockService::now(); - while (! terminate_ && ( ! timerQueue_.empty() || ! fdTable_.empty())) { - while ( ! timerQueue_.empty() && timerQueue_.top()->second.timeout <= eventTime_ ) { + while (! terminate_) { + + // Since a callback may have disabled further timers, we need to check for canceled timeouts + // again. + + while (! timerQueue_.empty()) { TimerMap::iterator i (timerQueue_.top()); if (! i->second.canceled) - i->second.cb(); + break; timerMap_.erase(i); timerQueue_.pop(); } - if (terminate_) - return; - int timeout (-1); - if (! timerQueue_.empty()) { + if (timerQueue_.empty()) { + if (fdTable_.empty()) + break; + } + else { ClockService::clock_type delta ( (timerQueue_.top()->second.timeout - eventTime_)/1000000UL); timeout = delta < 0 ? 0 : delta; } - ///\fixme Handle more than one epoll_event per call + ///\todo Handle more than one epoll_event per call struct epoll_event ev; int events = epoll_wait(epollFd_, &ev, 1, timeout); if (events<0) - // even though 'man epoll' does not mention EINTR the reality is different ... if (errno != EINTR) throw SystemException(errno); - /// \fixme Fix unneeded timer delays - // Hmm ... I remember, I purposely moved the timeout-handlers to the loop top ... but why? - // This delays possible time-critical handlers even further ... - eventTime_ = ClockService::now(); + + // We always run event handlers. This is important, even if a file-descriptor is signaled + // since some descriptors (e.g. real files) will *always* be ready and we still may want to + // handle timers. + // Time handlers are run before file events to not delay them unnecessarily. + + while (! timerQueue_.empty()) { + TimerMap::iterator i (timerQueue_.top()); + if (i->second.canceled) + ; + else if (i->second.timeout <= eventTime_) + i->second.cb(); + else + break; + timerQueue_.pop(); + timerMap_.erase(i); + } + if (events <= 0) - // Timeout .. the handler will be run when going back to the loop top continue; FdTable::iterator i = fdTable_.find(ev.data.fd); @@ -226,6 +243,15 @@ prefix_ void senf::Scheduler::process() } } +/////////////////////////////////////////////////////////////////////////// +// senf::SchedulerLogTimeSource + +prefix_ boost::posix_time::ptime senf::SchedulerLogTimeSource::operator()() + const +{ + return ClockService::abstime(Scheduler::instance().eventTime()); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_