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 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 }
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 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 }
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 }
00457
00458 typedef sch::Scheduler sched_t;
00459
00460 }
00461
00462 # ifndef QOLYESTER_DONTINCLUDE_HXX
00463 # include "scheduler.hxx"
00464 # endif
00465
00466 #endif // ! QOLYESTER_SCH_SCHEDULER_HH