--- libev/ev.pod 2011/01/17 12:11:12 1.360 +++ libev/ev.pod 2019/06/26 00:01:46 1.455 @@ -1,3 +1,5 @@ +=encoding utf-8 + =head1 NAME libev - a high performance full-featured event loop written in C @@ -60,7 +62,7 @@ // now wait for events to arrive ev_run (loop, 0); - // unloop was called, so exit + // break was called, so exit return 0; } @@ -84,9 +86,9 @@ This manual tries to be very detailed, but unfortunately, this also makes it very long. If you just want to know the basics of libev, I suggest -reading L, then the L above and -look up the missing functions in L and the C and -C sections in L. +reading L, then the L above and +look up the missing functions in L and the C and +C sections in L. =head1 ABOUT LIBEV @@ -105,10 +107,10 @@ =head2 FEATURES -Libev supports C, C, the Linux-specific aio and C +interfaces, the BSD-specific C and the Solaris-specific event port +mechanisms for file descriptor events (C), the Linux C +interface (for C), Linux eventfd/signalfd (for faster and cleaner inter-thread wakeup (C)/signal handling (C)) relative timers (C), absolute timers with customised rescheduling (C), synchronous signals (C), process status @@ -159,9 +161,13 @@ so C will disable this checking): these are programming errors in the libev caller and need to be fixed there. -Libev also has a few internal error-checking Cions, and also has -extensive consistency checking code. These do not trigger under normal -circumstances, as they indicate either a bug in libev or worse. +Via the C macro you can compile in and/or enable extensive +consistency checking code inside libev that can be used to check for +internal inconsistencies, suually caused by application bugs. + +Libev also has a few internal error-checking Cions. These do not +trigger under normal circumstances, as they indicate either a bug in libev +or worse. =head1 GLOBAL FUNCTIONS @@ -176,13 +182,19 @@ Returns the current time as libev would use it. Please note that the C function is usually faster and also often returns the timestamp you actually want to know. Also interesting is the combination of -C and C. +C and C. =item ev_sleep (ev_tstamp interval) -Sleep for the given interval: The current thread will be blocked until -either it is interrupted or the given time interval has passed. Basically -this is a sub-second-resolution C. +Sleep for the given interval: The current thread will be blocked +until either it is interrupted or the given time interval has +passed (approximately - it might return a bit earlier even if not +interrupted). Returns immediately if C<< interval <= 0 >>. + +Basically this is a sub-second-resolution C. + +The range of the C is limited - libev only guarantees to work +with sleep times of up to one day (C<< interval <= 86400 >>). =item int ev_version_major () @@ -243,7 +255,7 @@ See the description of C watchers for more info. -=item ev_set_allocator (void *(*cb)(void *ptr, long size)) +=item ev_set_allocator (void *(*cb)(void *ptr, long size) throw ()) Sets the allocation function to use (the prototype is similar - the semantics are identical to the C C89/SuS/POSIX function). It is @@ -259,12 +271,32 @@ free some memory if it cannot allocate memory, to use a special allocator, or even to sleep a while and retry until some memory is available. +Example: The following is the C function that libev itself uses +which should work with C and C functions of all kinds and +is probably a good basis for your own implementation. + + static void * + ev_realloc_emul (void *ptr, long size) EV_NOEXCEPT + { + if (size) + return realloc (ptr, size); + + free (ptr); + return 0; + } + Example: Replace the libev allocator with one that waits a bit and then -retries (example requires a standards-compliant C). +retries. static void * persistent_realloc (void *ptr, size_t size) { + if (!size) + { + free (ptr); + return 0; + } + for (;;) { void *newptr = realloc (ptr, size); @@ -279,7 +311,7 @@ ... ev_set_allocator (persistent_realloc); -=item ev_set_syserr_cb (void (*cb)(const char *msg)) +=item ev_set_syserr_cb (void (*cb)(const char *msg) throw ()) Set the callback function to call on a retryable system call error (such as failed select, poll, epoll_wait). The message is a printable string @@ -392,8 +424,10 @@ or setgid) then libev will I look at the environment variable C. Otherwise (the default), this environment variable will override the flags completely if it is found in the environment. This is -useful to try out specific backends to test their performance, or to work -around bugs. +useful to try out specific backends to test their performance, to work +around bugs, or to make libev threadsafe (accessing environment variables +cannot be done in a threadsafe way, but usually it works if no other +thread modifies them). =item C @@ -403,13 +437,14 @@ This works by calling C on every iteration of the loop, and thus this might slow down your event loop if you do a lot of loop iterations and little real work, but is usually not noticeable (on my -GNU/Linux system for example, C is actually a simple 5-insn sequence -without a system call and thus I fast, but my GNU/Linux system also has -C which is even faster). +GNU/Linux system for example, C is actually a simple 5-insn +sequence without a system call and thus I fast, but my GNU/Linux +system also has C which is even faster). (Update: glibc +versions 2.25 apparently removed the C optimisation again). The big advantage of this flag is that you can forget about fork (and -forget about forgetting to tell libev about forking) when you use this -flag. +forget about forgetting to tell libev about forking, although you still +have to ignore C) when you use this flag. This flag setting cannot be overridden or specified in the C environment variable. @@ -437,7 +472,7 @@ =item C When this flag is specified, then libev will avoid to modify the signal -mask. Specifically, this means you ahve to make sure signals are unblocked +mask. Specifically, this means you have to make sure signals are unblocked when you want to receive them. This behaviour is useful when you want to do your own signal handling, or @@ -482,13 +517,13 @@ =item C (value 4, Linux) -Use the linux-specific epoll(7) interface (for both pre- and post-2.6.9 +Use the Linux-specific epoll(7) interface (for both pre- and post-2.6.9 kernels). -For few fds, this backend is a bit little slower than poll and select, -but it scales phenomenally better. While poll and select usually scale -like O(total_fds) where n is the total number of fds (or the highest fd), -epoll scales either O(1) or O(active_fds). +For few fds, this backend is a bit little slower than poll and select, but +it scales phenomenally better. While poll and select usually scale like +O(total_fds) where total_fds is the total number of fds (or the highest +fd), epoll scales either O(1) or O(active_fds). The epoll mechanism deserves honorable mention as the most misdesigned of the more advanced event mechanisms: mere annoyances include silently @@ -501,19 +536,22 @@ set, which can take considerable time (one syscall per file descriptor) and is of course hard to detect. -Epoll is also notoriously buggy - embedding epoll fds I work, but -of course I, and epoll just loves to report events for totally -I file descriptors (even already closed ones, so one cannot -even remove them from the set) than registered in the set (especially -on SMP systems). Libev tries to counter these spurious notifications by -employing an additional generation counter and comparing that against the -events to filter out spurious ones, recreating the set when required. Last +Epoll is also notoriously buggy - embedding epoll fds I work, +but of course I, and epoll just loves to report events for +totally I file descriptors (even already closed ones, so +one cannot even remove them from the set) than registered in the set +(especially on SMP systems). Libev tries to counter these spurious +notifications by employing an additional generation counter and comparing +that against the events to filter out spurious ones, recreating the set +when required. Epoll also erroneously rounds down timeouts, but gives you +no way to know when and by how much, so sometimes you have to busy-wait +because epoll returns immediately despite a nonzero timeout. And last not least, it also refuses to work with some file descriptors which work perfectly fine with C or C. + +To work around all these problem, the current version of libev uses its +epoll backend as a fallback for file descriptor types that do not work. Or +falls back completely to epoll if the kernel acts up. This backend maps C and C in the same way as C. =item C (value 8, most BSD clones) -Kqueue deserves special mention, as at the time of this writing, it -was broken on all BSDs except NetBSD (usually it doesn't work reliably -with anything but sockets and pipes, except on Darwin, where of course -it's completely useless). Unlike epoll, however, whose brokenness -is by design, these kqueue bugs can (and eventually will) be fixed -without API changes to existing programs. For this reason it's not being -"auto-detected" unless you explicitly specify it in the flags (i.e. using -C) or libev was compiled on a known-to-be-good (-enough) -system like NetBSD. +Kqueue deserves special mention, as at the time this backend was +implemented, it was broken on all BSDs except NetBSD (usually it doesn't +work reliably with anything but sockets and pipes, except on Darwin, +where of course it's completely useless). Unlike epoll, however, whose +brokenness is by design, these kqueue bugs can be (and mostly have been) +fixed without API changes to existing programs. For this reason it's not +being "auto-detected" on all platforms unless you explicitly specify it +in the flags (i.e. using C) or libev was compiled on a +known-to-be-good (-enough) system like NetBSD. You still can embed kqueue into a normal poll or select backend and use it only for sockets (after having made sure that sockets work with kqueue on @@ -560,9 +642,9 @@ kernel is more efficient (which says nothing about its actual speed, of course). While stopping, setting and starting an I/O watcher does never cause an extra system call as with C, it still adds up to -two event changes per incident. Support for C is very bad (but -sane, unlike epoll) and it drops fds silently in similarly hard-to-detect -cases +two event changes per incident. Support for C is very bad (you +might have to leak fds on fork, but it's more sane than epoll) and it +drops fds silently in similarly hard-to-detect cases. This backend usually performs well under most conditions. @@ -601,11 +683,11 @@ On the negative side, the interface is I - so bizarre that even sun itself gets it wrong in their code examples: The event polling -function sometimes returning events to the caller even though an error +function sometimes returns events to the caller even though an error occurred, but with no indication whether it has done so or not (yes, it's -even documented that way) - deadly for edge-triggered interfaces where -you absolutely have to know whether an event occurred or not because you -have to re-arm the watcher. +even documented that way) - deadly for edge-triggered interfaces where you +absolutely have to know whether an event occurred or not because you have +to re-arm the watcher. Fortunately libev seems to be able to work around these idiocies. @@ -646,6 +728,12 @@ struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_KQUEUE); +Example: Similarly, on linux, you mgiht want to take advantage of the +linux aio backend if possible, but fall back to something else if that +isn't available. + + struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_LINUXAIO); + =item ev_loop_destroy (loop) Destroys an event loop object (frees all memory and kernel state @@ -671,13 +759,17 @@ =item ev_loop_fork (loop) -This function sets a flag that causes subsequent C iterations to -reinitialise the kernel state for backends that have one. Despite the -name, you can call it anytime, but it makes most sense after forking, in -the child process. You I call it (or use C) in the -child before resuming or calling C. +This function sets a flag that causes subsequent C iterations +to reinitialise the kernel state for backends that have one. Despite +the name, you can call it anytime you are allowed to start or stop +watchers (except inside an C callback), but it makes most +sense after forking, in the child process. You I call it (or use +C) in the child before resuming or calling C. + +In addition, if you want to reuse a loop (via this function or +C), you I have to ignore C. -Again, you I to call it on I loop that you want to re-use after +Again, you I to call it on I loop that you want to re-use after a fork, I. This is because some kernel interfaces *cough* I *cough* do funny things during fork. @@ -757,7 +849,7 @@ very long time without entering the event loop, updating libev's idea of the current time is a good idea. -See also L in the C section. +See also L in the C section. =item ev_suspend (loop) @@ -785,18 +877,22 @@ Calling C/C has the side effect of updating the event loop time (see C). -=item ev_run (loop, int flags) +=item bool ev_run (loop, int flags) Finally, this is it, the event handler. This function usually is called after you have initialised all your watchers and you want to start handling events. It will ask the operating system for any new events, call -the watcher callbacks, an then repeat the whole process indefinitely: This +the watcher callbacks, and then repeat the whole process indefinitely: This is why event loops are called I. If the flags argument is specified as C<0>, it will keep handling events until either no event watchers are active anymore or C was called. +The return value is false if there are no more active watchers (which +usually means "all jobs done" or "deadlock"), and true in all other cases +(which usually means " you should call C again"). + Please note that an explicit C is usually better than relying on all watchers to be stopped when deciding when a program has finished (especially in interactive programs), but having a program @@ -804,8 +900,8 @@ of relying on its watchers stopping correctly, that is truly a thing of beauty. -This function is also I exception-safe - you can break out of -a C call by calling C in a callback, throwing a C++ +This function is I exception-safe - you can break out of a +C call by calling C in a callback, throwing a C++ exception and so on. This does not decrement the C value, nor will it clear any outstanding C breaks. @@ -827,7 +923,9 @@ own C"). However, a pair of C/C watchers is usually a better approach for this kind of thing. -Here are the gory details of what C does: +Here are the gory details of what C does (this is for your +understanding, not a guarantee that things will work exactly like this in +future versions): - Increment loop depth. - Reset the ev_break status. @@ -870,7 +968,7 @@ ... queue jobs here, make sure they register event watchers as long ... as they still have work to do (even an idle watcher will do..) ev_run (my_loop, 0); - ... jobs done or somebody called unloop. yeah! + ... jobs done or somebody called break. yeah! =item ev_break (loop, how) @@ -943,10 +1041,11 @@ By setting a higher I you allow libev to spend more time collecting I/O events, so you can handle more events per iteration, at the cost of increasing latency. Timeouts (both C and -C) will be not affected. Setting this to a non-null value will +C) will not be affected. Setting this to a non-null value will introduce an additional C call into most loop iterations. The sleep time ensures that libev will not poll for I/O events more often then -once per this interval, on average. +once per this interval, on average (as long as the host time resolution is +good enough). Likewise, by setting a higher I you allow libev to spend more time collecting timeouts, at the expense of increased @@ -1002,7 +1101,7 @@ If you want to reset the callback, use C as new callback. -=item ev_set_loop_release_cb (loop, void (*release)(EV_P), void (*acquire)(EV_P)) +=item ev_set_loop_release_cb (loop, void (*release)(EV_P) throw (), void (*acquire)(EV_P) throw ()) Sometimes you want to share the same loop between multiple threads. This can be done relatively simply by putting mutex_lock/unlock calls around @@ -1010,7 +1109,7 @@ However, C can run an indefinite time, so it is not feasible to wait for it to return. One way around this is to wake up the event -loop via C and C, another way is to set these +loop via C and C, another way is to set these I and I callbacks on the loop. When set, then C will be called just before the thread is @@ -1160,13 +1259,18 @@ =item C -All C watchers are invoked just I C starts -to gather new events, and all C watchers are invoked just after -C has gathered them, but before it invokes any callbacks for any -received events. Callbacks of both watcher types can start and stop as -many watchers as they want, and all of them will be taken into account -(for example, a C watcher might start an idle watcher to keep -C from blocking). +All C watchers are invoked just I C starts to +gather new events, and all C watchers are queued (not invoked) +just after C has gathered them, but before it queues any callbacks +for any received events. That means C watchers are the last +watchers invoked before the event loop sleeps or polls for new events, and +C watchers will be invoked before any other watchers of the same +or lower priority within an event loop iteration. + +Callbacks of both watcher types can start and stop as many watchers as +they want, and all of them will be taken into account (for example, a +C watcher might start an idle watcher to keep C from +blocking). =item C @@ -1299,7 +1403,7 @@ Returns the callback currently set on the watcher. -=item ev_cb_set (ev_TYPE *watcher, callback) +=item ev_set_cb (ev_TYPE *watcher, callback) Change the callback. You can change the callback at virtually any time (modulo threads). @@ -1327,7 +1431,7 @@ The default priority used by watchers when no priority has been set is always C<0>, which is supposed to not be too high and not be too low :). -See L, below, for a more thorough treatment of +See L, below, for a more thorough treatment of priorities. =item ev_invoke (loop, ev_TYPE *watcher, int revents) @@ -1362,7 +1466,7 @@ =back -See also the L and L and L idioms. =head2 WATCHER STATES @@ -1374,14 +1478,16 @@ =over 4 -=item initialiased +=item initialised -Before a watcher can be registered with the event looop it has to be +Before a watcher can be registered with the event loop it has to be initialised. This can be done with a call to C, or calls to C followed by the watcher-specific C function. -In this state it is simply some block of memory that is suitable for use -in an event loop. It can be moved around, freed, reused etc. at will. +In this state it is simply some block of memory that is suitable for +use in an event loop. It can be moved around, freed, reused etc. at +will - as long as you either keep the memory contents intact, or call +C again. =item started/running/active @@ -1419,8 +1525,9 @@ freeing it is often a good idea. While stopped (and not pending) the watcher is essentially in the -initialised state, that is it can be reused, moved, modified in any way -you wish. +initialised state, that is, it can be reused, moved, modified in any way +you wish (but when you trash the memory block, you need to C +it again). =back @@ -1579,13 +1686,13 @@ =head3 The special problem of disappearing file descriptors -Some backends (e.g. kqueue, epoll) need to be told about closing a file -descriptor (either due to calling C explicitly or any other means, -such as C). The reason is that you register interest in some file -descriptor, but when it goes away, the operating system will silently drop -this interest. If another file descriptor with the same number then is -registered with libev, there is no efficient way to see that this is, in -fact, a different file descriptor. +Some backends (e.g. kqueue, epoll, linuxaio) need to be told about closing +a file descriptor (either due to calling C explicitly or any other +means, such as C). The reason is that you register interest in some +file descriptor, but when it goes away, the operating system will silently +drop this interest. If another file descriptor with the same number then +is registered with libev, there is no efficient way to see that this is, +in fact, a different file descriptor. To avoid having to explicitly tell libev about such cases, libev follows the following policy: Each time C is being called, libev @@ -1644,9 +1751,10 @@ =head3 The special problem of fork -Some backends (epoll, kqueue) do not support C at all or exhibit -useless behaviour. Libev fully supports fork, but needs to be told about -it in the child if you want to continue to use it in the child. +Some backends (epoll, kqueue, probably linuxaio) do not support C +at all or exhibit useless behaviour. Libev fully supports fork, but needs +to be told about it in the child if you want to continue to use it in the +child. To support fork in your child processes, you have to call C after a fork in the child, enable C, or resort to @@ -1758,10 +1866,11 @@ The callback is guaranteed to be invoked only I its timeout has passed (not I, so on systems with very low-resolution clocks this -might introduce a small delay). If multiple timers become ready during the -same loop iteration then the ones with earlier time-out values are invoked -before ones of the same priority with later time-out values (but this is -no longer true when a callback calls C recursively). +might introduce a small delay, see "the special problem of being too +early", below). If multiple timers become ready during the same loop +iteration then the ones with earlier time-out values are invoked before +ones of the same priority with later time-out values (but this is no +longer true when a callback calls C recursively). =head3 Be smart about timeouts @@ -1846,63 +1955,77 @@ but remember the time of last activity, and check for a real timeout only within the callback: + ev_tstamp timeout = 60.; ev_tstamp last_activity; // time of last activity + ev_timer timer; static void callback (EV_P_ ev_timer *w, int revents) { - ev_tstamp now = ev_now (EV_A); - ev_tstamp timeout = last_activity + 60.; + // calculate when the timeout would happen + ev_tstamp after = last_activity - ev_now (EV_A) + timeout; - // if last_activity + 60. is older than now, we did time out - if (timeout < now) + // if negative, it means we the timeout already occurred + if (after < 0.) { // timeout occurred, take action } else { - // callback was invoked, but there was some activity, re-arm - // the watcher to fire in last_activity + 60, which is - // guaranteed to be in the future, so "again" is positive: - w->repeat = timeout - now; - ev_timer_again (EV_A_ w); + // callback was invoked, but there was some recent + // activity. simply restart the timer to time out + // after "after" seconds, which is the earliest time + // the timeout can occur. + ev_timer_set (w, after, 0.); + ev_timer_start (EV_A_ w); } } -To summarise the callback: first calculate the real timeout (defined -as "60 seconds after the last activity"), then check if that time has -been reached, which means something I, in fact, time out. Otherwise -the callback was invoked too early (C is in the future), so -re-schedule the timer to fire at that future time, to see if maybe we have -a timeout then. - -Note how C is used, taking advantage of the -C optimisation when the timer is already running. +To summarise the callback: first calculate in how many seconds the +timeout will occur (by calculating the absolute time when it would occur, +C, and subtracting the current time, C from that). + +If this value is negative, then we are already past the timeout, i.e. we +timed out, and need to do whatever is needed in this case. + +Otherwise, we now the earliest time at which the timeout would trigger, +and simply start the timer with this timeout value. + +In other words, each time the callback is invoked it will check whether +the timeout occurred. If not, it will simply reschedule itself to check +again at the earliest time it could time out. Rinse. Repeat. This scheme causes more callback invocations (about one every 60 seconds minus half the average time between activity), but virtually no calls to libev to change the timeout. -To start the timer, simply initialise the watcher and set C -to the current time (meaning we just have some activity :), then call the -callback, which will "do the right thing" and start the timer: - - ev_init (timer, callback); - last_activity = ev_now (loop); - callback (loop, timer, EV_TIMER); +To start the machinery, simply initialise the watcher and set +C to the current time (meaning there was some activity just +now), then call the callback, which will "do the right thing" and start +the timer: + + last_activity = ev_now (EV_A); + ev_init (&timer, callback); + callback (EV_A_ &timer, 0); -And when there is some activity, simply store the current time in +When there is some activity, simply store the current time in C, no libev calls at all: - last_activity = ev_now (loop); + if (activity detected) + last_activity = ev_now (EV_A); + +When your timeout value changes, then the timeout can be changed by simply +providing a new value, stopping the timer and calling the callback, which +will again do the right thing (for example, time out immediately :). + + timeout = new_value; + ev_timer_stop (EV_A_ &timer); + callback (EV_A_ &timer, 0); This technique is slightly more complex, but in most cases where the time-out is unlikely to be triggered, much more efficient. -Changing the timeout is trivial as well (if it isn't hard-coded in the -callback :) - just change the timeout and invoke the callback, which will -fix things for you. - =item 4. Wee, just use a double-linked list for your timeouts. If there is not one request, but many thousands (millions...), all @@ -1938,10 +2061,47 @@ off after the first million or so of active timers, i.e. it's usually overkill :) +=head3 The special problem of being too early + +If you ask a timer to call your callback after three seconds, then +you expect it to be invoked after three seconds - but of course, this +cannot be guaranteed to infinite precision. Less obviously, it cannot be +guaranteed to any precision by libev - imagine somebody suspending the +process with a STOP signal for a few hours for example. + +So, libev tries to invoke your callback as soon as possible I the +delay has occurred, but cannot guarantee this. + +A less obvious failure mode is calling your callback too early: many event +loops compare timestamps with a "elapsed delay >= requested delay", but +this can cause your callback to be invoked much earlier than you would +expect. + +To see why, imagine a system with a clock that only offers full second +resolution (think windows if you can't come up with a broken enough OS +yourself). If you schedule a one-second timer at the time 500.9, then the +event loop will schedule your timeout to elapse at a system time of 500 +(500.9 truncated to the resolution) + 1, or 501. + +If an event library looks at the timeout 0.1s later, it will see "501 >= +501" and invoke the callback 0.1s after it was started, even though a +one-second delay was requested - this is being "too early", despite best +intentions. + +This is the reason why libev will never invoke the callback if the elapsed +delay equals the requested delay, but only when the elapsed delay is +larger than the requested delay. In the example above, libev would only invoke +the callback at system time 502, or 1.1s after the timer was started. + +So, while libev cannot guarantee that your callback will be invoked +exactly when requested, it I and I guarantee that the requested +delay has actually elapsed, or in other words, it always errs on the "too +late" side of things. + =head3 The special problem of time updates -Establishing the current time is a costly operation (it usually takes at -least two system calls): EV therefore updates its idea of the current +Establishing the current time is a costly operation (it usually takes +at least one system call): EV therefore updates its idea of the current time only before and after C collects new events, which causes a growing difference between C and C when handling lots of events in one iteration. @@ -1950,13 +2110,48 @@ time. This is usually the right thing as this timestamp refers to the time of the event triggering whatever timeout you are modifying/starting. If you suspect event processing to be delayed and you I to base the -timeout on the current time, use something like this to adjust for this: +timeout on the current time, use something like the following to adjust +for it: - ev_timer_set (&timer, after + ev_now () - ev_time (), 0.); + ev_timer_set (&timer, after + (ev_time () - ev_now ()), 0.); If the event loop is suspended for a long time, you can also force an update of the time returned by C by calling C. +()>, although that will push the event time of all outstanding events +further into the future. + +=head3 The special problem of unsynchronised clocks + +Modern systems have a variety of clocks - libev itself uses the normal +"wall clock" clock and, if available, the monotonic clock (to avoid time +jumps). + +Neither of these clocks is synchronised with each other or any other clock +on the system, so C might return a considerably different time +than C or C