X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FScheduler.cc;h=41708511e832a07ebdfef46756c4062709e9c221;hb=44c966bc9d744d0926cffd5184fdb77a62564c16;hp=9f222bfd789304d1f8347afb8c41e3fd62e10f1a;hpb=17e24d84603667395e9ffa786a9cdbb722bf9c1f;p=senf.git diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 9f222bf..4170851 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -54,7 +54,7 @@ static const int EPollInitialSize = 16; ///////////////////////////////cc.p//////////////////////////////////////// prefix_ senf::Scheduler::Scheduler() - : timerIdCounter_(0), epollFd_ (epoll_create(EPollInitialSize)), terminate_(false), + : files_(0), timerIdCounter_(0), epollFd_ (epoll_create(EPollInitialSize)), terminate_(false), eventTime_(0), eventEarly_(ClockService::milliseconds(11)), eventAdjust_(0) { if (epollFd_<0) @@ -120,8 +120,15 @@ prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMas ev.events = i->second.epollMask(); ev.data.fd = fd; - if (epoll_ctl(epollFd_, action, fd, &ev)<0) - throw SystemException(errno); + if (! i->second.file && epoll_ctl(epollFd_, action, fd, &ev) < 0) { + if (errno == EPERM) { + // Argh ... epoll does not support ordinary files :-( :-( + i->second.file = true; + ++ files_; + } + else + throwErrno("::epoll_ctl()"); + } } prefix_ void senf::Scheduler::do_remove(int fd, int eventMask) @@ -140,18 +147,21 @@ prefix_ void senf::Scheduler::do_remove(int fd, int eventMask) ev.data.fd = fd; int action (EPOLL_CTL_MOD); + bool file (i->second.file); if (ev.events==0) { action = EPOLL_CTL_DEL; - fdTable_.erase(i); + fdErase_.push_back(fd); } - if (epoll_ctl(epollFd_, action, fd, &ev)<0) - throw SystemException(errno); + if (! file && epoll_ctl(epollFd_, action, fd, &ev) < 0) + throwErrno("::epoll_ctl()"); + if (file) + -- files_; } prefix_ void senf::Scheduler::registerSigHandlers() { - for (unsigned signal; signal < sigHandlers_.size(); ++signal) + for (unsigned signal (1); signal < sigHandlers_.size(); ++signal) { if (sigHandlers_[signal]) { struct ::sigaction sa; sa.sa_sigaction = & Scheduler::sigHandler; @@ -162,6 +172,7 @@ prefix_ void senf::Scheduler::registerSigHandlers() if (::sigaction(signal, &sa, 0) < 0) throw SystemException(errno); } + } } prefix_ void senf::Scheduler::sigHandler(int signal, ::siginfo_t * siginfo, void *) @@ -204,15 +215,23 @@ prefix_ void senf::Scheduler::process() timerQueue_.pop(); } + for (FdEraseList::iterator i (fdErase_.begin()); i != fdErase_.end(); ++i) + fdTable_.erase(*i); + fdErase_.clear(); + int timeout (-1); - if (timerQueue_.empty()) { - if (fdTable_.empty()) - break; - } + if (files_ > 0) + timeout = 0; else { - ClockService::clock_type delta ( - (timerQueue_.top()->second.timeout - eventTime_ + eventAdjust_)/1000000UL); - timeout = delta < 0 ? 0 : delta; + if (timerQueue_.empty()) { + if (fdTable_.empty()) + break; + } + else { + ClockService::clock_type delta ( + (timerQueue_.top()->second.timeout - eventTime_ + eventAdjust_)/1000000UL); + timeout = delta < 0 ? 0 : delta; + } } ///\todo Handle more than one epoll_event per call @@ -244,11 +263,8 @@ prefix_ void senf::Scheduler::process() timerMap_.erase(i); } - if (events <= 0) - continue; - // Check the signal queue - if (ev.data.fd == sigpipe_[0]) { + if (events > 0 && ev.data.fd == sigpipe_[0]) { ::siginfo_t siginfo; if (::read(sigpipe_[0], &siginfo, sizeof(siginfo)) < int(sizeof(siginfo))) { // We ignore truncated records which may only occur if the signal @@ -261,37 +277,42 @@ prefix_ void senf::Scheduler::process() continue; } - FdTable::iterator i = fdTable_.find(ev.data.fd); - BOOST_ASSERT (i != fdTable_.end() ); - EventSpec spec (i->second); + for (FdTable::iterator i = fdTable_.begin(); i != fdTable_.end(); ++i) { + EventSpec & spec (i->second); - unsigned extraFlags (0); - if (ev.events & EPOLLHUP) extraFlags |= EV_HUP; - if (ev.events & EPOLLERR) extraFlags |= EV_ERR; + if (! (spec.file || (events > 0 && i->first == ev.data.fd))) + continue; + + unsigned extraFlags (0); + unsigned mask (spec.file ? spec.epollMask() : ev.events); - if (ev.events & EPOLLIN) { - BOOST_ASSERT(spec.cb_read); - spec.cb_read(EventId(EV_READ | extraFlags)); - } - else if (ev.events & EPOLLPRI) { - BOOST_ASSERT(spec.cb_prio); - spec.cb_prio(EventId(EV_PRIO | extraFlags)); - } - else if (ev.events & EPOLLOUT) { - BOOST_ASSERT(spec.cb_write); - spec.cb_write(EventId(EV_WRITE | extraFlags)); - } - else { - // This branch is only taken, if HUP or ERR is signaled but none of IN/OUT/PRI. - // In this case we will signal all registered callbacks. The callbacks must be - // prepared to be called multiple times if they are registered to more than - // one event. - if (spec.cb_write) - spec.cb_write(EventId(extraFlags)); - if (spec.cb_prio) - spec.cb_prio(EventId(extraFlags)); - if (spec.cb_read) - spec.cb_read(EventId(extraFlags)); + if (mask & EPOLLHUP) extraFlags |= EV_HUP; + if (mask & EPOLLERR) extraFlags |= EV_ERR; + + if (mask & EPOLLIN) { + BOOST_ASSERT(spec.cb_read); + spec.cb_read(EventId(EV_READ | extraFlags)); + } + else if (mask & EPOLLPRI) { + BOOST_ASSERT(spec.cb_prio); + spec.cb_prio(EventId(EV_PRIO | extraFlags)); + } + else if (mask & EPOLLOUT) { + BOOST_ASSERT(spec.cb_write); + spec.cb_write(EventId(EV_WRITE | extraFlags)); + } + else { + // This branch is only taken, if HUP or ERR is signaled but none of IN/OUT/PRI. + // In this case we will signal all registered callbacks. The callbacks must be + // prepared to be called multiple times if they are registered to more than + // one event. + if (spec.cb_write) + spec.cb_write(EventId(extraFlags)); + if (spec.cb_prio) + spec.cb_prio(EventId(extraFlags)); + if (spec.cb_read) + spec.cb_read(EventId(extraFlags)); + } } } }