--- gvpe/src/iom.C 2003/03/21 20:33:36 1.1 +++ gvpe/src/iom.C 2003/04/04 05:26:45 1.10 @@ -1,4 +1,3 @@ -#include /* iom.C -- I/O multiplexor @@ -25,43 +24,74 @@ #include #include "slog.h" - #include "iom.h" -inline bool lowest_first (const time_watcher *a, const time_watcher *b) +tstamp NOW; +bool iom_valid; +io_manager iom; + +inline bool earliest_first (const time_watcher *a, const time_watcher *b) { return a->at > b->at; } -timestamp NOW; +void time_watcher::set (tstamp when) +{ + at = when; -io_manager iom; + if (registered) + iom.reschedule_time_watchers (); + else + iom.reg (this); +} -void time_watcher::set (timestamp when) +void time_watcher::trigger () { - iom.unreg (this); - at = when; - iom.reg (this); + call (*this); + + if (registered) + iom.reschedule_time_watchers (); + else + iom.reg (this); } -void io_manager::reg (int fd, short events, io_watcher *w) +void time_watcher::start () { - pollfd pfd; + if (!registered) + iom.reg (this); +} + +time_watcher::~time_watcher () +{ + if (iom_valid) + iom.unreg (this); +} + +io_watcher::~io_watcher () +{ + if (iom_valid) + iom.unreg (this); +} - pfd.fd = fd; - pfd.events = events; +void io_manager::reg (io_watcher *w) +{ + pollfd pfd; pfs.push_back (pfd); iow.push_back (w); + + w->p = &(*(pfs.end () - 1)); } void io_manager::unreg (io_watcher *w) { - unsigned int sz = iow.size (); - unsigned int i = find (iow.begin (), iow.end (), w) - iow.begin (); - - if (i != sz) + if (w->p) { + unsigned int sz = iow.size (); + unsigned int i = find (iow.begin (), iow.end (), w) - iow.begin (); + + assert (i != sz); + if (sz == 1) { pfs.clear (); @@ -77,32 +107,40 @@ iow[i] = iow[sz - 1]; iow.pop_back (); pfs[i] = pfs[sz - 1]; pfs.pop_back (); } + + w->p = 0; } } +void io_manager::reschedule_time_watchers () +{ + make_heap (tw.begin (), tw.end (), earliest_first); +} + void io_manager::reg (time_watcher *w) { + w->registered = true; + tw.push_back (w); - push_heap (tw.begin (), tw.end (), lowest_first); + push_heap (tw.begin (), tw.end (), earliest_first); } void io_manager::unreg (time_watcher *w) { - unsigned int sz = tw.size (); - unsigned int i = find (tw.begin (), tw.end (), w) - tw.begin (); - - if (i != sz) + if (w->registered) { - if (sz == 1) - tw.clear (); - else - { - if (i != sz - 1) - tw[i] = tw[sz - 1]; + unsigned int sz = tw.size (); + unsigned int i = find (tw.begin (), tw.end (), w) - tw.begin (); - tw.pop_back (); - make_heap (tw.begin (), tw.end (), lowest_first); - } + assert (i != sz); + + if (i != sz - 1) + tw[i] = tw[sz - 1]; + + tw.pop_back (); + reschedule_time_watchers (); + + w->registered = false; } } @@ -112,7 +150,7 @@ gettimeofday (&tv, 0); - NOW = (timestamp)tv.tv_sec + (timestamp)tv.tv_usec / 1000000; + NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000; } void io_manager::loop () @@ -121,41 +159,60 @@ for (;;) { - int timeout = tw.empty () ? -1 : (int) ((tw[0]->at - NOW) * 1000); + while (tw[0]->at <= NOW) + { + // remove the first watcher + time_watcher *w = tw[0]; - //printf ("s%d t%d #%d <%f<%f<\n", pfs.size (), timeout, tw.size (), tw[0]->at - NOW, tw[1]->at - NOW); + pop_heap (tw.begin (), tw.end (), earliest_first); + tw.pop_back (); - if (timeout >= 0) - { - int fds = poll (&pfs[0], pfs.size (), timeout); + w->registered = false; - set_now (); + // call it + w->call (*w); - for (unsigned int i = iow.size (); fds && i--; ) - if (pfs[i].revents) - { - --fds; - iow[i]->call (pfs[i].revents); - } + // re-add it if necessary + if (w->at >= 0 && !w->registered) + reg (w); } - while (!tw.empty () && tw[0]->at <= NOW) - { - pop_heap (tw.begin (), tw.end (), lowest_first); - time_watcher *w = tw[tw.size () - 1]; - w->call (w->at); - push_heap (tw.begin (), tw.end (), lowest_first); - } + int timeout = (int) ((tw[0]->at - NOW) * 1000); + + int fds = poll (&pfs[0], pfs.size (), timeout); + + set_now (); + + vector::iterator w; + vector::iterator p; + + for (w = iow.begin (), p = pfs.begin (); + fds > 0 && w < iow.end (); + ++w, ++p) + if (p->revents) + { + --fds; + (*w)->call (**w, p->revents); + } } } +void io_manager::idle_cb (time_watcher &w) +{ + w.at = NOW + 86400; // wake up every day, for no good reason +} + io_manager::io_manager () { + iom_valid = true; + set_now (); + idle = new time_watcher (this, &io_manager::idle_cb); + idle->start (0); } io_manager::~io_manager () { - // + iom_valid = false; }