diff options
author | root <root> | 2009-07-10 19:10:19 +0000 |
---|---|---|
committer | root <root> | 2009-07-10 19:10:19 +0000 |
commit | 9a4bdcd75ef07d4a9fee91d2dd3f9d4ac1c57580 (patch) | |
tree | 0aadce32eacc79b88ac6226d3333c3b4aea10228 | |
parent | fe7f056cfc2dc30ab33a1e36b0005fa1e39b0e50 (diff) |
*** empty log message ***
-rw-r--r-- | Changes | 3 | ||||
-rw-r--r-- | ev.c | 47 | ||||
-rw-r--r-- | ev.h | 12 | ||||
-rw-r--r-- | ev.pod | 5 | ||||
-rw-r--r-- | ev_epoll.c | 4 | ||||
-rw-r--r-- | ev_kqueue.c | 4 | ||||
-rw-r--r-- | ev_poll.c | 4 | ||||
-rw-r--r-- | ev_port.c | 4 | ||||
-rw-r--r-- | ev_select.c | 4 | ||||
-rw-r--r-- | ev_vars.h | 11 | ||||
-rw-r--r-- | ev_wrap.h | 16 |
11 files changed, 65 insertions, 49 deletions
@@ -3,8 +3,11 @@ Revision history for libev, a high-performance and full-featured event loop. TODO: ev_walk TODO: remain TODO: on_call_pending, on_suspend_resume ev_invoke_pending (EV_P) +TODO: EV_MINIMAL - ev_unloop and ev_loop wrongly used a global variable to exit loops, instead of using a per-loop variable (bug caught by accident...). + - calling ev_unloop in fork/prepare watchers will no longer poll + for new events. - Denis F. Latypoff corrected many typos in example code snippets. - the ev_set_io_collect_interval interpretation has changed. - honor autoconf detection of EV_USE_CLOCK_SYSCALL, also double- @@ -492,12 +492,15 @@ ev_realloc (void *ptr, long size) /*****************************************************************************/ +/* set in reify when reification needed */ +#define EV_ANFD_REIFY 1 + /* file descriptor info structure */ typedef struct { WL head; unsigned char events; /* the events watched for */ - unsigned char reify; /* flag set when this ANFD needs reification */ + unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */ unsigned char emask; /* the epoll backend stores the actual kernel mask in here */ unsigned char unused; #if EV_USE_EPOLL @@ -570,15 +573,17 @@ typedef struct #endif #if EV_MINIMAL < 2 -# define EV_SUSPEND_CB if (expect_false (suspend_cb)) suspend_cb (EV_A) -# define EV_RESUME_CB if (expect_false (resume_cb )) resume_cb (EV_A) +# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A) +# define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A) # define EV_INVOKE_PENDING invoke_cb (EV_A) #else -# define EV_SUSPEND_CB (void)0 -# define EV_RESUME_CB (void)0 +# define EV_RELEASE_CB (void)0 +# define EV_ACQUIRE_CB (void)0 # define EV_INVOKE_PENDING ev_invoke_pending (EV_A) #endif +#define EVUNLOOP_RECURSE 0x80 + /*****************************************************************************/ #ifndef EV_HAVE_EV_TIME @@ -762,7 +767,7 @@ queue_events (EV_P_ W *events, int eventcnt, int type) /*****************************************************************************/ inline_speed void -fd_event (EV_P_ int fd, int revents) +fd_event_nc (EV_P_ int fd, int revents) { ANFD *anfd = anfds + fd; ev_io *w; @@ -776,11 +781,22 @@ fd_event (EV_P_ int fd, int revents) } } +/* do not submit kernel events for fds that have reify set */ +/* because that means they changed while we were polling for new events */ +inline_speed void +fd_event (EV_P_ int fd, int revents) +{ + ANFD *anfd = anfds + fd; + + if (expect_true (!anfd->reify)) + fd_event_nc (EV_A_ fd, revents); +} + void ev_feed_fd_event (EV_P_ int fd, int revents) { if (fd >= 0 && fd < anfdmax) - fd_event (EV_A_ fd, revents); + fd_event_nc (EV_A_ fd, revents); } /* make sure the external fd watch events are in-sync */ @@ -905,7 +921,7 @@ fd_rearm_all (EV_P) { anfds [fd].events = 0; anfds [fd].emask = 0; - fd_change (EV_A_ fd, EV__IOFDSET | 1); + fd_change (EV_A_ fd, EV__IOFDSET | EV_ANFD_REIFY); } } @@ -1411,10 +1427,10 @@ void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P)) invoke_cb = invoke_pending_cb; } -void ev_set_blocking_cb (EV_P_ void (*suspend_cb_)(EV_P), void (*resume_cb_)(EV_P)) +void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P)) { - suspend_cb = suspend_cb_; - resume_cb = resume_cb_; + release_cb = release; + acquire_cb = acquire; } #endif @@ -2079,6 +2095,8 @@ ev_loop (EV_P_ int flags) ++loop_depth; #endif + assert (("libev: ev_loop recursion during release detected", loop_done != EVUNLOOP_RECURSE)); + loop_done = EVUNLOOP_CANCEL; EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ @@ -2115,6 +2133,9 @@ ev_loop (EV_P_ int flags) EV_INVOKE_PENDING; } + if (expect_false (loop_done)) + break; + /* we might have forked, so reify kernel state if necessary */ if (expect_false (postfork)) loop_fork (EV_A); @@ -2174,7 +2195,9 @@ ev_loop (EV_P_ int flags) #if EV_MINIMAL < 2 ++loop_count; #endif + assert ((loop_done = EVUNLOOP_RECURSE, 1)); /* assert for side effect */ backend_poll (EV_A_ waittime); + assert ((loop_done = EVUNLOOP_CANCEL, 1)); /* assert for side effect */ /* update ev_rt_now, do magic */ time_update (EV_A_ waittime + sleeptime); @@ -2350,7 +2373,7 @@ ev_io_start (EV_P_ ev_io *w) array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero); wlist_add (&anfds[fd].head, (WL)w); - fd_change (EV_A_ fd, w->events & EV__IOFDSET | 1); + fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY); w->events &= ~EV__IOFDSET; EV_FREQUENT_CHECK; @@ -547,19 +547,11 @@ void ev_loop_verify (EV_P); /* abort if loop data corrupted */ void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */ void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */ -/* - * a single void * can be attached to each loop. this is intended - * to aid the invoke_pending/blocking callbacks. - */ +/* advanced stuff for threading etc. support, see docs */ void ev_set_userdata (EV_P_ void *data); void *ev_userdata (EV_P); - -/* - * hooks to overide how and when libev invokes callbacks, - * and hooks that wrap the actual eventloop blocking call. - */ void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P)); -void ev_set_blocking_cb (EV_P_ void (*suspend_cb_)(EV_P), void (*resume_cb_)(EV_P)); +void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P)); void ev_invoke_pending (EV_P); /* invoke all pending watchers */ @@ -3678,8 +3678,9 @@ is used to override some inlining decisions, saves roughly 30% code size on amd64. It also selects a much smaller 2-heap for timer management over the default 4-heap. -You can save even more by disabling watcher types you do not need and -setting C<EV_MAXPRI> == C<EV_MINPRI>. +You can save even more by disabling watcher types you do not need +and setting C<EV_MAXPRI> == C<EV_MINPRI>. Also, disabling C<assert> +(C<-DNDEBUG>) will usually reduce code size a lot. Defining C<EV_MINIMAL> to C<2> will additionally reduce the core API to provide a bare-bones event library. See C<ev.h> for details on what parts @@ -121,9 +121,9 @@ epoll_poll (EV_P_ ev_tstamp timeout) int i; int eventcnt; - EV_SUSPEND_CB; + EV_RELEASE_CB; eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.)); - EV_RESUME_CB; + EV_ACQUIRE_CB; if (expect_false (eventcnt < 0)) { diff --git a/ev_kqueue.c b/ev_kqueue.c index 2a9832f..ac73f7c 100644 --- a/ev_kqueue.c +++ b/ev_kqueue.c @@ -85,7 +85,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout) int res, i; struct timespec ts; - EV_SUSPEND_CB; + EV_RELEASE_CB; /* need to resize so there is enough space for errors */ if (kqueue_changecnt > kqueue_eventmax) @@ -100,7 +100,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout) res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); kqueue_changecnt = 0; - EV_RESUME_CB; + EV_ACQUIRE_CB; if (expect_false (res < 0)) { @@ -91,9 +91,9 @@ poll_poll (EV_P_ ev_tstamp timeout) struct pollfd *p; int res; - EV_SUSPEND_CB; + EV_RELEASE_CB; res = poll (polls, pollcnt, (int)ceil (timeout * 1000.)); - EV_RESUME_CB; + EV_ACQUIRE_CB; if (expect_false (res < 0)) { @@ -85,11 +85,11 @@ port_poll (EV_P_ ev_tstamp timeout) struct timespec ts; uint_t nget = 1; - EV_SUSPEND_CB; + EV_RELEASE_CB; ts.tv_sec = (time_t)timeout; ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9; res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts); - EV_RESUME_CB; + EV_ACQUIRE_CB; if (res == -1) { diff --git a/ev_select.c b/ev_select.c index b7bb69d..e57c1e2 100644 --- a/ev_select.c +++ b/ev_select.c @@ -140,7 +140,7 @@ select_poll (EV_P_ ev_tstamp timeout) int res; int fd_setsize; - EV_SUSPEND_CB; + EV_RELEASE_CB; tv.tv_sec = (long)timeout; tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6); @@ -167,7 +167,7 @@ select_poll (EV_P_ ev_tstamp timeout) #else res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); #endif - EV_RESUME_CB; + EV_ACQUIRE_CB; if (expect_false (res < 0)) { @@ -48,7 +48,7 @@ VARx(ev_tstamp, timeout_blocktime) VARx(int, backend) VARx(int, activecnt) /* total number of active events ("refcount") */ -VARx(char, loop_done) /* signal by ev_unloop */ +VARx(unsigned char, loop_done) /* signal by ev_unloop */ VARx(int, backend_fd) VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */ @@ -166,16 +166,13 @@ VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */ VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE]) #endif -#if EV_MINIMAL < 2 +#if EV_MINIMAL < 2 || EV_GENWRAP VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */ VARx(unsigned int, loop_depth) /* #ev_loop enters - #ev_loop leaves */ VARx(void *, userdata) -#endif - -#if EV_MINIMAL < 2 -VAR (suspend_cb, void (*suspend_cb)(EV_P)) -VAR (resume_cb , void (*resume_cb) (EV_P)) +VAR (release_cb, void (*release_cb)(EV_P)) +VAR (acquire_cb, void (*acquire_cb)(EV_P)) VAR (invoke_cb , void (*invoke_cb) (EV_P)) #endif @@ -8,8 +8,6 @@ #define timeout_blocktime ((loop)->timeout_blocktime) #define backend ((loop)->backend) #define activecnt ((loop)->activecnt) -#define loop_count ((loop)->loop_count) -#define loop_depth ((loop)->loop_depth) #define loop_done ((loop)->loop_done) #define backend_fd ((loop)->backend_fd) #define backend_fudge ((loop)->backend_fudge) @@ -79,9 +77,11 @@ #define fs_w ((loop)->fs_w) #define fs_2625 ((loop)->fs_2625) #define fs_hash ((loop)->fs_hash) +#define loop_count ((loop)->loop_count) +#define loop_depth ((loop)->loop_depth) #define userdata ((loop)->userdata) -#define suspend_cb ((loop)->suspend_cb) -#define resume_cb ((loop)->resume_cb) +#define release_cb ((loop)->release_cb) +#define acquire_cb ((loop)->acquire_cb) #define invoke_cb ((loop)->invoke_cb) #else #undef EV_WRAP_H @@ -92,8 +92,6 @@ #undef timeout_blocktime #undef backend #undef activecnt -#undef loop_count -#undef loop_depth #undef loop_done #undef backend_fd #undef backend_fudge @@ -163,8 +161,10 @@ #undef fs_w #undef fs_2625 #undef fs_hash +#undef loop_count +#undef loop_depth #undef userdata -#undef suspend_cb -#undef resume_cb +#undef release_cb +#undef acquire_cb #undef invoke_cb #endif |