X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FScheduler.cc;h=b6485b1fa0770aa06d75a4250852d20d2f498743;hb=0327b3f303ea2a61d44a30bfaac022874dcf2a0d;hp=65b3f0998501478ca207859fd6dd94a6011c9df9;hpb=31d85cd6b8e03c5ecc924ca8892906be1bab702f;p=senf.git diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 65b3f09..b6485b1 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -79,26 +79,15 @@ #include #include #include "Utils/Exception.hh" -#include "Utils/MicroTime.hh" static const int EPollInitialSize = 16; #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -prefix_ senf::Scheduler::Scheduler & senf::Scheduler::instance() -{ - static Scheduler instance; - return instance; -} - -prefix_ void senf::Scheduler::timeout(unsigned long timeout, TimerCallback const & cb) -{ - timerQueue_.push(TimerSpec(now()+1000*timeout,cb)); -} - prefix_ senf::Scheduler::Scheduler() - : epollFd_(epoll_create(EPollInitialSize)) + : timerIdCounter_(0), epollFd_ (epoll_create(EPollInitialSize)), terminate_(false), + eventTime_(0) { if (epollFd_<0) throw SystemException(errno); @@ -165,30 +154,45 @@ prefix_ int senf::Scheduler::EventSpec::epollMask() prefix_ void senf::Scheduler::process() { terminate_ = false; - while (! terminate_) { - - MicroTime timeNow = now(); - while ( ! timerQueue_.empty() && timerQueue_.top().timeout <= timeNow ) { - timerQueue_.top().cb(); + eventTime_ = ClockService::now(); + while (! terminate_ && ( ! timerQueue_.empty() || ! fdTable_.empty())) { + while ( ! timerQueue_.empty() && timerQueue_.top()->second.timeout <= eventTime_ ) { + TimerMap::iterator i (timerQueue_.top()); + if (! i->second.canceled) + i->second.cb(); + timerMap_.erase(i); timerQueue_.pop(); } + if (terminate_) return; - int timeout = timerQueue_.empty() ? -1 : int((timerQueue_.top().timeout - timeNow)/1000); + int timeout (-1); + if (! timerQueue_.empty()) { + ClockService::clock_type delta ( + (timerQueue_.top()->second.timeout - eventTime_)/1000000UL); + timeout = delta < 0 ? 0 : delta; + } + + ///\fixme Handle more than one epoll_event per call struct epoll_event ev; int events = epoll_wait(epollFd_, &ev, 1, timeout); if (events<0) - // Hmm ... man epoll says, it will NOT return with EINTR. I hope, this is true :-) - throw SystemException(errno); - 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(); + 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); BOOST_ASSERT (i != fdTable_.end() ); - // \todo Make this more efficient. Instead of copying the event-spec it should be - // revalidated by monitoring add/remove calls EventSpec spec (i->second); unsigned extraFlags (0); @@ -233,4 +237,5 @@ prefix_ void senf::Scheduler::process() // indent-tabs-mode: nil // ispell-local-dictionary: "american" // compile-command: "scons -u test" +// comment-column: 40 // End: