*** empty log message ***

This commit is contained in:
Marc Alexander Lehmann 2007-12-08 15:30:26 +00:00
parent 78fc327db0
commit 883b1688c6
3 changed files with 277 additions and 40 deletions

127
ev.3
View File

@ -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..."

95
ev.html
View File

@ -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;
}

95
ev.pod
View File

@ -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...