#define TV_FRAC tv_usec
#define TV_MULT 1000000L
+#ifndef IOM_LIBEVENT
#if IOM_IO
static io_manager_vec<io_watcher> iow;
#endif
-#if IOM_CHECK
-static io_manager_vec<check_watcher> cw;
-#endif
#if IOM_TIME
static io_manager_vec<time_watcher> tw;
#endif
+#endif
+
+#if IOM_CHECK
+static io_manager_vec<check_watcher> cw;
+#endif
#if IOM_IDLE
static io_manager_vec<idle_watcher> iw;
#endif
+
#if IOM_SIG
static int sigpipe[2]; // signal signalling pipe
static sigset_t sigs;
};
static vector<sig_vec *> sw;
#endif
+
#if IOM_CHILD
static io_manager_vec<child_watcher> pw;
#endif
{
#ifdef IOM_PREINIT
{ IOM_PREINIT }
+#endif
+#ifdef IOM_LIBEVENT
+ event_init ();
#endif
iom_valid = true;
}
#if IOM_TIME
+# ifdef IOM_LIBEVENT
+ void iom_time_c_callback (int fd, short events, void *data)
+ {
+ time_watcher *w = static_cast<time_watcher *>(data);
+ w->call (*w);
+ }
+# else
+ void io_manager::reg (time_watcher &w) { io_manager::reg (w, tw); }
+ void io_manager::unreg (time_watcher &w) { io_manager::unreg (w, tw); }
+# endif
+
void time_watcher::trigger ()
{
call (*this);
- io_manager::reg (*this);
+ start ();
}
-
-void io_manager::reg (time_watcher &w) { io_manager::reg (w, tw); }
-void io_manager::unreg (time_watcher &w) { io_manager::unreg (w, tw); }
#endif
#if IOM_IO
-void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); }
-void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); }
+# ifdef IOM_LIBEVENT
+ void iom_io_c_callback (int fd, short events, void *data)
+ {
+ io_watcher *w = static_cast<io_watcher *>(data);
+ w->call (*w, events);
+ }
+# else
+ void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); }
+ void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); }
+# endif
#endif
#if IOM_CHECK
{
init::required ();
-#if IOM_TIME
- set_now ();
-#endif
+ #if IOM_TIME
+ set_now ();
+ #endif
for (;;)
{
+ #ifndef IOM_LIBEVENT
+ #if IOM_TIME
+ // call pending time watchers
+ {
+ bool activity;
-#if IOM_TIME
- // call pending time watchers
- {
- bool activity;
-
- do
- {
- activity = false;
-
- for (int i = tw.size (); i--; )
- if (!tw[i])
- tw.erase_unordered (i);
- else if (tw[i]->at <= NOW)
- {
- time_watcher &w = *tw[i];
-
- unreg (w);
- w.call (w);
+ do
+ {
+ activity = false;
- activity = true;
- }
- }
- while (activity);
- }
-#endif
+ for (int i = tw.size (); i--; )
+ if (!tw[i])
+ tw.erase_unordered (i);
+ else if (tw[i]->at <= NOW)
+ {
+ time_watcher &w = *tw[i];
+
+ unreg (w);
+ w.call (w);
-#if IOM_CHECK
- // call all check watchers
- for (int i = cw.size (); i--; )
- if (!cw[i])
- cw.erase_unordered (i);
- else
- cw[i]->call (*cw[i]);
-#endif
+ activity = true;
+ }
+ }
+ while (activity);
+ }
+ #endif
+ #endif
+
+ #if IOM_CHECK
+ // call all check watchers
+ for (int i = cw.size (); i--; )
+ if (!cw[i])
+ cw.erase_unordered (i);
+ else
+ cw[i]->call (*cw[i]);
+ #endif
struct TIMEVAL *to = 0;
struct TIMEVAL tval;
}
else
#endif
+#ifndef IOM_LIBEVENT
{
-#if IOM_TIME
- // find earliest active watcher
- time_watcher *next = tw[0]; // the first time-watcher must exist at ALL times
+ #if IOM_TIME
+ // find earliest active watcher
+ time_watcher *next = tw[0]; // the first time-watcher must exist at ALL times
- for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
- if (*i && (*i)->at < next->at)
- next = *i;
+ for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
+ if (*i && (*i)->at < next->at)
+ next = *i;
- if (next->at > NOW && next != tw[0])
- {
- double diff = next->at - NOW;
- tval.tv_sec = (int)diff;
- tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT);
- to = &tval;
- }
+ if (next->at > NOW && next != tw[0])
+ {
+ double diff = next->at - NOW;
+ tval.tv_sec = (int)diff;
+ tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT);
+ to = &tval;
+ }
+ #endif
}
-#endif
#if IOM_IO || IOM_SIG
fd_set rfd, wfd;
int fds = 0;
-# if IOM_IO
- for (io_manager_vec<io_watcher>::const_iterator i = iow.end (); i-- > iow.begin (); )
- if (*i)
- {
- if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
- if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
+ #if IOM_IO
+ for (io_manager_vec<io_watcher>::const_iterator i = iow.end (); i-- > iow.begin (); )
+ if (*i)
+ {
+ if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
+ if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
- if ((*i)->fd >= fds) fds = (*i)->fd + 1;
- }
-# endif
+ if ((*i)->fd >= fds) fds = (*i)->fd + 1;
+ }
+ #endif
if (!to && !fds) //TODO: also check idle_watchers and check_watchers?
break; // no events
-# if IOM_SIG
- FD_SET (sigpipe[0], &rfd);
- if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
-# endif
+ #if IOM_SIG
+ FD_SET (sigpipe[0], &rfd);
+ if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
+ #endif
-# if IOM_SIG
- // there is no race, as we use a pipe for signals, so select
- // will return if a signal is caught.
- sigprocmask (SIG_UNBLOCK, &sigs, NULL);
-# endif
+ #if IOM_SIG
+ // there is no race, as we use a pipe for signals, so select
+ // will return if a signal is caught.
+ sigprocmask (SIG_UNBLOCK, &sigs, NULL);
+ #endif
fds = select (fds, &rfd, &wfd, NULL, to);
-# if IOM_SIG
- sigprocmask (SIG_BLOCK, &sigs, NULL);
-# endif
+ #if IOM_SIG
+ sigprocmask (SIG_BLOCK, &sigs, NULL);
+ #endif
-# if IOM_TIME
- {
- // update time, try to compensate for gross non-monotonic time changes
- tstamp diff = NOW;
- set_now ();
- diff = NOW - diff;
-
- if (diff < 0)
- for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
- if (*i)
- (*i)->at += diff;
- }
-# endif
+#else
+ if (to)
+ event_loop (EVLOOP_NONBLOCK);
+ else
+ event_loop (EVLOOP_ONCE);
+#endif
- if (fds > 0)
+ #if IOM_TIME
{
-# if IOM_SIG
- if (FD_ISSET (sigpipe[0], &rfd))
- {
- char ch;
-
- while (read (sigpipe[0], &ch, 1) > 0)
- ;
-
- for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); )
- if (*svp && (*svp)->pending)
- {
- sig_vec &sv = **svp;
- for (int i = sv.size (); i--; )
- if (!sv[i])
- sv.erase_unordered (i);
- else
- sv[i]->call (*sv[i]);
-
- sv.pending = false;
- }
- }
-# endif
+ // update time, try to compensate for gross non-monotonic time changes
+ tstamp diff = NOW;
+ set_now ();
+ diff = NOW - diff;
+
+ if (diff < 0)
+ for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
+ if (*i)
+ (*i)->at += diff;
+ }
+ #endif
-# if IOM_IO
- for (int i = iow.size (); i--; )
- if (!iow[i])
- iow.erase_unordered (i);
- else
+#ifndef IOM_LIBEVENT
+ if (fds > 0)
+ {
+ #if IOM_SIG
+ if (FD_ISSET (sigpipe[0], &rfd))
{
- io_watcher &w = *iow[i];
- short revents = w.events;
+ char ch;
+
+ while (read (sigpipe[0], &ch, 1) > 0)
+ ;
+
+ for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); )
+ if (*svp && (*svp)->pending)
+ {
+ sig_vec &sv = **svp;
+ for (int i = sv.size (); i--; )
+ if (!sv[i])
+ sv.erase_unordered (i);
+ else
+ sv[i]->call (*sv[i]);
+
+ sv.pending = false;
+ }
+ }
+ #endif
- if (!FD_ISSET (w.fd, &rfd)) revents &= ~EVENT_READ;
- if (!FD_ISSET (w.fd, &wfd)) revents &= ~EVENT_WRITE;
+ #if IOM_IO
+ for (int i = iow.size (); i--; )
+ if (!iow[i])
+ iow.erase_unordered (i);
+ else
+ {
+ io_watcher &w = *iow[i];
+ short revents = w.events;
- if (revents)
- w.call (w, revents);
- }
-#endif
+ if (!FD_ISSET (w.fd, &rfd)) revents &= ~EVENT_READ;
+ if (!FD_ISSET (w.fd, &wfd)) revents &= ~EVENT_WRITE;
+
+ if (revents)
+ w.call (w, revents);
+ }
+ #endif
}
else if (fds < 0 && errno != EINTR)
{
perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
abort ();
}
+#else
+ if (0)
+ ;
+#endif
#if IOM_IDLE
else
for (int i = iw.size (); i--; )
if (!to)
break;
- select (0, 0, 0, 0, &to);
+ select (0, 0, 0, 0, to);
set_now ();
-#else
break;
#endif
}
// TSTAMP_MAX must still fit into a positive struct timeval
#define TSTAMP_MAX (double)(1UL<<31)
+//#define IOM_LIBEVENT "event.h" *NOT* a supported feature
+#ifdef IOM_LIBEVENT
+# include <sys/time.h>
+# include IOM_LIBEVENT
+# undef IOM_IO
+# define IOM_IO 1
+#endif
+
struct watcher;
#if IOM_IO
struct io_watcher;
#endif
// register a watcher
+#ifndef IOM_LIBEVENT
#if IOM_IO
static void reg (io_watcher &w); static void unreg (io_watcher &w);
#endif
#if IOM_TIME
static void reg (time_watcher &w); static void unreg (time_watcher &w);
#endif
+#if IOM_SIG
+ static void reg (sig_watcher &w); static void unreg (sig_watcher &w);
+#endif
#if IOM_CHECK
static void reg (check_watcher &w); static void unreg (check_watcher &w);
#endif
+#endif
#if IOM_IDLE
static void reg (idle_watcher &w); static void unreg (idle_watcher &w);
#endif
-#if IOM_SIG
- static void reg (sig_watcher &w); static void unreg (sig_watcher &w);
-#endif
#if IOM_CHILD
static void reg (child_watcher &w); static void unreg (child_watcher &w);
#endif
};
#if IOM_IO
+#ifdef IOM_LIBEVENT
+enum { EVENT_UNDEF = -1, EVENT_NONE = 0, EVENT_READ = EV_READ, EVENT_WRITE = EV_WRITE };
+
+void iom_io_c_callback (int fd, short events, void *data);
+
+struct io_watcher : watcher, callback<void (io_watcher &, short)> {
+ struct event ev;
+ int fd;
+
+ void set (int fd_, short events_) { fd = fd_; event_set (&ev, fd_, events_, iom_io_c_callback, (void *)this); }
+
+ void set (short events_) { set (fd, events_); }
+ void start () { event_add (&ev, 0); active = 1; }
+ void start (int fd_, short events_) { set (fd_, events_); start (); }
+ void stop () { if (active) event_del (&ev); active = 0; }
+
+ template<class O, class M>
+ io_watcher (O object, M method)
+ : callback<void (io_watcher &, short)> (object, method)
+ { }
+ ~io_watcher () { stop (); }
+};
+#else
enum { EVENT_UNDEF = -1, EVENT_NONE = 0, EVENT_READ = 1, EVENT_WRITE = 2 };
struct io_watcher : watcher, callback<void (io_watcher &, short)> {
void set (short events_) { set (fd, events_); }
void start () { io_manager::reg (*this); }
- void start (int fd_, short events_) { set (fd_, events_); io_manager::reg (*this); }
+ void start (int fd_, short events_) { set (fd_, events_); start (); }
void stop () { io_manager::unreg (*this); }
template<class O, class M>
~io_watcher () { stop (); }
};
#endif
+#endif
#if IOM_TIME
+#ifdef IOM_LIBEVENT
+void iom_time_c_callback (int fd, short events, void *data);
+
+struct time_watcher : watcher, callback<void (time_watcher &)> {
+ struct event ev;
+ tstamp at;
+
+ void trigger ();
+
+ void set (tstamp when) { at = when; }
+ void operator () () { trigger (); }
+ void start ()
+ {
+ struct timeval tv;
+ tv.tv_sec = (long)at;
+ tv.tv_usec = (long)((at - (tstamp)tv.tv_sec) * 1000000.);
+ evtimer_add (&ev, &tv);
+ active = 1;
+ }
+ void start (tstamp when) { set (when); start (); }
+ void stop () { if (active) evtimer_del (&ev); active = 0; }
+
+ template<class O, class M>
+ time_watcher (O object, M method)
+ : callback<void (time_watcher &)> (object, method), at (0)
+ {
+ evtimer_set (&ev, iom_time_c_callback, (void *)this);
+ }
+ ~time_watcher () { stop (); }
+};
+#else
struct time_watcher : watcher, callback<void (time_watcher &)> {
tstamp at;
void set (tstamp when) { at = when; }
void operator () () { trigger (); }
void start () { io_manager::reg (*this); }
- void start (tstamp when) { set (when); io_manager::reg (*this); }
+ void start (tstamp when) { set (when); start (); }
void stop () { io_manager::unreg (*this); }
template<class O, class M>
~time_watcher () { stop (); }
};
#endif
+#endif
#if IOM_CHECK
// run before checking for new events