X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FScheduler.cc;h=6aa249c467761040b4fc9f2704fb62d83b041a12;hb=84df23442e79b04a5c4e55a93f46a26b8abe4728;hp=c720c5509bc7953fcdffdae8ffd6171c8561bd79;hpb=9fabfe82429b675009a8109b03ccbd5e13f6ee0a;p=senf.git diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index c720c55..6aa249c 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -1,9 +1,9 @@ // $Id$ // // Copyright (C) 2006 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) -// Stefan Bund +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -23,9 +23,6 @@ /** \file \brief Scheduler non-inline non-template implementation - \idea Implement signal handling (See source for more discussion - about this) - \idea Multithreading support: To support multithreading, the static member Scheduler::instance() must return a thread-local value (that is Scheduler::instance() must allocate one Scheduler @@ -42,6 +39,7 @@ //#include "Scheduler.ih" // Custom includes +#include "../Utils/senfassert.hh" #include #include #include @@ -58,24 +56,24 @@ prefix_ senf::Scheduler::Scheduler() eventTime_(0), eventEarly_(ClockService::milliseconds(11)), eventAdjust_(0) { if (epollFd_<0) - throw SystemException(errno); + throw SystemException(); if (::pipe(sigpipe_) < 0) - throw SystemException(errno); + throw SystemException(); int flags (::fcntl(sigpipe_[1],F_GETFL)); if (flags < 0) - throw SystemException(errno); + throw SystemException(); flags |= O_NONBLOCK; if (::fcntl(sigpipe_[1], F_SETFL, flags) < 0) - throw SystemException(errno); + throw SystemException(); ::epoll_event ev; ::memset(&ev, 0, sizeof(ev)); ev.events = EV_READ; ev.data.fd = sigpipe_[0]; if (::epoll_ctl(epollFd_, EPOLL_CTL_ADD, sigpipe_[0], &ev) < 0) - throw SystemException(errno); + throw SystemException(); } prefix_ void senf::Scheduler::registerSignal(unsigned signal, SimpleCallback const & cb) @@ -104,12 +102,20 @@ prefix_ void senf::Scheduler::unregisterSignal(unsigned signal) prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMask) { + if (eventMask == 0) + return; + FdTable::iterator i (fdTable_.find(fd)); int action (EPOLL_CTL_MOD); if (i == fdTable_.end()) { action = EPOLL_CTL_ADD; i = fdTable_.insert(std::make_pair(fd, EventSpec())).first; } + if (i->second.epollMask() == 0) { + action = EPOLL_CTL_ADD; + fdErase_.erase( std::remove(fdErase_.begin(), fdErase_.end(), unsigned(fd)), + fdErase_.end() ); + } if (eventMask & EV_READ) i->second.cb_read = cb; if (eventMask & EV_PRIO) i->second.cb_prio = cb; @@ -127,12 +133,15 @@ prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMas ++ files_; } else - throwErrno("::epoll_ctl()"); + throw SystemException("::epoll_ctl()"); } } prefix_ void senf::Scheduler::do_remove(int fd, int eventMask) { + if (eventMask == 0) + return; + FdTable::iterator i (fdTable_.find(fd)); if (i == fdTable_.end()) return; @@ -150,18 +159,18 @@ prefix_ void senf::Scheduler::do_remove(int fd, int eventMask) bool file (i->second.file); if (ev.events==0) { action = EPOLL_CTL_DEL; - fdTable_.erase(i); + fdErase_.push_back(fd); } if (! file && epoll_ctl(epollFd_, action, fd, &ev) < 0) - throwErrno("::epoll_ctl()"); + throw SystemException("::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; @@ -170,8 +179,9 @@ prefix_ void senf::Scheduler::registerSigHandlers() if (signal == SIGCHLD) sa.sa_flags |= SA_NOCLDSTOP; if (::sigaction(signal, &sa, 0) < 0) - throw SystemException(errno); + throw SystemException(); } + } } prefix_ void senf::Scheduler::sigHandler(int signal, ::siginfo_t * siginfo, void *) @@ -214,6 +224,10 @@ 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 (files_ > 0) timeout = 0; @@ -238,7 +252,7 @@ prefix_ void senf::Scheduler::process() if (events<0) if (errno != EINTR) - throw SystemException(errno); + throw SystemException(); eventTime_ = ClockService::now(); @@ -258,11 +272,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 @@ -276,26 +287,27 @@ prefix_ void senf::Scheduler::process() } for (FdTable::iterator i = fdTable_.begin(); i != fdTable_.end(); ++i) { - EventSpec spec (i->second); - unsigned extraFlags (0); - unsigned events (spec.file ? spec.epollMask() : ev.events); + EventSpec & spec (i->second); - if (! (spec.file || i->first == ev.data.fd)) + if (! (spec.file || (events > 0 && i->first == ev.data.fd))) continue; - if (events & EPOLLHUP) extraFlags |= EV_HUP; - if (events & EPOLLERR) extraFlags |= EV_ERR; + unsigned extraFlags (0); + unsigned mask (spec.file ? spec.epollMask() : ev.events); + + if (mask & EPOLLHUP) extraFlags |= EV_HUP; + if (mask & EPOLLERR) extraFlags |= EV_ERR; - if (events & EPOLLIN) { - BOOST_ASSERT(spec.cb_read); + if (mask & EPOLLIN) { + SENF_ASSERT(spec.cb_read); spec.cb_read(EventId(EV_READ | extraFlags)); } - else if (events & EPOLLPRI) { - BOOST_ASSERT(spec.cb_prio); + else if (mask & EPOLLPRI) { + SENF_ASSERT(spec.cb_prio); spec.cb_prio(EventId(EV_PRIO | extraFlags)); } - else if (events & EPOLLOUT) { - BOOST_ASSERT(spec.cb_write); + else if (mask & EPOLLOUT) { + SENF_ASSERT(spec.cb_write); spec.cb_write(EventId(EV_WRITE | extraFlags)); } else {