]> git.llucax.com Git - software/libev.git/blobdiff - ev.pod
susv3 specifies rounding behaviour to go up, so screw broken osses
[software/libev.git] / ev.pod
diff --git a/ev.pod b/ev.pod
index d40456bbde29d5ea0c0070e55bbdd6aebfff4920..237bdb00aef5c23b4e0a75873cb0914d399124ce 100644 (file)
--- a/ev.pod
+++ b/ev.pod
@@ -488,8 +488,9 @@ usually a better approach for this kind of thing.
 
 Here are the gory details of what C<ev_loop> does:
 
+   - Before the first iteration, call any pending watchers.
    * If there are no active watchers (reference count is zero), return.
-   - Queue prepare watchers and then call all outstanding watchers.
+   - Queue all prepare watchers and then call all outstanding watchers.
    - If we have been forked, recreate the kernel state.
    - Update the kernel state with all outstanding changes.
    - Update the "event loop time".
@@ -738,8 +739,9 @@ it.
 Returns a true value iff the watcher is pending, (i.e. it has outstanding
 events but its callback has not yet been invoked). As long as a watcher
 is pending (but not active) you must not call an init function on it (but
-C<ev_TYPE_set> is safe) and you must make sure the watcher is available to
-libev (e.g. you cnanot C<free ()> it).
+C<ev_TYPE_set> is safe), you must not change its priority, and you must
+make sure the watcher is available to libev (e.g. you cannot C<free ()>
+it).
 
 =item callback ev_cb (ev_TYPE *watcher)
 
@@ -768,6 +770,9 @@ watchers on the same event and make sure one is called first.
 If you need to suppress invocation when higher priority events are pending
 you need to look at C<ev_idle> watchers, which provide this functionality.
 
+You I<must not> change the priority of a watcher as long as it is active or
+pending.
+
 The default priority used by watchers when no priority has been set is
 always C<0>, which is supposed to not be too high and not be too low :).
 
@@ -775,6 +780,18 @@ Setting a priority outside the range of C<EV_MINPRI> to C<EV_MAXPRI> is
 fine, as long as you do not mind that the priority value you query might
 or might not have been adjusted to be within valid range.
 
+=item ev_invoke (loop, ev_TYPE *watcher, int revents)
+
+Invoke the C<watcher> with the given C<loop> and C<revents>. Neither
+C<loop> nor C<revents> need to be valid as long as the watcher callback
+can deal with that fact.
+
+=item int ev_clear_pending (loop, ev_TYPE *watcher)
+
+If the watcher is pending, this function returns clears its pending status
+and returns its C<revents> bitset (as if its callback was invoked). If the
+watcher isn't pending it does nothing and returns C<0>.
+
 =back
 
 
@@ -1467,6 +1484,16 @@ of lower priority, but only once, using idle watchers to keep the event
 loop from blocking if lower-priority coroutines are active, thus mapping
 low-priority coroutines to idle/background tasks).
 
+It is recommended to give C<ev_check> watchers highest (C<EV_MAXPRI>)
+priority, to ensure that they are being run before any other watchers
+after the poll. Also, C<ev_check> watchers (and C<ev_prepare> watchers,
+too) should not activate ("feed") events into libev. While libev fully
+supports this, they will be called before other C<ev_check> watchers did
+their job. As C<ev_check> watchers are often used to embed other event
+loops those other event loops might be in an unusable state until their
+C<ev_check> watcher ran (always remind yourself to coexist peacefully with
+others).
+
 =over 4
 
 =item ev_prepare_init (ev_prepare *, callback)
@@ -1479,10 +1506,18 @@ macros, but using them is utterly, utterly and completely pointless.
 
 =back
 
-Example: To include a library such as adns, you would add IO watchers
-and a timeout watcher in a prepare handler, as required by libadns, and
-in a check watcher, destroy them and call into libadns. What follows is
-pseudo-code only of course:
+There are a number of principal ways to embed other event loops or modules
+into libev. Here are some ideas on how to include libadns into libev
+(there is a Perl module named C<EV::ADNS> that does this, which you could
+use for an actually working example. Another Perl module named C<EV::Glib>
+embeds a Glib main context into libev, and finally, C<Glib::EV> embeds EV
+into the Glib event loop).
+
+Method 1: Add IO watchers and a timeout watcher in a prepare handler,
+and in a check watcher, destroy them and call into libadns. What follows
+is pseudo-code only of course. This requires you to either use a low
+priority for the check watcher or use C<ev_clear_pending> explicitly, as
+the callbacks for the IO/timeout watchers might not have been called yet.
 
   static ev_io iow [nfd];
   static ev_timer tw;
@@ -1490,11 +1525,6 @@ pseudo-code only of course:
   static void
   io_cb (ev_loop *loop, ev_io *w, int revents)
   {
-    // set the relevant poll flags
-    // could also call adns_processreadable etc. here
-    struct pollfd *fd = (struct pollfd *)w->data;
-    if (revents & EV_READ ) fd->revents |= fd->events & POLLIN;
-    if (revents & EV_WRITE) fd->revents |= fd->events & POLLOUT;
   }
 
   // create io watchers for each fd and a timer before blocking
@@ -1510,7 +1540,7 @@ pseudo-code only of course:
     ev_timer_init (&tw, 0, timeout * 1e-3);
     ev_timer_start (loop, &tw);
 
-    // create on ev_io per pollfd
+    // create one ev_io per pollfd
     for (int i = 0; i < nfd; ++i)
       {
         ev_io_init (iow + i, io_cb, fds [i].fd,
@@ -1518,7 +1548,6 @@ pseudo-code only of course:
            | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
 
         fds [i].revents = 0;
-        iow [i].data = fds + i;
         ev_io_start (loop, iow + i);
       }
   }
@@ -1530,11 +1559,80 @@ pseudo-code only of course:
     ev_timer_stop (loop, &tw);
 
     for (int i = 0; i < nfd; ++i)
-      ev_io_stop (loop, iow + i);
+      {
+        // set the relevant poll flags
+        // could also call adns_processreadable etc. here
+        struct pollfd *fd = fds + i;
+        int revents = ev_clear_pending (iow + i);
+        if (revents & EV_READ ) fd->revents |= fd->events & POLLIN;
+        if (revents & EV_WRITE) fd->revents |= fd->events & POLLOUT;
+
+        // now stop the watcher
+        ev_io_stop (loop, iow + i);
+      }
 
     adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop));
   }
 
+Method 2: This would be just like method 1, but you run C<adns_afterpoll>
+in the prepare watcher and would dispose of the check watcher.
+
+Method 3: If the module to be embedded supports explicit event
+notification (adns does), you can also make use of the actual watcher
+callbacks, and only destroy/create the watchers in the prepare watcher.
+
+  static void
+  timer_cb (EV_P_ ev_timer *w, int revents)
+  {
+    adns_state ads = (adns_state)w->data;
+    update_now (EV_A);
+
+    adns_processtimeouts (ads, &tv_now);
+  }
+
+  static void
+  io_cb (EV_P_ ev_io *w, int revents)
+  {
+    adns_state ads = (adns_state)w->data;
+    update_now (EV_A);
+
+    if (revents & EV_READ ) adns_processreadable  (ads, w->fd, &tv_now);
+    if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
+  }
+
+  // do not ever call adns_afterpoll
+
+Method 4: Do not use a prepare or check watcher because the module you
+want to embed is too inflexible to support it. Instead, youc na override
+their poll function.  The drawback with this solution is that the main
+loop is now no longer controllable by EV. The C<Glib::EV> module does
+this.
+
+  static gint
+  event_poll_func (GPollFD *fds, guint nfds, gint timeout)
+  {
+    int got_events = 0;
+
+    for (n = 0; n < nfds; ++n)
+      // create/start io watcher that sets the relevant bits in fds[n] and increment got_events
+
+    if (timeout >= 0)
+      // create/start timer
+
+    // poll
+    ev_loop (EV_A_ 0);
+
+    // stop timer again
+    if (timeout >= 0)
+      ev_timer_stop (EV_A_ &to);
+
+    // stop io watchers again - their callbacks should have set
+    for (n = 0; n < nfds; ++n)
+      ev_io_stop (EV_A_ iow [n]);
+
+    return got_events;
+  }
+
 
 =head2 C<ev_embed> - when one backend isn't enough...
 
@@ -1830,14 +1928,21 @@ Example: simple class declaration and watcher initialisation
   ev::io iow;
   iow.set <myclass, &myclass::io_cb> (&obj);
 
-=item w->set (void (*function)(watcher &w, int), void *data = 0)
+=item w->set<function> (void *data = 0)
 
 Also sets a callback, but uses a static method or plain function as
 callback. The optional C<data> argument will be stored in the watcher's
 C<data> member and is free for you to use.
 
+The prototype of the C<function> must be C<void (*)(ev::TYPE &w, int)>.
+
 See the method-C<set> above for more details.
 
+Example:
+
+  static void io_cb (ev::io &w, int revents) { }
+  iow.set <io_cb> ();
+
 =item w->set (struct ev_loop *)
 
 Associates a different C<struct ev_loop> with this watcher. You can only