Browse Source

implement idle and check watchers, rmeove flawed hook system

master
Marc Alexander Lehmann 13 years ago
parent
commit
8a712bb7dd
2 changed files with 116 additions and 46 deletions
  1. +79
    -28
      ev.c
  2. +37
    -18
      ev.h

+ 79
- 28
ev.c View File

@ -141,6 +141,15 @@ fd_event (int fd, int events)
}
}
static void
queue_events (struct ev_watcher **events, int eventcnt, int type)
{
int i;
for (i = 0; i < eventcnt; ++i)
event (events [i], type);
}
/*****************************************************************************/
static struct ev_timer **atimers;
@ -263,6 +272,14 @@ siginit (void)
/*****************************************************************************/
static struct ev_idle **idles;
static int idlemax, idlecnt;
static struct ev_check **checks;
static int checkmax, checkcnt;
/*****************************************************************************/
#if HAVE_EPOLL
# include "ev_epoll.c"
#endif
@ -330,27 +347,6 @@ void ev_postfork_child (void)
/*****************************************************************************/
static ev_hook hooks [EVHOOK_NUM];
void
ev_hook_register (int type, ev_hook hook)
{
hooks [type] = hook;
}
void
ev_hook_unregister (int type, ev_hook hook)
{
hooks [type] = 0;
}
static void
hook_call (int type)
{
if (hooks [type])
hooks [type] ();
}
static void
fd_reify (void)
{
@ -472,15 +468,19 @@ void ev_loop (int flags)
double block;
ev_loop_done = flags & EVLOOP_ONESHOT;
do
if (checkcnt)
{
hook_call (EVHOOK_PREPOLL);
queue_events (checks, checkcnt, EV_CHECK);
call_pending ();
}
do
{
/* update fd-related kernel structures */
fd_reify ();
/* calculate blocking time */
if (flags & EVLOOP_NONBLOCK)
if (flags & EVLOOP_NONBLOCK || idlecnt)
block = 0.;
else
{
@ -506,14 +506,19 @@ void ev_loop (int flags)
/* update ev_now, do magic */
time_update ();
hook_call (EVHOOK_POSTPOLL);
/* put pending timers into pendign queue and reschedule them */
/* queue pending timers and reschedule them */
/* absolute timers first */
timers_reify (atimers, atimercnt, ev_now);
/* relative timers second */
timers_reify (rtimers, rtimercnt, now);
/* queue idle watchers unless io or timers are pending */
if (!pendingcnt)
queue_events (idles, idlecnt, EV_IDLE);
/* queue check and possibly idle watchers */
queue_events (checks, checkcnt, EV_CHECK);
call_pending ();
}
while (!ev_loop_done);
@ -681,6 +686,38 @@ evsignal_stop (struct ev_signal *w)
signal (w->signum, SIG_DFL);
}
void evidle_start (struct ev_idle *w)
{
if (ev_is_active (w))
return;
ev_start ((struct ev_watcher *)w, ++idlecnt);
array_needsize (idles, idlemax, idlecnt, );
idles [idlecnt - 1] = w;
}
void evidle_stop (struct ev_idle *w)
{
idles [w->active - 1] = idles [--idlecnt];
ev_stop ((struct ev_watcher *)w);
}
void evcheck_start (struct ev_check *w)
{
if (ev_is_active (w))
return;
ev_start ((struct ev_watcher *)w, ++checkcnt);
array_needsize (checks, checkmax, checkcnt, );
checks [checkcnt - 1] = w;
}
void evcheck_stop (struct ev_check *w)
{
checks [w->active - 1] = checks [--checkcnt];
ev_stop ((struct ev_watcher *)w);
}
/*****************************************************************************/
#if 1
@ -704,6 +741,12 @@ scb (struct ev_signal *w, int revents)
fprintf (stderr, "signal %x,%d\n", revents, w->signum);
}
static void
gcb (struct ev_signal *w, int revents)
{
fprintf (stderr, "generic %x\n", revents);
}
int main (void)
{
struct ev_io sin;
@ -716,7 +759,7 @@ int main (void)
struct ev_timer t[10000];
#if 1
#if 0
int i;
for (i = 0; i < 10000; ++i)
{
@ -739,6 +782,14 @@ int main (void)
evsignal_set (&sig, SIGQUIT);
evsignal_start (&sig);
struct ev_check cw;
evw_init (&cw, gcb, 0);
evcheck_start (&cw);
struct ev_idle iw;
evw_init (&iw, gcb, 0);
evidle_start (&iw);
ev_loop (0);
return 0;


+ 37
- 18
ev.h View File

@ -5,23 +5,26 @@ typedef double ev_tstamp;
/* eventmask, revents, events... */
#define EV_UNDEF -1 /* guaranteed to be invalid */
#define EV_NONE 0
#define EV_READ 1
#define EV_WRITE 2
#define EV_TIMEOUT 4
#define EV_SIGNAL 8
#define EV_NONE 0x00
#define EV_READ 0x01
#define EV_WRITE 0x02
#define EV_TIMEOUT 0x04
#define EV_SIGNAL 0x08
#define EV_IDLE 0x10
#define EV_CHECK 0x20
/* shared by all watchers */
#define EV_WATCHER(type) \
int active; /* private */ \
int pending; /* private */ \
void *data; /* rw */ \
void (*cb)(struct type *, int revents) /* rw */
void (*cb)(struct type *, int revents) /* rw */ /* gets invoked with an eventmask */
#define EV_WATCHER_LIST(type) \
EV_WATCHER (type); \
struct type *next /* private */
/* invoked at a specific time or after a specific time, repeatable */
struct ev_timer
{
EV_WATCHER_LIST (ev_timer);
@ -31,6 +34,7 @@ struct ev_timer
unsigned char is_abs; /* ro */
};
/* invoked when fd is either EV_READable or EV_WRITEable */
struct ev_io
{
EV_WATCHER_LIST (ev_io);
@ -39,6 +43,7 @@ struct ev_io
int events; /* ro */
};
/* invoked when the given signal has been received */
struct ev_signal
{
EV_WATCHER_LIST (ev_signal);
@ -46,12 +51,25 @@ struct ev_signal
int signum; /* ro */
};
/* invoked when the nothing else needs to be done, keeps the process from blocking */
struct ev_idle
{
EV_WATCHER (ev_idle);
};
/* invoked for each run of the mainloop, just before the next blocking vall is initiated */
struct ev_check
{
EV_WATCHER (ev_check);
};
#define EVMETHOD_NONE 0
#define EVMETHOD_SELECT 1
#define EVMETHOD_EPOLL 2
int ev_init (int flags);
int ev_init (int flags); /* returns ev_method */
extern int ev_method;
/* these three calls are suitable for plugging into pthread_atfork */
void ev_prefork (void);
void ev_postfork_parent (void);
void ev_postfork_child (void);
@ -64,13 +82,6 @@ ev_tstamp ev_time (void);
void ev_loop (int flags);
extern int ev_loop_done; /* set to 1 to break out of event loop */
#define EVHOOK_PREPOLL 0 /* called before updating fds, timers and blocking */
#define EVHOOK_POSTPOLL 1 /* called after blocking */
#define EVHOOK_NUM 2 /* just the # of hooks */
typedef void (*ev_hook)(void);
void ev_hook_register (int type, ev_hook hook);
void ev_hook_unregister (int type, ev_hook hook);
/* these may evaluate ev multiple times, and the other arguments at most once */
#define evw_init(ev,cb_,data_) do { (ev)->active = 0; (ev)->cb = (cb_); (ev)->data = (void *)data_; } while (0)
@ -81,14 +92,22 @@ void ev_hook_unregister (int type, ev_hook hook);
#define ev_is_active(ev) (0 + (ev)->active) /* true when the watcher has been started */
void evio_start (struct ev_io *w);
void evio_stop (struct ev_io *w);
/* stopping (enabling, adding) a watcher does nothing if it is already running */
/* stopping (disabling, deleting) a watcher does nothing unless its already running */
void evio_start (struct ev_io *w);
void evio_stop (struct ev_io *w);
void evtimer_start (struct ev_timer *w);
void evtimer_stop (struct ev_timer *w);
void evtimer_start (struct ev_timer *w);
void evtimer_stop (struct ev_timer *w);
void evsignal_start (struct ev_signal *w);
void evsignal_stop (struct ev_signal *w);
void evidle_start (struct ev_idle *w);
void evidle_stop (struct ev_idle *w);
void evcheck_start (struct ev_check *w);
void evcheck_stop (struct ev_check *w);
#endif

Loading…
Cancel
Save