diff options
| author | root <root> | 2007-10-31 07:24:17 +0000 | 
|---|---|---|
| committer | root <root> | 2007-10-31 07:24:17 +0000 | 
| commit | 6c9b968485dc8690f81ae6626c07a82a4e085eb1 (patch) | |
| tree | 1f1fbd90c0dae4d9372fe50cdbe5668781720593 | |
| parent | eec85cf766fbaa1ee090c8daaf5b4a501f890f63 (diff) | |
implement idle and check watchers, rmeove flawed hook system
| -rw-r--r-- | ev.c | 107 | ||||
| -rw-r--r-- | ev.h | 55 | 
2 files changed, 116 insertions, 46 deletions
@@ -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; @@ -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  | 
