diff options
| -rw-r--r-- | ev.3 | 127 | ||||
| -rw-r--r-- | ev.html | 95 | ||||
| -rw-r--r-- | ev.pod | 95 | 
3 files changed, 277 insertions, 40 deletions
| @@ -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..." @@ -6,7 +6,7 @@  	<meta name="description" content="Pod documentation for libev" />  	<meta name="inputfile" content="<standard input>" />  	<meta name="outputfile" content="<standard output>" /> -	<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->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 @@ -1524,7 +1526,7 @@ pseudo-code only of course:</p>      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, @@ -1532,7 +1534,6 @@ pseudo-code only of course:</p>             | (fds [i].events & 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, &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));    } +</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->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 + +</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 < 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; +  } + @@ -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... | 
