ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev.3
(Generate patch)

Comparing libev/ev.3 (file contents):
Revision 1.43 by root, Sat Dec 8 14:27:38 2007 UTC vs.
Revision 1.44 by root, Sat Dec 8 15:30:26 2007 UTC

1644.PD 1644.PD
1645Initialises and configures the prepare or check watcher \- they have no 1645Initialises and configures the prepare or check watcher \- they have no
1646parameters of any kind. There are \f(CW\*(C`ev_prepare_set\*(C'\fR and \f(CW\*(C`ev_check_set\*(C'\fR 1646parameters of any kind. There are \f(CW\*(C`ev_prepare_set\*(C'\fR and \f(CW\*(C`ev_check_set\*(C'\fR
1647macros, but using them is utterly, utterly and completely pointless. 1647macros, but using them is utterly, utterly and completely pointless.
1648.PP 1648.PP
1649Example: To include a library such as adns, you would add \s-1IO\s0 watchers 1649There are a number of principal ways to embed other event loops or modules
1650and a timeout watcher in a prepare handler, as required by libadns, and 1650into libev. Here are some ideas on how to include libadns into libev
1651(there is a Perl module named \f(CW\*(C`EV::ADNS\*(C'\fR that does this, which you could
1652use for an actually working example. Another Perl module named \f(CW\*(C`EV::Glib\*(C'\fR
1653embeds a Glib main context into libev, and finally, \f(CW\*(C`Glib::EV\*(C'\fR embeds \s-1EV\s0
1654into the Glib event loop).
1655.PP
1656Method 1: Add \s-1IO\s0 watchers and a timeout watcher in a prepare handler,
1651in a check watcher, destroy them and call into libadns. What follows is 1657and in a check watcher, destroy them and call into libadns. What follows
1652pseudo-code only of course: 1658is pseudo-code only of course. This requires you to either use a low
1659priority for the check watcher or use \f(CW\*(C`ev_clear_pending\*(C'\fR explicitly, as
1660the callbacks for the IO/timeout watchers might not have been called yet.
1653.PP 1661.PP
1654.Vb 2 1662.Vb 2
1655\& static ev_io iow [nfd]; 1663\& static ev_io iow [nfd];
1656\& static ev_timer tw; 1664\& static ev_timer tw;
1657.Ve 1665.Ve
1658.PP 1666.PP
1659.Vb 9 1667.Vb 4
1660\& static void 1668\& static void
1661\& io_cb (ev_loop *loop, ev_io *w, int revents) 1669\& io_cb (ev_loop *loop, ev_io *w, int revents)
1662\& { 1670\& {
1663\& // set the relevant poll flags
1664\& // could also call adns_processreadable etc. here
1665\& struct pollfd *fd = (struct pollfd *)w->data;
1666\& if (revents & EV_READ ) fd->revents |= fd->events & POLLIN;
1667\& if (revents & EV_WRITE) fd->revents |= fd->events & POLLOUT;
1668\& } 1671\& }
1669.Ve 1672.Ve
1670.PP 1673.PP
1671.Vb 8 1674.Vb 8
1672\& // create io watchers for each fd and a timer before blocking 1675\& // create io watchers for each fd and a timer before blocking
1684\& ev_timer_init (&tw, 0, timeout * 1e-3); 1687\& ev_timer_init (&tw, 0, timeout * 1e-3);
1685\& ev_timer_start (loop, &tw); 1688\& ev_timer_start (loop, &tw);
1686.Ve 1689.Ve
1687.PP 1690.PP
1688.Vb 6 1691.Vb 6
1689\& // create on ev_io per pollfd 1692\& // create one ev_io per pollfd
1690\& for (int i = 0; i < nfd; ++i) 1693\& for (int i = 0; i < nfd; ++i)
1691\& { 1694\& {
1692\& ev_io_init (iow + i, io_cb, fds [i].fd, 1695\& ev_io_init (iow + i, io_cb, fds [i].fd,
1693\& ((fds [i].events & POLLIN ? EV_READ : 0) 1696\& ((fds [i].events & POLLIN ? EV_READ : 0)
1694\& | (fds [i].events & POLLOUT ? EV_WRITE : 0))); 1697\& | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
1695.Ve 1698.Ve
1696.PP 1699.PP
1697.Vb 5 1700.Vb 4
1698\& fds [i].revents = 0; 1701\& fds [i].revents = 0;
1699\& iow [i].data = fds + i;
1700\& ev_io_start (loop, iow + i); 1702\& ev_io_start (loop, iow + i);
1701\& } 1703\& }
1702\& } 1704\& }
1703.Ve 1705.Ve
1704.PP 1706.PP
1708\& adns_check_cb (ev_loop *loop, ev_check *w, int revents) 1710\& adns_check_cb (ev_loop *loop, ev_check *w, int revents)
1709\& { 1711\& {
1710\& ev_timer_stop (loop, &tw); 1712\& ev_timer_stop (loop, &tw);
1711.Ve 1713.Ve
1712.PP 1714.PP
1713.Vb 2 1715.Vb 8
1714\& for (int i = 0; i < nfd; ++i) 1716\& for (int i = 0; i < nfd; ++i)
1717\& {
1718\& // set the relevant poll flags
1719\& // could also call adns_processreadable etc. here
1720\& struct pollfd *fd = fds + i;
1721\& int revents = ev_clear_pending (iow + i);
1722\& if (revents & EV_READ ) fd->revents |= fd->events & POLLIN;
1723\& if (revents & EV_WRITE) fd->revents |= fd->events & POLLOUT;
1724.Ve
1725.PP
1726.Vb 3
1727\& // now stop the watcher
1715\& ev_io_stop (loop, iow + i); 1728\& ev_io_stop (loop, iow + i);
1729\& }
1716.Ve 1730.Ve
1717.PP 1731.PP
1718.Vb 2 1732.Vb 2
1719\& adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop)); 1733\& adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop));
1734\& }
1735.Ve
1736.PP
1737Method 2: This would be just like method 1, but you run \f(CW\*(C`adns_afterpoll\*(C'\fR
1738in the prepare watcher and would dispose of the check watcher.
1739.PP
1740Method 3: If the module to be embedded supports explicit event
1741notification (adns does), you can also make use of the actual watcher
1742callbacks, and only destroy/create the watchers in the prepare watcher.
1743.PP
1744.Vb 5
1745\& static void
1746\& timer_cb (EV_P_ ev_timer *w, int revents)
1747\& {
1748\& adns_state ads = (adns_state)w->data;
1749\& update_now (EV_A);
1750.Ve
1751.PP
1752.Vb 2
1753\& adns_processtimeouts (ads, &tv_now);
1754\& }
1755.Ve
1756.PP
1757.Vb 5
1758\& static void
1759\& io_cb (EV_P_ ev_io *w, int revents)
1760\& {
1761\& adns_state ads = (adns_state)w->data;
1762\& update_now (EV_A);
1763.Ve
1764.PP
1765.Vb 3
1766\& if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now);
1767\& if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
1768\& }
1769.Ve
1770.PP
1771.Vb 1
1772\& // do not ever call adns_afterpoll
1773.Ve
1774.PP
1775Method 4: Do not use a prepare or check watcher because the module you
1776want to embed is too inflexible to support it. Instead, youc na override
1777their poll function. The drawback with this solution is that the main
1778loop is now no longer controllable by \s-1EV\s0. The \f(CW\*(C`Glib::EV\*(C'\fR module does
1779this.
1780.PP
1781.Vb 4
1782\& static gint
1783\& event_poll_func (GPollFD *fds, guint nfds, gint timeout)
1784\& {
1785\& int got_events = 0;
1786.Ve
1787.PP
1788.Vb 2
1789\& for (n = 0; n < nfds; ++n)
1790\& // create/start io watcher that sets the relevant bits in fds[n] and increment got_events
1791.Ve
1792.PP
1793.Vb 2
1794\& if (timeout >= 0)
1795\& // create/start timer
1796.Ve
1797.PP
1798.Vb 2
1799\& // poll
1800\& ev_loop (EV_A_ 0);
1801.Ve
1802.PP
1803.Vb 3
1804\& // stop timer again
1805\& if (timeout >= 0)
1806\& ev_timer_stop (EV_A_ &to);
1807.Ve
1808.PP
1809.Vb 3
1810\& // stop io watchers again - their callbacks should have set
1811\& for (n = 0; n < nfds; ++n)
1812\& ev_io_stop (EV_A_ iow [n]);
1813.Ve
1814.PP
1815.Vb 2
1816\& return got_events;
1720\& } 1817\& }
1721.Ve 1818.Ve
1722.ie n .Sh """ev_embed"" \- when one backend isn't enough..." 1819.ie n .Sh """ev_embed"" \- when one backend isn't enough..."
1723.el .Sh "\f(CWev_embed\fP \- when one backend isn't enough..." 1820.el .Sh "\f(CWev_embed\fP \- when one backend isn't enough..."
1724.IX Subsection "ev_embed - when one backend isn't enough..." 1821.IX Subsection "ev_embed - when one backend isn't enough..."

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines