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 inline bool       operator()() const;
00049     };
00050 
00055     class Event {
00056     public:
00060 # ifdef DEBUG
00061       inline Event(const std::string& name);
00062 # else // !DEBUG
00063       inline 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 inline void      poll(std::multiset<IOEvent*, C, A>& s,
00288                                      int timeout = -1);
00289       private:
00290 
00291         static int      priority(const ::pollfd& ufd)
00292         {
00293           int r (0);
00294 
00295           if (ufd.events & POLLOUT)
00296             ++r;
00297           if (ufd.events & POLLIN)
00298             --r;
00299           if (ufd.events & POLLPRI)
00300             --r;
00301 
00302           return r;
00303         }
00304 
00305       };
00306 
00307     } // namespace internal
00308 
00309     template <class P = internal::PollData>
00310     class PollEvent_ : public Event {
00311       typedef PollEvent_<P>     This;
00312       typedef Event             Super;
00313     public:
00314       typedef P         p_t;
00315 # ifdef DEBUG
00316       PollEvent_(const P& p, const std::string& name)
00317         : Super(name),
00318           p_(p)
00319       {}
00320 # else // !DEBUG
00321       PollEvent_(const P& p)
00322         : Super(),
00323           p_(p)
00324       {}
00325 # endif
00326 
00327       virtual ~PollEvent_() {}
00328 
00329       const P&  p() const { return p_; }
00330       P&        p() { return p_; }
00331     private:
00332       P         p_;
00333     };
00334 
00335     typedef PollEvent_<>        IOEvent;
00336 
00341     void                term_handler(int);
00342     void                int_handler(int);
00343     void                quit_handler(int);
00344 
00349     class Scheduler {
00350       typedef Scheduler This;
00351 
00352       struct tevent_less {
00353         bool operator()(const TimedEvent* a, const TimedEvent* b) const {
00354           return a->next() < b->next();
00355         }
00356       };
00357 
00358       struct ioevent_less {
00359         bool operator()(const IOEvent* a, const IOEvent* b) const {
00360           return a->p() < b->p();
00361         }
00362       };
00363 
00364     public:
00365       typedef std::multiset<TimedEvent*, tevent_less>   teventset_t;
00366 
00367       typedef std::multiset<IOEvent*, ioevent_less>     ioeventset_t;
00368 
00372       inline Scheduler(LoopHandler&);
00373       inline ~Scheduler();
00374     private:
00375       inline Scheduler(const This& other);
00376       inline This& operator=(const This& other);
00377 
00378     public:
00385       inline void               insert(TimedEvent* e);
00386 
00387       inline void               erase(TimedEvent* e);
00388 
00395       inline void               insert(IOEvent* e);
00396 
00397       inline void               erase(IOEvent* e);
00398 
00399       template <class E>
00400       inline void               destroy(E* e);
00401 
00402       bool              to_delete() const { return delete_; }
00403     private:
00408       inline void       handle_tevents();
00409 
00414       inline void       handle_ioevents();
00415     public:
00416 
00420       inline void       loop();
00421 
00422     private:
00423       teventset_t       tevent_set_;    
00424       ioeventset_t      ioevent_set_;   
00425       LoopHandler&      loophandler_;
00426       const Event*      current_event_; 
00427       bool              delete_;
00428     };
00429 
00430     template <class E>
00431     class Updatable : public E {
00432       typedef Updatable<E>      This;
00433       typedef E                 Super;
00434     public:
00435       Updatable(const E& e)
00436         : Super(e),
00437           updater_(0)
00438       {}
00439 
00440       Updatable& operator = (const E& rhs)
00441       {
00442         static_cast<E&> (*this) = rhs;
00443         return *this;
00444       }
00445 
00446       void set_updater(TimedEvent* u) {
00447         updater_ = u;
00448       }
00449       TimedEvent*       updater() const { return updater_; }
00450     private:
00451       TimedEvent*       updater_;
00452     };
00453 
00454   } // namespace sch
00455 
00456   typedef sch::Scheduler        sched_t;
00457 
00458 } // namespace olsr
00459 
00460 # include "scheduler.hxx"
00461 
00462 #endif // ! QOLYESTER_SCH_SCHEDULER_HH

Generated on Mon Sep 10 17:02:12 2007 for Qolyester daemon by  doxygen 1.5.1