00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 }
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 }
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 }
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 }
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 }
00455
00456 typedef sch::Scheduler sched_t;
00457
00458 }
00459
00460 # include "scheduler.hxx"
00461
00462 #endif // ! QOLYESTER_SCH_SCHEDULER_HH