typedef struct ev_watcher_list *WL;
typedef struct ev_watcher_time *WT;
+static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
+
/*****************************************************************************/
typedef struct
} ANPENDING;
#ifdef EV_MULTIPLICITY
+
struct ev_loop
{
-# define VAR(name,decl) decl
+# define VAR(name,decl) decl;
# include "ev_vars.h"
};
+# undef VAR
+# include "ev_wrap.h"
+
#else
-# define VAR(name,decl) static decl
+
+# define VAR(name,decl) static decl;
# include "ev_vars.h"
+# undef VAR
+
#endif
-#undef VAR
/*****************************************************************************/
/*****************************************************************************/
static void
-upheap (WT *timers, int k)
+upheap (WT *heap, int k)
{
- WT w = timers [k];
+ WT w = heap [k];
- while (k && timers [k >> 1]->at > w->at)
+ while (k && heap [k >> 1]->at > w->at)
{
- timers [k] = timers [k >> 1];
- timers [k]->active = k + 1;
+ heap [k] = heap [k >> 1];
+ heap [k]->active = k + 1;
k >>= 1;
}
- timers [k] = w;
- timers [k]->active = k + 1;
+ heap [k] = w;
+ heap [k]->active = k + 1;
}
static void
-downheap (WT *timers, int N, int k)
+downheap (WT *heap, int N, int k)
{
- WT w = timers [k];
+ WT w = heap [k];
while (k < (N >> 1))
{
int j = k << 1;
- if (j + 1 < N && timers [j]->at > timers [j + 1]->at)
+ if (j + 1 < N && heap [j]->at > heap [j + 1]->at)
++j;
- if (w->at <= timers [j]->at)
+ if (w->at <= heap [j]->at)
break;
- timers [k] = timers [j];
- timers [k]->active = k + 1;
+ heap [k] = heap [j];
+ heap [k]->active = k + 1;
k = j;
}
- timers [k] = w;
- timers [k]->active = k + 1;
+ heap [k] = w;
+ heap [k]->active = k + 1;
}
/*****************************************************************************/
#endif
ev_io_set (&sigev, sigpipe [0], EV_READ);
- ev_io_start (&sigev);
+ ev_io_start (EV_A_ &sigev);
ev_unref (EV_A); /* child watcher should not keep loop alive */
}
return method;
}
-int
-ev_init (EV_P_ int methods)
+static void
+loop_init (EV_P_ int methods)
{
-#ifdef EV_MULTIPLICITY
- memset (loop, 0, sizeof (struct ev_loop));
-#endif
-
if (!method)
{
#if EV_USE_MONOTONIC
rt_now = ev_time ();
mn_now = get_clock ();
now_floor = mn_now;
- diff = rt_now - mn_now;
+ rtmn_diff = rt_now - mn_now;
if (pipe (sigpipe))
return 0;
return method;
}
+#ifdef EV_MULTIPLICITY
+
+struct ev_loop *
+ev_loop_new (int methods)
+{
+ struct ev_loop *loop = (struct ev_loop *)calloc (1, sizeof (struct ev_loop));
+
+ loop_init (EV_A_ methods);
+
+ return loop;
+}
+
+void
+ev_loop_delete (EV_P)
+{
+ /*TODO*/
+ free (loop);
+}
+
+#else
+
+int
+ev_init (int methods)
+{
+ loop_init ();
+}
+
+#endif
+
/*****************************************************************************/
void
void
ev_fork_child (void)
{
+ /*TODO*/
+#if !EV_MULTIPLICITY
#if EV_USE_EPOLL
if (method == EVMETHOD_EPOLL)
- epoll_postfork_child ();
+ epoll_postfork_child (EV_A);
#endif
- ev_io_stop (&sigev);
+ ev_io_stop (EV_A_ &sigev);
close (sigpipe [0]);
close (sigpipe [1]);
pipe (sigpipe);
- siginit ();
+ siginit (EV_A);
+#endif
}
/*****************************************************************************/
else
ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */
- event ((W)w, EV_TIMEOUT);
+ event (EV_A_ (W)w, EV_TIMEOUT);
}
}
}
static void
-periodics_reschedule (EV_P_ ev_tstamp diff)
+periodics_reschedule (EV_P)
{
int i;
if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5))
{
- rt_now = mn_now + diff;
+ rt_now = rtmn_diff + mn_now;
return 0;
}
else
{
if (time_update_monotonic (EV_A))
{
- ev_tstamp odiff = diff;
+ ev_tstamp odiff = rtmn_diff;
for (i = 4; --i; ) /* loop a few times, before making important decisions */
{
- diff = rt_now - mn_now;
+ rtmn_diff = rt_now - mn_now;
- if (fabs (odiff - diff) < MIN_TIMEJUMP)
+ if (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP)
return; /* all is well */
rt_now = ev_time ();
now_floor = mn_now;
}
- periodics_reschedule (EV_A_ diff - odiff);
+ periodics_reschedule (EV_A);
/* no timer adjustment, as the monotonic clock doesn't jump */
+ /* timers_reschedule (EV_A_ rtmn_diff - odiff) */
}
}
else
if (expect_false (mn_now > rt_now || mn_now < rt_now - MAX_BLOCKTIME - MIN_TIMEJUMP))
{
- periodics_reschedule (EV_A_ rt_now - mn_now);
+ periodics_reschedule (EV_A);
/* adjust timers. this is easy, as the offset is the same for all */
for (i = 0; i < timercnt; ++i)
- timers [i]->at += diff;
+ timers [i]->at += rt_now - mn_now;
}
mn_now = rt_now;
# define EV_MAXPRI +2
#endif
+#ifndef EV_MULTIPLICITY
+# define EV_MULTIPLICITY 1
+#endif
+
/* support multiple event loops? */
-#ifdef EV_MULTIPLICITY
+#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P struct ev_loop *loop
# define EV_P_ EV_P,
# define EV_P_
# define EV_A
# define EV_A_
-
#endif
/* eventmask, revents, events... */
struct ev_signal
{
EV_WATCHER_LIST (ev_signal);
+#if EV_MULTIPLICITY
+ struct ev_loop *loop;
+#endif
int signum; /* ro */
};
#define EVMETHOD_DEVPOLL 16 /* NYI */
#define EVMETHOD_PORT 32 /* NYI */
#define EVMETHOD_ANY ~0 /* any method, do not consult env */
+
#if EV_PROTOTYPES
-int ev_method (EV_P);
-int ev_init (EV_P_ int methods); /* returns ev_method */
int ev_version_major (void);
int ev_version_minor (void);
void ev_fork_child (void);
ev_tstamp ev_time (void);
+
+# if EV_MULTIPLICITY
+struct ev_loop *ev_loop_new (int methods);
+void ev_loop_delete (EV_P);
+# else
+int ev_init (int methods); /* returns ev_method */
+# endif
+
+int ev_method (EV_P);
+
#endif
#define EVLOOP_NONBLOCK 1 /* do not block/wait */
#define EVLOOP_ONESHOT 2 /* block *once* only */
+#define EVUNLOOP_ONCE 1 /* unloop once */
+#define EVUNLOOP_ALL 2 /* unloop all loops */
+
#if EV_PROTOTYPES
void ev_loop (EV_P_ int flags);
-void ev_unloop (EV_P_ int status); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */
+void ev_unloop (EV_P_ int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */
ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */
events |= byte_w & (1 << bit) ? EV_WRITE : 0;
if (events)
- fd_event (idx * 8 + bit, events);
+ fd_event (EV_A_ idx * 8 + bit, events);
}
}
}
else if (res < 0)
{
if (errno == EBADF)
- fd_ebadf ();
+ fd_ebadf (EV_A);
else if (errno == ENOMEM)
- fd_enomem ();
+ fd_enomem (EV_A);
}
}
#define VARx(type,name) VAR(name, type name)
-VARx(ev_tstamp, now_floor); /* last time we refreshed rt_time */
-VARx(ev_tstamp, mn_now); /* monotonic clock "now" */
-VARx(ev_tstamp, rt_now);
-VARx(ev_tstamp, diff); /* difference realtime - monotonic time */
-VARx(int, method);
-
-VARx(int, have_monotonic); /* runtime */
-
-VARx(ev_tstamp, method_fudge); /* assumed typical timer resolution */
-VAR (method_modify, void (*method_modify)(EV_P_ int fd, int oev, int nev));
-VAR (method_poll , void (*method_poll)(EV_P_ ev_tstamp timeout));
-
-VARx(int, activecnt); /* number of active events */
-
-#if EV_USE_SELECT
-VARx(unsigned char *, vec_ri);
-VARx(unsigned char *, vec_ro);
-VARx(unsigned char *, vec_wi);
-VARx(unsigned char *, vec_wo);
-VARx(int, vec_max);
+VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */
+VARx(ev_tstamp, mn_now) /* monotonic clock "now" */
+VARx(ev_tstamp, rt_now)
+VARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */
+VARx(int, method)
+
+VARx(ev_tstamp, method_fudge) /* assumed typical timer resolution */
+VAR (method_modify, void (*method_modify)(EV_P_ int fd, int oev, int nev))
+VAR (method_poll , void (*method_poll)(EV_P_ ev_tstamp timeout))
+
+VARx(int, activecnt) /* number of active events */
+
+#if EV_USE_SELECT || EV_GENWRAP
+VARx(unsigned char *, vec_ri)
+VARx(unsigned char *, vec_ro)
+VARx(unsigned char *, vec_wi)
+VARx(unsigned char *, vec_wo)
+VARx(int, vec_max)
#endif
-#if EV_USEV_POLL
-VARx(struct pollfd *, polls);
-VARx(int, pollmax);
-VARx(int, pollcnt);
-VARx(int *, pollidxs); /* maps fds into structure indices */
-VARx(int, pollidxmax);
+#if EV_USE_POLL || EV_GENWRAP
+VARx(struct pollfd *, polls)
+VARx(int, pollmax)
+VARx(int, pollcnt)
+VARx(int *, pollidxs) /* maps fds into structure indices */
+VARx(int, pollidxmax)
#endif
-#if EV_USE_EPOLL
-VARx(int, epoll_fd);
+#if EV_USE_EPOLL || EV_GENWRAP
+VARx(int, epoll_fd)
-VARx(struct epoll_event *, events);
-VARx(int, eventmax);
+VARx(struct epoll_event *, epoll_events)
+VARx(int, epoll_eventmax)
#endif
-#if EV_USE_KQUEUE
-VARx(int, kqueue_fd);
-VARx(struct kevent *, kqueue_changes);
-VARx(int, kqueue_changemax);
-VARx(int, kqueue_changecnt);
-VARx(struct kevent *, kqueue_events);
-VARx(int, kqueue_eventmax);
+#if EV_USE_KQUEUE || EV_GENWRAP
+VARx(int, kqueue_fd)
+VARx(struct kevent *, kqueue_changes)
+VARx(int, kqueue_changemax)
+VARx(int, kqueue_changecnt)
+VARx(struct kevent *, kqueue_events)
+VARx(int, kqueue_eventmax)
#endif
-VARx(ANFD *, anfds);
-VARx(int, anfdmax);
+VARx(ANFD *, anfds)
+VARx(int, anfdmax)
-VAR (pendings, ANPENDING *pendings [NUMPRI]);
-VAR (pendingmax, int pendingmax [NUMPRI]);
-VAR (pendingcnt, int pendingcnt [NUMPRI]);
+VAR (pendings, ANPENDING *pendings [NUMPRI])
+VAR (pendingmax, int pendingmax [NUMPRI])
+VAR (pendingcnt, int pendingcnt [NUMPRI])
-VARx(int *, fdchanges);
-VARx(int, fdchangemax);
-VARx(int, fdchangecnt);
+VARx(int *, fdchanges)
+VARx(int, fdchangemax)
+VARx(int, fdchangecnt)
-VARx(struct ev_timer **, timers);
-VARx(int, timermax);
-VARx(int, timercnt);
+VARx(struct ev_timer **, timers)
+VARx(int, timermax)
+VARx(int, timercnt)
-VARx(struct ev_periodic **, periodics);
-VARx(int, periodicmax);
-VARx(int, periodiccnt);
+VARx(struct ev_periodic **, periodics)
+VARx(int, periodicmax)
+VARx(int, periodiccnt)
-VARx(struct ev_idle **, idles);
-VARx(int, idlemax);
-VARx(int, idlecnt);
+VARx(struct ev_idle **, idles)
+VARx(int, idlemax)
+VARx(int, idlecnt)
-VARx(struct ev_prepare **, prepares);
-VARx(int, preparemax);
-VARx(int, preparecnt);
+VARx(struct ev_prepare **, prepares)
+VARx(int, preparemax)
+VARx(int, preparecnt)
-VARx(struct ev_check **, checks);
-VARx(int, checkmax);
-VARx(int, checkcnt);
+VARx(struct ev_check **, checks)
+VARx(int, checkmax)
+VARx(int, checkcnt)
-VAR (childs, struct ev_child *childs [PID_HASHSIZE]);
-VARx(struct ev_signal, childev);
+VAR (childs, struct ev_child *childs [PID_HASHSIZE])
+VARx(struct ev_signal, childev)
-VARx(struct ev_io, sigev);
+VARx(struct ev_io, sigev)
#undef VARx
--- /dev/null
+/* DO NOT EDIT, automaticlaly generated by update_ev_wrap */
+#define now_floor ((loop)->now_floor)
+#define mn_now ((loop)->mn_now)
+#define rt_now ((loop)->rt_now)
+#define rtmn_diff ((loop)->rtmn_diff)
+#define method ((loop)->method)
+#define method_fudge ((loop)->method_fudge)
+#define method_modify ((loop)->method_modify)
+#define method_poll ((loop)->method_poll)
+#define activecnt ((loop)->activecnt)
+#define vec_ri ((loop)->vec_ri)
+#define vec_ro ((loop)->vec_ro)
+#define vec_wi ((loop)->vec_wi)
+#define vec_wo ((loop)->vec_wo)
+#define vec_max ((loop)->vec_max)
+#define polls ((loop)->polls)
+#define pollmax ((loop)->pollmax)
+#define pollcnt ((loop)->pollcnt)
+#define pollidxs ((loop)->pollidxs)
+#define pollidxmax ((loop)->pollidxmax)
+#define epoll_fd ((loop)->epoll_fd)
+#define epoll_events ((loop)->epoll_events)
+#define epoll_eventmax ((loop)->epoll_eventmax)
+#define kqueue_fd ((loop)->kqueue_fd)
+#define kqueue_changes ((loop)->kqueue_changes)
+#define kqueue_changemax ((loop)->kqueue_changemax)
+#define kqueue_changecnt ((loop)->kqueue_changecnt)
+#define kqueue_events ((loop)->kqueue_events)
+#define kqueue_eventmax ((loop)->kqueue_eventmax)
+#define anfds ((loop)->anfds)
+#define anfdmax ((loop)->anfdmax)
+#define pendings ((loop)->pendings)
+#define pendingmax ((loop)->pendingmax)
+#define pendingcnt ((loop)->pendingcnt)
+#define fdchanges ((loop)->fdchanges)
+#define fdchangemax ((loop)->fdchangemax)
+#define fdchangecnt ((loop)->fdchangecnt)
+#define timers ((loop)->timers)
+#define timermax ((loop)->timermax)
+#define timercnt ((loop)->timercnt)
+#define periodics ((loop)->periodics)
+#define periodicmax ((loop)->periodicmax)
+#define periodiccnt ((loop)->periodiccnt)
+#define idles ((loop)->idles)
+#define idlemax ((loop)->idlemax)
+#define idlecnt ((loop)->idlecnt)
+#define prepares ((loop)->prepares)
+#define preparemax ((loop)->preparemax)
+#define preparecnt ((loop)->preparecnt)
+#define checks ((loop)->checks)
+#define checkmax ((loop)->checkmax)
+#define checkcnt ((loop)->checkcnt)
+#define childs ((loop)->childs)
+#define childev ((loop)->childev)
+#define sigev ((loop)->sigev)
#include "event.h"
-#ifdef EV_MULTIPLICITY
-# define dLOOPev struct ev_loop *loop = ev->ev_base->loop
-# define dLOOPbase struct ev_loop *loop = base->loop
+#if EV_MULTIPLICITY
+# define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
+# define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
#else
# define dLOOPev
# define dLOOPbase
#endif
+/* never accessed, will always be cast from/to ev_loop */
struct event_base
{
-#ifdef EV_MULTIPLICITY
- struct ev_loop *loop;
-#endif
int dummy;
};
void *event_init (void)
{
- if (!x_cur && ev_init (0))
- return x_cur = &x_base;
+#if EV_MULTIPLICITY
+ x_cur = (struct event_base *)ev_loop_new (EVMETHOD_AUTO);
+#else
+ x_cur = &x_base;
+#endif
- return 0;
+ return x_cur;
}
void event_base_free (struct event_base *base)
{
dLOOPbase;
- /* nop */
+#if EV_MULTIPLICITY
+ ev_loop_delete (loop);
+#endif
}
int event_dispatch (void)
struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
if (!(ev->ev_events & EV_PERSIST) && ev_is_active (w))
- ev_io_stop (w);
+ ev_io_stop (EV_A_ w);
x_cb (ev, revents);
}
void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
{
- if (events & EV_SIGNAL)
- ev_watcher_init (&ev->iosig.sig, x_cb_sig);
- else
- ev_watcher_init (&ev->iosig.io, x_cb_io);
+ if (!ev->initialised)
+ {
+ ev->initialised = 1;
+
+ if (events & EV_SIGNAL)
+ ev_watcher_init (&ev->iosig.sig, x_cb_sig);
+ else
+ ev_watcher_init (&ev->iosig.io, x_cb_io);
- ev_watcher_init (&ev->to, x_cb_to);
+ ev_watcher_init (&ev->to, x_cb_to);
+ }
- ev->ev_base = x_cur;
+ ev->ev_base = x_cur; /* not threadsafe, but its like libevent works */
ev->ev_fd = fd;
ev->ev_events = events;
ev->ev_pri = 0;
}
static void
-x_loopexit_cb (EV_P_ int revents, void *arg)
+x_loopexit_cb (int revents, void *base)
{
- ev_unloop (EV_A_ 2);
+ dLOOPbase;
+
+ ev_unloop (EV_A_ EVUNLOOP_ONCE);
}
int event_base_loopexit (struct event_base *base, struct timeval *tv)
int ev_pri;
int ev_res;
short ev_events;
+
+ char initialised; /* flag to work around some idiosynchrasies in the API */
};
#define EV_PERSIST 0x10
#define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd)
#define EVENT_FD(ev) ((int) (ev)->ev_fd)
-#define event_initialized(ev) 1
+#define event_initialized(ev) ((ev)->initialised)
#define evtimer_add(ev,tv) event_add (ev, tv)
#define evtimer_set(ev,cb,data) event_set (ev, -1, 0, cb, data)
--- /dev/null
+#!/bin/sh
+
+(
+ echo '#define VAR(name,decl) define name ((loop)->name)'
+ echo '#define EV_GENWRAP 1'
+ cat ev_vars.h
+) | cc -E -o - - | sed -e 's/define/#define/' | grep '#define' | (
+ echo "/* DO NOT EDIT, automaticlaly generated by update_ev_wrap */"
+ cat
+) | tee ev_wrap.h