wow the event api is broken

This commit is contained in:
Marc Alexander Lehmann 2007-11-04 00:24:16 +00:00
parent b26997b104
commit 6e886dc713
8 changed files with 256 additions and 126 deletions

113
ev.c
View File

@ -115,6 +115,8 @@ typedef struct ev_watcher *W;
typedef struct ev_watcher_list *WL;
typedef struct ev_watcher_time *WT;
static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
/*****************************************************************************/
typedef struct
@ -131,16 +133,22 @@ 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
/*****************************************************************************/
@ -335,44 +343,44 @@ fd_enomem (EV_P)
/*****************************************************************************/
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;
}
/*****************************************************************************/
@ -447,7 +455,7 @@ siginit (EV_P)
#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 */
}
@ -536,13 +544,9 @@ ev_method (EV_P)
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
@ -556,7 +560,7 @@ ev_init (EV_P_ int methods)
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;
@ -599,6 +603,35 @@ ev_init (EV_P_ int methods)
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
@ -616,16 +649,19 @@ ev_fork_parent (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
}
/*****************************************************************************/
@ -665,7 +701,7 @@ timers_reify (EV_P)
else
ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */
event ((W)w, EV_TIMEOUT);
event (EV_A_ (W)w, EV_TIMEOUT);
}
}
@ -691,7 +727,7 @@ periodics_reify (EV_P)
}
static void
periodics_reschedule (EV_P_ ev_tstamp diff)
periodics_reschedule (EV_P)
{
int i;
@ -722,7 +758,7 @@ time_update_monotonic (EV_P)
if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5))
{
rt_now = mn_now + diff;
rt_now = rtmn_diff + mn_now;
return 0;
}
else
@ -743,13 +779,13 @@ time_update (EV_P)
{
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 ();
@ -757,8 +793,9 @@ time_update (EV_P)
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
@ -768,11 +805,11 @@ time_update (EV_P)
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;

28
ev.h
View File

@ -44,8 +44,12 @@ typedef double ev_tstamp;
# 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,
@ -56,7 +60,6 @@ struct ev_loop;
# define EV_P_
# define EV_A
# define EV_A_
#endif
/* eventmask, revents, events... */
@ -155,6 +158,9 @@ struct ev_io
struct ev_signal
{
EV_WATCHER_LIST (ev_signal);
#if EV_MULTIPLICITY
struct ev_loop *loop;
#endif
int signum; /* ro */
};
@ -201,9 +207,8 @@ struct ev_child
#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);
@ -213,13 +218,26 @@ void ev_fork_parent (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 */

View File

@ -107,7 +107,7 @@ select_poll (EV_P_ ev_tstamp timeout)
events |= byte_w & (1 << bit) ? EV_WRITE : 0;
if (events)
fd_event (idx * 8 + bit, events);
fd_event (EV_A_ idx * 8 + bit, events);
}
}
}
@ -115,9 +115,9 @@ select_poll (EV_P_ ev_tstamp timeout)
else if (res < 0)
{
if (errno == EBADF)
fd_ebadf ();
fd_ebadf (EV_A);
else if (errno == ENOMEM)
fd_enomem ();
fd_enomem (EV_A);
}
}

118
ev_vars.h
View File

@ -1,86 +1,84 @@
#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(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(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(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 */
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);
#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

55
ev_wrap.h Normal file
View File

@ -0,0 +1,55 @@
/* 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)

48
event.c
View File

@ -35,19 +35,17 @@
#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;
};
@ -83,17 +81,22 @@ const char *event_get_method (void)
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)
@ -139,7 +142,7 @@ x_cb_io (EV_P_ struct ev_io *w, int revents)
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);
}
@ -152,14 +155,19 @@ x_cb_to (EV_P_ struct ev_timer *w, int 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;
ev_watcher_init (&ev->to, x_cb_to);
if (events & EV_SIGNAL)
ev_watcher_init (&ev->iosig.sig, x_cb_sig);
else
ev_watcher_init (&ev->iosig.io, x_cb_io);
ev->ev_base = x_cur;
ev_watcher_init (&ev->to, x_cb_to);
}
ev->ev_base = x_cur; /* not threadsafe, but its like libevent works */
ev->ev_fd = fd;
ev->ev_events = events;
ev->ev_pri = 0;
@ -287,9 +295,11 @@ int event_base_dispatch (struct event_base *base)
}
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)

View File

@ -54,6 +54,8 @@ struct event
int ev_pri;
int ev_res;
short ev_events;
char initialised; /* flag to work around some idiosynchrasies in the API */
};
#define EV_PERSIST 0x10
@ -61,7 +63,7 @@ struct event
#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)

10
update_ev_wrap Executable file
View File

@ -0,0 +1,10 @@
#!/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