--- libev/ev.pod 2010/11/10 13:41:48 1.344 +++ libev/ev.pod 2011/10/16 11:02:57 1.384 @@ -60,7 +60,7 @@ // now wait for events to arrive ev_run (loop, 0); - // unloop was called, so exit + // break was called, so exit return 0; } @@ -176,13 +176,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 () @@ -301,6 +307,19 @@ ... ev_set_syserr_cb (fatal_error); +=item ev_feed_signal (int signum) + +This function can be used to "simulate" a signal receive. It is completely +safe to call this function at any time, from any context, including signal +handlers or random threads. + +Its main use is to customise signal handling in your process, especially +in the presence of threads. For example, you could block signals +by default in all threads (and specifying C when +creating any loops), and in one thread, use C or any other +mechanism to wait for signals, then "deliver" them to libev by calling +C. + =back =head1 FUNCTIONS CONTROLLING EVENT LOOPS @@ -421,6 +440,21 @@ there are a lot of shoddy libraries and programs (glib's threadpool for example) that can't properly initialise their signal masks. +=item C + +When this flag is specified, then libev will avoid to modify the signal +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 +want to handle signals only in specific threads and want to avoid libev +unblocking the signals. + +It's also required by POSIX in a threaded program, as libev calls +C, whose behaviour is officially unspecified. + +This flag's behaviour will become the default in future versions of libev. + =item C (value 1, portable select backend) This is your standard select(2) backend. Not I standard, as @@ -457,10 +491,10 @@ 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 @@ -473,17 +507,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 libev) on file descriptors +representing files, and expect it to become ready when their program +doesn't block on disk accesses (which can take a long time on their own). + +However, this cannot ever work in the "expected" way - you get a readiness +notification as soon as the kernel knows whether and how much data is +there, and in the case of open files, that's always the case, so you +always get a readiness notification instantly, and your read (or possibly +write) will still block on the disk I/O. + +Another way to view it is that in the case of sockets, pipes, character +devices and so on, there is another party (the sender) that delivers data +on its own, but in the case of files, there is no such thing: the disk +will not send data on its own, simply because it doesn't know what you +wish to read - you would first have to request some data. + +Since files are typically not-so-well supported by advanced notification +mechanism, libev tries hard to emulate POSIX behaviour with respect +to files, even though you should not use it. The reason for this is +convenience: sometimes you want to watch STDIN or STDOUT, which is +usually a tty, often a pipe, but also sometimes files or special devices +(for example, C on Linux works with F but not with +F), and even though the file might better be served with +asynchronous I/O instead of with non-blocking I/O, it is still useful when +it "just works" instead of freezing. + +So avoid file descriptors pointing to files when you know it (e.g. use +libeio), but use them when it is convenient, e.g. for STDIN/STDOUT, or +when you rarely read from a file instead of from a socket, and want to +reuse the same code path. + =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. +it in the child if you want to continue to use it in the child. -To support fork in your programs, you either have to call -C or C after a fork in the child, -enable C, or resort to C or -C. +To support fork in your child processes, you have to call C after a fork in the child, enable C, or resort to +C or C. =head3 The special problem of SIGPIPE @@ -1751,10 +1773,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 @@ -1931,10 +1954,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 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. @@ -1951,6 +2011,39 @@ update of the time returned by C by calling C. +=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