]> git.llucax.com Git - software/libev.git/commitdiff
implement idle and check watchers, rmeove flawed hook system
authorroot <root>
Wed, 31 Oct 2007 07:24:17 +0000 (07:24 +0000)
committerroot <root>
Wed, 31 Oct 2007 07:24:17 +0000 (07:24 +0000)
ev.c
ev.h

diff --git a/ev.c b/ev.c
index e328df3b23a116c88e440e319347537a591cc9d2..5b59ae1d71ff2e9944e9a08891dadd15c1ec81ef 100644 (file)
--- a/ev.c
+++ b/ev.c
@@ -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;
diff --git a/ev.h b/ev.h
index 9290378aa5df3caae305ff06077e64cd260c92aa..36f35a5c5be9c82fa312a955224068190c36b4db 100644 (file)
--- a/ev.h
+++ b/ev.h
@@ -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