]> git.llucax.com Git - software/libev.git/commitdiff
*** empty log message ***
authorroot <root>
Sat, 8 Dec 2007 15:30:26 +0000 (15:30 +0000)
committerroot <root>
Sat, 8 Dec 2007 15:30:26 +0000 (15:30 +0000)
ev.3
ev.html
ev.pod

diff --git a/ev.3 b/ev.3
index 8e5a19f59908d4276eb9fd4038db2623680de28b..5e213b8ef0265079e4af8870359fb83a03895cd0 100644 (file)
--- a/ev.3
+++ b/ev.3
@@ -1646,25 +1646,28 @@ Initialises and configures the prepare or check watcher \- they have no
 parameters of any kind. There are \f(CW\*(C`ev_prepare_set\*(C'\fR and \f(CW\*(C`ev_check_set\*(C'\fR
 macros, but using them is utterly, utterly and completely pointless.
 .PP
-Example: To include a library such as adns, you would add \s-1IO\s0 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 \f(CW\*(C`EV::ADNS\*(C'\fR that does this, which you could
+use for an actually working example. Another Perl module named \f(CW\*(C`EV::Glib\*(C'\fR
+embeds a Glib main context into libev, and finally, \f(CW\*(C`Glib::EV\*(C'\fR embeds \s-1EV\s0
+into the Glib event loop).
+.PP
+Method 1: Add \s-1IO\s0 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 \f(CW\*(C`ev_clear_pending\*(C'\fR explicitly, as
+the callbacks for the IO/timeout watchers might not have been called yet.
 .PP
 .Vb 2
 \&  static ev_io iow [nfd];
 \&  static ev_timer tw;
 .Ve
 .PP
-.Vb 9
+.Vb 4
 \&  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;
 \&  }
 .Ve
 .PP
@@ -1686,7 +1689,7 @@ pseudo-code only of course:
 .Ve
 .PP
 .Vb 6
-\&    // 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,
@@ -1694,9 +1697,8 @@ pseudo-code only of course:
 \&           | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
 .Ve
 .PP
-.Vb 5
+.Vb 4
 \&        fds [i].revents = 0;
-\&        iow [i].data = fds + i;
 \&        ev_io_start (loop, iow + i);
 \&      }
 \&  }
@@ -1710,15 +1712,110 @@ pseudo-code only of course:
 \&    ev_timer_stop (loop, &tw);
 .Ve
 .PP
-.Vb 2
+.Vb 8
 \&    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;
+.Ve
+.PP
+.Vb 3
+\&        // now stop the watcher
+\&        ev_io_stop (loop, iow + i);
+\&      }
 .Ve
 .PP
 .Vb 2
 \&    adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop));
 \&  }
 .Ve
+.PP
+Method 2: This would be just like method 1, but you run \f(CW\*(C`adns_afterpoll\*(C'\fR
+in the prepare watcher and would dispose of the check watcher.
+.PP
+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.
+.PP
+.Vb 5
+\&  static void
+\&  timer_cb (EV_P_ ev_timer *w, int revents)
+\&  {
+\&    adns_state ads = (adns_state)w->data;
+\&    update_now (EV_A);
+.Ve
+.PP
+.Vb 2
+\&    adns_processtimeouts (ads, &tv_now);
+\&  }
+.Ve
+.PP
+.Vb 5
+\&  static void
+\&  io_cb (EV_P_ ev_io *w, int revents)
+\&  {
+\&    adns_state ads = (adns_state)w->data;
+\&    update_now (EV_A);
+.Ve
+.PP
+.Vb 3
+\&    if (revents & EV_READ ) adns_processreadable  (ads, w->fd, &tv_now);
+\&    if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
+\&  }
+.Ve
+.PP
+.Vb 1
+\&  // do not ever call adns_afterpoll
+.Ve
+.PP
+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 \s-1EV\s0. The \f(CW\*(C`Glib::EV\*(C'\fR module does
+this.
+.PP
+.Vb 4
+\&  static gint
+\&  event_poll_func (GPollFD *fds, guint nfds, gint timeout)
+\&  {
+\&    int got_events = 0;
+.Ve
+.PP
+.Vb 2
+\&    for (n = 0; n < nfds; ++n)
+\&      // create/start io watcher that sets the relevant bits in fds[n] and increment got_events
+.Ve
+.PP
+.Vb 2
+\&    if (timeout >= 0)
+\&      // create/start timer
+.Ve
+.PP
+.Vb 2
+\&    // poll
+\&    ev_loop (EV_A_ 0);
+.Ve
+.PP
+.Vb 3
+\&    // stop timer again
+\&    if (timeout >= 0)
+\&      ev_timer_stop (EV_A_ &to);
+.Ve
+.PP
+.Vb 3
+\&    // stop io watchers again - their callbacks should have set
+\&    for (n = 0; n < nfds; ++n)
+\&      ev_io_stop (EV_A_ iow [n]);
+.Ve
+.PP
+.Vb 2
+\&    return got_events;
+\&  }
+.Ve
 .ie n .Sh """ev_embed"" \- when one backend isn't enough..."
 .el .Sh "\f(CWev_embed\fP \- when one backend isn't enough..."
 .IX Subsection "ev_embed - when one backend isn't enough..."
diff --git a/ev.html b/ev.html
index 31b2769f0629bcc69b95553a1662a9ec08577cae..1dcdd21a2507721860d38c86722fc8d78ad63c89 100644 (file)
--- a/ev.html
+++ b/ev.html
@@ -6,7 +6,7 @@
        <meta name="description" content="Pod documentation for libev" />
        <meta name="inputfile" content="&lt;standard input&gt;" />
        <meta name="outputfile" content="&lt;standard output&gt;" />
-       <meta name="created" content="Sat Dec  8 15:31:35 2007" />
+       <meta name="created" content="Sat Dec  8 16:30:24 2007" />
        <meta name="generator" content="Pod::Xhtml 1.57" />
 <link rel="stylesheet" href="http://res.tst.eu/pod.css"/></head>
 <body>
@@ -1494,21 +1494,23 @@ parameters of any kind. There are <code>ev_prepare_set</code> and <code>ev_check
 macros, but using them is utterly, utterly and completely pointless.</p>
        </dd>
 </dl>
-<p>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:</p>
+<p>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 <code>EV::ADNS</code> that does this, which you could
+use for an actually working example. Another Perl module named <code>EV::Glib</code>
+embeds a Glib main context into libev, and finally, <code>Glib::EV</code> embeds EV
+into the Glib event loop).</p>
+<p>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 <code>ev_clear_pending</code> explicitly, as
+the callbacks for the IO/timeout watchers might not have been called yet.</p>
 <pre>  static ev_io iow [nfd];
   static ev_timer tw;
 
   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-&gt;data;
-    if (revents &amp; EV_READ ) fd-&gt;revents |= fd-&gt;events &amp; POLLIN;
-    if (revents &amp; EV_WRITE) fd-&gt;revents |= fd-&gt;events &amp; POLLOUT;
   }
 
   // create io watchers for each fd and a timer before blocking
@@ -1524,7 +1526,7 @@ pseudo-code only of course:</p>
     ev_timer_init (&amp;tw, 0, timeout * 1e-3);
     ev_timer_start (loop, &amp;tw);
 
-    // create on ev_io per pollfd
+    // create one ev_io per pollfd
     for (int i = 0; i &lt; nfd; ++i)
       {
         ev_io_init (iow + i, io_cb, fds [i].fd,
@@ -1532,7 +1534,6 @@ pseudo-code only of course:</p>
            | (fds [i].events &amp; POLLOUT ? EV_WRITE : 0)));
 
         fds [i].revents = 0;
-        iow [i].data = fds + i;
         ev_io_start (loop, iow + i);
       }
   }
@@ -1544,11 +1545,79 @@ pseudo-code only of course:</p>
     ev_timer_stop (loop, &amp;tw);
 
     for (int i = 0; i &lt; 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 &amp; EV_READ ) fd-&gt;revents |= fd-&gt;events &amp; POLLIN;
+        if (revents &amp; EV_WRITE) fd-&gt;revents |= fd-&gt;events &amp; POLLOUT;
+
+        // now stop the watcher
+        ev_io_stop (loop, iow + i);
+      }
 
     adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop));
   }
 
+</pre>
+<p>Method 2: This would be just like method 1, but you run <code>adns_afterpoll</code>
+in the prepare watcher and would dispose of the check watcher.</p>
+<p>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.</p>
+<pre>  static void
+  timer_cb (EV_P_ ev_timer *w, int revents)
+  {
+    adns_state ads = (adns_state)w-&gt;data;
+    update_now (EV_A);
+
+    adns_processtimeouts (ads, &amp;tv_now);
+  }
+
+  static void
+  io_cb (EV_P_ ev_io *w, int revents)
+  {
+    adns_state ads = (adns_state)w-&gt;data;
+    update_now (EV_A);
+
+    if (revents &amp; EV_READ ) adns_processreadable  (ads, w-&gt;fd, &amp;tv_now);
+    if (revents &amp; EV_WRITE) adns_processwriteable (ads, w-&gt;fd, &amp;tv_now);
+  }
+
+  // do not ever call adns_afterpoll
+
+</pre>
+<p>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 <code>Glib::EV</code> module does
+this.</p>
+<pre>  static gint
+  event_poll_func (GPollFD *fds, guint nfds, gint timeout)
+  {
+    int got_events = 0;
+
+    for (n = 0; n &lt; nfds; ++n)
+      // create/start io watcher that sets the relevant bits in fds[n] and increment got_events
+
+    if (timeout &gt;= 0)
+      // create/start timer
+
+    // poll
+    ev_loop (EV_A_ 0);
+
+    // stop timer again
+    if (timeout &gt;= 0)
+      ev_timer_stop (EV_A_ &amp;to);
+
+    // stop io watchers again - their callbacks should have set
+    for (n = 0; n &lt; nfds; ++n)
+      ev_io_stop (EV_A_ iow [n]);
+
+    return got_events;
+  }
+
 
 
 
diff --git a/ev.pod b/ev.pod
index 62118f167549cea2539d0b591c0b01b7fbc5758b..538b9f82ddd6c235cd8716d8e7ae556cbfa1b2b9 100644 (file)
--- a/ev.pod
+++ b/ev.pod
@@ -1495,10 +1495,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;
@@ -1506,11 +1514,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
@@ -1526,7 +1529,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,
@@ -1534,7 +1537,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);
       }
   }
@@ -1546,11 +1548,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...