From: root Date: Sun, 4 Nov 2007 00:24:16 +0000 (+0000) Subject: wow the event api is broken X-Git-Tag: rel-0_5~27 X-Git-Url: https://git.llucax.com/software/libev.git/commitdiff_plain/678c8c54d0ce967d8f1db3e575aed61879279975 wow the event api is broken --- diff --git a/ev.c b/ev.c index 8c05776..300049e 100644 --- a/ev.c +++ b/ev.c @@ -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; diff --git a/ev.h b/ev.h index 208ee70..d98fe8e 100644 --- a/ev.h +++ b/ev.h @@ -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 */ diff --git a/ev_select.c b/ev_select.c index 05dc30a..5738fe5 100644 --- a/ev_select.c +++ b/ev_select.c @@ -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); } } diff --git a/ev_vars.h b/ev_vars.h index 1c7505e..e3c1f0e 100644 --- a/ev_vars.h +++ b/ev_vars.h @@ -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(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 diff --git a/ev_wrap.h b/ev_wrap.h new file mode 100644 index 0000000..379ed74 --- /dev/null +++ b/ev_wrap.h @@ -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) diff --git a/event.c b/event.c index 1c2bc73..75cd06b 100644 --- a/event.c +++ b/event.c @@ -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; + + 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; @@ -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) diff --git a/event.h b/event.h index 1bc88d2..d21ed3f 100644 --- a/event.h +++ b/event.h @@ -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) diff --git a/update_ev_wrap b/update_ev_wrap new file mode 100755 index 0000000..32ab625 --- /dev/null +++ b/update_ev_wrap @@ -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