Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

scheduler.hh

Go to the documentation of this file.
00001 // Copyright (C) 2003, 2004, 2005 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 
00030 
00031 #ifndef QOLYESTER_SCH_SCHEDULER_HH
00032 # define QOLYESTER_SCH_SCHEDULER_HH 1
00033 
00034 # include <sys/poll.h>
00035 # include <string>
00036 # include <set>
00037 # include "config.hh"
00038 # include "utl/meta.hh"
00039 # include "utl/timeval.hh"
00040 
00041 namespace olsr {
00042 
00043   namespace sch {
00044 
00045     class LoopHandler {
00046     public:
00047       virtual ~LoopHandler() {}
00048       virtual bool      operator()() const;
00049     };
00050 
00055     class Event {
00056     public:
00060 # ifdef DEBUG
00061       Event(const std::string& name);
00062 # else // !DEBUG
00063       Event();
00064 # endif
00065 
00066       virtual ~Event() {}
00067 
00071       virtual void      handle() = 0;
00072 
00073 # ifdef DEBUG
00074       const std::string&        name() const { return name_; }
00075 # else // !DEBUG
00076       null_t                    name() const { return null_t(); }
00077 # endif
00078     private:
00079 # ifdef DEBUG
00080       const std::string name_; 
00081 # endif // !DEBUG
00082     };
00083 
00088     class TimedEvent : public Event {
00089       typedef TimedEvent        This;
00090       typedef Event             Super;
00091     public:
00098 # ifdef DEBUG
00099       TimedEvent(const timeval_t& n, const std::string& name)
00100         : Super(name),
00101           next_(n)
00102       {}
00103 # else // !DEBUG
00104       TimedEvent(const timeval_t& n)
00105         : Super(),
00106           next_(n)
00107       {}
00108 # endif
00109 
00113       virtual ~TimedEvent() {}
00114 
00120       const timeval_t&  next() const {  return next_; }
00121       void              set_next(const timeval_t& n) { next_ = n; }
00122 
00123     protected:
00124       timeval_t         next_;  
00125     };
00126 
00127     namespace upd {
00128 
00129       template <class S, class I = typename S::iterator>
00130       struct SetEraser {
00131         SetEraser(S& s, const I& i)
00132           : s_(s),
00133             i_(i)
00134         {}
00135         void    operator()() {
00136           s_.erase(i_);
00137         }
00138       private:
00139         S&      s_;
00140         I               i_;
00141       };
00142 
00143     } // namespace upd
00144 
00145     template <class F>
00146     class UpdateEvent : public TimedEvent {
00147       typedef UpdateEvent<F>    This;
00148       typedef TimedEvent        Super;
00149     public:
00150 # ifdef DEBUG
00151       UpdateEvent(const timeval_t& n, const F& f)
00152         : Super(n, "UpdateEvent"),
00153           f_(f)
00154       {}
00155 # else // !DEBUG
00156       UpdateEvent(const timeval_t& n, const F& f)
00157         : Super(n),
00158           f_(f)
00159       {}
00160 # endif
00161       virtual void      handle() {
00162         f_();
00163       }
00164     private:
00165       F f_;
00166     };
00167 
00168     namespace internal {
00169 
00170       struct TrivialIncrement {
00171         void    operator()(timeval_t& n, timeval_t& p) const {
00172           n += p;
00173         }
00174       };
00175 
00176     } // namespace internal
00177 
00178     template <class I = internal::TrivialIncrement>
00179     class PeriodicEvent_ : public TimedEvent {
00180       typedef PeriodicEvent_<I> This;
00181       typedef TimedEvent                Super;
00182     public:
00183 # ifdef DEBUG
00184       PeriodicEvent_(const timeval_t& n, const timeval_t& p,
00185                      const std::string& name)
00186         : Super(n, name),
00187           period_(p)
00188       {}
00189       PeriodicEvent_(const timeval_t& n, const timeval_t& p, const I& i,
00190                      const std::string& name)
00191         : Super(n, name),
00192           period_(p),
00193           increment_(i)
00194       {}
00195 # else // !DEBUG
00196       PeriodicEvent_(const timeval_t& n, const timeval_t& p)
00197         : Super(n),
00198           period_(p)
00199       {}
00200       PeriodicEvent_(const timeval_t& n, const timeval_t& p, const I& i)
00201         : Super(n),
00202           period_(p),
00203           increment_(i)
00204       {}
00205 # endif
00206       virtual void      handle();
00207     private:
00208       timeval_t period_;
00209       I         increment_;
00210     };
00211 
00212     typedef PeriodicEvent_<>    PeriodicEvent;
00213 
00214     namespace internal {
00215 
00216       struct JitterIncrement {
00217         JitterIncrement()
00218           : jitter_(0)
00219         {}
00220         JitterIncrement(const timeval_t& j)
00221           : jitter_(j)
00222         {}
00223         void    operator()(timeval_t& n, timeval_t& p) const {
00224           timeval_t     j = timeval_t::jitter(jitter_);
00225           if (j > p)
00226             return;
00227           n += p - j;
00228         }
00229       private:
00230         timeval_t       jitter_;
00231       };
00232 
00233     } // namespace internal
00234 
00235     class JitteredEvent : public PeriodicEvent_<internal::JitterIncrement> {
00236       typedef JitteredEvent                             This;
00237       typedef PeriodicEvent_<internal::JitterIncrement> Super;
00238     public:
00239 # ifdef DEBUG
00240       JitteredEvent(const timeval_t& n, const timeval_t& p, const timeval_t& j,
00241                     const std::string& name)
00242         : Super(n, p, j, name)
00243       {}
00244 # else // !DEBUG
00245       JitteredEvent(const timeval_t& n, const timeval_t& p, const timeval_t& j)
00246         : Super(n, p, j)
00247       {}
00248 # endif
00249     };
00250 
00251     template <class> class PollEvent_;
00252     namespace internal {
00253       struct PollData;
00254     }
00255 
00256     typedef PollEvent_<internal::PollData>      IOEvent;
00257 
00258     namespace internal {
00259 
00260       struct PollData {
00261         PollData(int fd, short events) {
00262           pfd.fd = fd;
00263           pfd.events = events;
00264           pfd.revents = 0;
00265         }
00266 
00267         bool    active() const {
00268           return (pfd.events & pfd.revents) != 0;
00269         }
00270 
00271         bool    operator<(const PollData& rhs) const {
00272           if (active() != rhs.active())
00273             return active();
00274 
00275           const int     apri = priority(pfd);
00276           const int     bpri = priority(rhs.pfd);
00277 
00278           if (apri != bpri)
00279             return apri > bpri;
00280           else
00281             return pfd.fd < rhs.pfd.fd;
00282         }
00283 
00284         ::pollfd        pfd;
00285 
00286         template <class C, class A>
00287         static void
00288         poll(std::multiset<IOEvent*, C, A>& s, int timeout = -1);
00289       private:
00290 
00291         inline static
00292         int
00293         priority(const ::pollfd& ufd)
00294         {
00295           int r (0);
00296 
00297           if (ufd.events & POLLOUT)
00298             ++r;
00299           if (ufd.events & POLLIN)
00300             --r;
00301           if (ufd.events & POLLPRI)
00302             --r;
00303 
00304           return r;
00305         }
00306 
00307       };
00308 
00309     } // namespace internal
00310 
00311     template <class P = internal::PollData>
00312     class PollEvent_ : public Event {
00313       typedef PollEvent_<P>     This;
00314       typedef Event             Super;
00315     public:
00316       typedef P         p_t;
00317 # ifdef DEBUG
00318       PollEvent_(const P& p, const std::string& name)
00319         : Super(name),
00320           p_(p)
00321       {}
00322 # else // !DEBUG
00323       PollEvent_(const P& p)
00324         : Super(),
00325           p_(p)
00326       {}
00327 # endif
00328 
00329       virtual ~PollEvent_() {}
00330 
00331       const P&  p() const { return p_; }
00332       P&        p() { return p_; }
00333     private:
00334       P         p_;
00335     };
00336 
00337     typedef PollEvent_<>        IOEvent;
00338 
00343     void                term_handler(int);
00344     void                int_handler(int);
00345     void                quit_handler(int);
00346 
00351     class Scheduler {
00352       typedef Scheduler This;
00353 
00354       struct tevent_less {
00355         bool operator()(const TimedEvent* a, const TimedEvent* b) const {
00356           return a->next() < b->next();
00357         }
00358       };
00359 
00360       struct ioevent_less {
00361         bool operator()(const IOEvent* a, const IOEvent* b) const {
00362           return a->p() < b->p();
00363         }
00364       };
00365 
00366     public:
00367       typedef std::multiset<TimedEvent*, tevent_less>   teventset_t;
00368 
00369       typedef std::multiset<IOEvent*, ioevent_less>     ioeventset_t;
00370 
00374       Scheduler(LoopHandler&);
00375       ~Scheduler();
00376     private:
00377       Scheduler(const This& other);
00378       This& operator=(const This& other);
00379 
00380     public:
00387       void              insert(TimedEvent* e);
00388 
00389       void              erase(TimedEvent* e);
00390 
00397       void              insert(IOEvent* e);
00398 
00399       void              erase(IOEvent* e);
00400 
00401       template <class E>
00402       void              destroy(E* e);
00403 
00404       bool              to_delete() const { return delete_; }
00405     private:
00410       void handle_tevents();
00411 
00416       void handle_ioevents();
00417     public:
00418 
00422       void loop();
00423 
00424     private:
00425       teventset_t       tevent_set_;    
00426       ioeventset_t      ioevent_set_;   
00427       LoopHandler&      loophandler_;
00428       const Event*      current_event_; 
00429       bool              delete_;
00430     };
00431 
00432     template <class E>
00433     class Updatable : public E {
00434       typedef Updatable<E>      This;
00435       typedef E                 Super;
00436     public:
00437       Updatable(const E& e)
00438         : Super(e),
00439           updater_(0)
00440       {}
00441 
00442       Updatable& operator = (const E& rhs)
00443       {
00444         static_cast<E&> (*this) = rhs;
00445         return *this;
00446       }
00447 
00448       void set_updater(TimedEvent* u) {
00449         updater_ = u;
00450       }
00451       TimedEvent*       updater() const { return updater_; }
00452     private:
00453       TimedEvent*       updater_;
00454     };
00455 
00456   } // namespace sch
00457 
00458   typedef sch::Scheduler        sched_t;
00459 
00460 } // namespace olsr
00461 
00462 # ifndef QOLYESTER_DONTINCLUDE_HXX
00463 #  include "scheduler.hxx"
00464 # endif
00465 
00466 #endif // ! QOLYESTER_SCH_SCHEDULER_HH

Generated on Thu Jul 28 21:21:48 2005 for Qolyester daemon by  doxygen 1.4.1