X-Git-Url: https://git.llucax.com/software/libev.git/blobdiff_plain/97710f65c4339600b822e15e7e78841ae445f0f5..b7e58d7ed7f85d7cb7fe1c34cfe3fa2484a6dc31:/ev.pod diff --git a/ev.pod b/ev.pod index d1c5d63..3f4a064 100644 --- a/ev.pod +++ b/ev.pod @@ -1104,10 +1104,21 @@ Prepare and check watchers are usually (but not always) used in tandem: prepare watchers get invoked before the process blocks and check watchers afterwards. +You I call C or similar functions that enter +the current event loop from either C or C +watchers. Other loops than the current one are fine, however. The +rationale behind this is that you do not need to check for recursion in +those watchers, i.e. the sequence will always be C, blocking, +C so if you have one watcher of each kind they will always be +called in pairs bracketing the blocking call. + Their main purpose is to integrate other event mechanisms into libev and their use is somewhat advanced. This could be used, for example, to track variable changes, implement your own watchers, integrate net-snmp or a -coroutine library and lots more. +coroutine library and lots more. They are also occasionally useful if +you cache some data and want to flush it before blocking (for example, +in X programs you might want to do an C in an C +watcher). This is done by examining in each prepare call which file descriptors need to be watched by the other library, registering C watchers for @@ -1139,7 +1150,60 @@ macros, but using them is utterly, utterly and completely pointless. =back -Example: *TODO*. +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: + + 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 + static void + adns_prepare_cb (ev_loop *loop, ev_prepare *w, int revents) + { + int timeout = 3600000;truct pollfd fds [nfd]; + // actual code will need to loop here and realloc etc. + adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ())); + + /* the callback is illegal, but won't be called as we stop during check */ + ev_timer_init (&tw, 0, timeout * 1e-3); + ev_timer_start (loop, &tw); + + // create on ev_io per pollfd + for (int i = 0; i < nfd; ++i) + { + ev_io_init (iow + i, io_cb, fds [i].fd, + ((fds [i].events & POLLIN ? EV_READ : 0) + | (fds [i].events & POLLOUT ? EV_WRITE : 0))); + + fds [i].revents = 0; + iow [i].data = fds + i; + ev_io_start (loop, iow + i); + } + } + + // stop all watchers after blocking + static void + adns_check_cb (ev_loop *loop, ev_check *w, int revents) + { + ev_timer_stop (loop, &tw); + + for (int i = 0; i < nfd; ++i) + ev_io_stop (loop, iow + i); + + adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop)); + } =head2 C - when one backend isn't enough... @@ -1638,10 +1702,27 @@ additional independent event loops. Otherwise there will be no support for multiple event loops and there is no first event loop pointer argument. Instead, all functions act on the single default loop. -=item EV_PERIODICS +=item EV_PERIODIC_ENABLE + +If undefined or defined to be C<1>, then periodic timers are supported. If +defined to be C<0>, then they are not. Disabling them saves a few kB of +code. + +=item EV_EMBED_ENABLE + +If undefined or defined to be C<1>, then embed watchers are supported. If +defined to be C<0>, then they are not. -If undefined or defined to be C<1>, then periodic timers are supported, -otherwise not. This saves a few kb of code. +=item EV_STAT_ENABLE + +If undefined or defined to be C<1>, then stat watchers are supported. If +defined to be C<0>, then they are not. + +=item EV_MINIMAL + +If you need to shave off some kilobytes of code at the expense of some +speed, define this symbol to C<1>. Currently only used for gcc to override +some inlining decisions, saves roughly 30% codesize of amd64. =item EV_COMMON @@ -1656,18 +1737,18 @@ For example, the perl EV module uses something like this: SV *self; /* contains this struct */ \ SV *cb_sv, *fh /* note no trailing ";" */ -=item EV_CB_DECLARE(type) +=item EV_CB_DECLARE (type) -=item EV_CB_INVOKE(watcher,revents) +=item EV_CB_INVOKE (watcher, revents) -=item ev_set_cb(ev,cb) +=item ev_set_cb (ev, cb) Can be used to change the callback member declaration in each watcher, and the way callbacks are invoked and set. Must expand to a struct member definition and a statement, respectively. See the F header file for their default definitions. One possible use for overriding these is to -avoid the ev_loop pointer as first argument in all cases, or to use method -calls instead of plain function calls in C++. +avoid the C as first argument in all cases, or to use +method calls instead of plain function calls in C++. =head2 EXAMPLES @@ -1694,6 +1775,34 @@ And a F implementation file that contains libev proper and is compiled #include "ev_cpp.h" #include "ev.c" + +=head1 COMPLEXITIES + +In this section the complexities of (many of) the algorithms used inside +libev will be explained. For complexity discussions about backends see the +documentation for C. + +=over 4 + +=item Starting and stopping timer/periodic watchers: O(log skipped_other_timers) + +=item Changing timer/periodic watchers (by autorepeat, again): O(log skipped_other_timers) + +=item Starting io/check/prepare/idle/signal/child watchers: O(1) + +=item Stopping check/prepare/idle watchers: O(1) + +=item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % 16)) + +=item Finding the next timer per loop iteration: O(1) + +=item Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd) + +=item Activating one watcher: O(1) + +=back + + =head1 AUTHOR Marc Lehmann .