--- libev/ev.pod 2010/03/24 18:27:13 1.293 +++ libev/ev.pod 2011/07/12 23:32:10 1.379 @@ -28,8 +28,8 @@ // with its corresponding stop function. ev_io_stop (EV_A_ w); - // this causes all nested ev_loop's to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ALL); + // this causes all nested ev_run's to stop iterating + ev_break (EV_A_ EVBREAK_ALL); } // another callback, this time for a time-out @@ -37,15 +37,15 @@ timeout_cb (EV_P_ ev_timer *w, int revents) { puts ("timeout"); - // this causes the innermost ev_loop to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ONE); + // this causes the innermost ev_run to stop iterating + ev_break (EV_A_ EVBREAK_ONE); } int main (void) { // use the default event loop unless you have special needs - struct ev_loop *loop = ev_default_loop (0); + struct ev_loop *loop = EV_DEFAULT; // initialise an io watcher, then start it // this one will watch for stdin to become readable @@ -58,9 +58,9 @@ ev_timer_start (loop, &timeout_watcher); // now wait for events to arrive - ev_loop (loop, 0); + ev_run (loop, 0); - // unloop was called, so exit + // break was called, so exit return 0; } @@ -77,9 +77,17 @@ on event-based programming, nor will it introduce event-based programming with libev. -Familarity with event based programming techniques in general is assumed +Familiarity with event based programming techniques in general is assumed throughout this document. +=head1 WHAT TO READ WHEN IN A HURRY + +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. + =head1 ABOUT LIBEV Libev is an event loop: you register interest in certain events (such as a @@ -126,7 +134,7 @@ =head2 TIME REPRESENTATION Libev represents time as a single floating point number, representing -the (fractional) number of seconds since the (POSIX) epoch (in practise +the (fractional) number of seconds since the (POSIX) epoch (in practice somewhere near the beginning of 1970, details are complicated, don't ask). This type is called C, which is what you should use too. It usually aliases to the C type in C. When you need to do @@ -167,13 +175,20 @@ 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. +you actually want to know. Also interesting is the combination of +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 () @@ -194,7 +209,8 @@ not a problem. Example: Make sure we haven't accidentally been linked against the wrong -version. +version (note, however, that this will not detect other ABI mismatches, +such as LFS or reentrancy). assert (("libev version mismatch", ev_version_major () == EV_VERSION_MAJOR @@ -215,24 +231,25 @@ =item unsigned int ev_recommended_backends () -Return the set of all backends compiled into this binary of libev and also -recommended for this platform. This set is often smaller than the one -returned by C, as for example kqueue is broken on -most BSDs and will not be auto-detected unless you explicitly request it -(assuming you know what you are doing). This is the set of backends that -libev will probe for if you specify no backends explicitly. +Return the set of all backends compiled into this binary of libev and +also recommended for this platform, meaning it will work for most file +descriptor types. This set is often smaller than the one returned by +C, as for example kqueue is broken on most BSDs +and will not be auto-detected unless you explicitly request it (assuming +you know what you are doing). This is the set of backends that libev will +probe for if you specify no backends explicitly. =item unsigned int ev_embeddable_backends () Returns the set of backends that are embeddable in other event loops. This -is the theoretical, all-platform, value. To find which backends -might be supported on the current system, you would need to look at -C, likewise for -recommended ones. +value is platform-specific but can include backends not available on the +current system. To find which embeddable backends might be supported on +the current system, you would need to look at C, likewise for recommended ones. See the description of C watchers for more info. -=item ev_set_allocator (void *(*cb)(void *ptr, long size)) [NOT REENTRANT] +=item ev_set_allocator (void *(*cb)(void *ptr, long size)) Sets the allocation function to use (the prototype is similar - the semantics are identical to the C C89/SuS/POSIX function). It is @@ -268,7 +285,7 @@ ... ev_set_allocator (persistent_realloc); -=item ev_set_syserr_cb (void (*cb)(const char *msg)); [NOT REENTRANT] +=item ev_set_syserr_cb (void (*cb)(const char *msg)) 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 @@ -290,40 +307,78 @@ ... 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 THE EVENT LOOP +=head1 FUNCTIONS CONTROLLING EVENT LOOPS -An event loop is described by a C (the C -is I optional in this case, as there is also an C -I). +An event loop is described by a C (the C is +I optional in this case unless libev 3 compatibility is disabled, as +libev 3 had an C function colliding with the struct name). The library knows two types of such loops, the I loop, which -supports signals and child events, and dynamically created loops which do -not. +supports child process events, and dynamically created event loops which +do not. =over 4 =item struct ev_loop *ev_default_loop (unsigned int flags) -This will initialise the default event loop if it hasn't been initialised -yet and return it. If the default loop could not be initialised, returns -false. If it already was initialised it simply returns it (and ignores the -flags. If that is troubling you, check C afterwards). +This returns the "default" event loop object, which is what you should +normally use when you just need "the event loop". Event loop objects and +the C parameter are described in more detail in the entry for +C. + +If the default loop is already initialised then this function simply +returns it (and ignores the flags. If that is troubling you, check +C afterwards). Otherwise it will create it with the given +flags, which should almost always be C<0>, unless the caller is also the +one calling C or otherwise qualifies as "the main program". If you don't know what event loop to use, use the one returned from this -function. +function (or via the C macro). Note that this function is I thread-safe, so if you want to use it -from multiple threads, you have to lock (note also that this is unlikely, -as loops cannot be shared easily between threads anyway). +from multiple threads, you have to employ some kind of mutex (note also +that this case is unlikely, as loops cannot be shared easily between +threads anyway). + +The default loop is the only loop that can handle C watchers, +and to do this, it always registers a handler for C. If this is +a problem for your application you can either create a dynamic loop with +C which doesn't do that, or you can simply overwrite the +C signal handler I calling C. + +Example: This is the most typical usage. + + if (!ev_default_loop (0)) + fatal ("could not initialise libev, bad $LIBEV_FLAGS in environment?"); + +Example: Restrict libev to the select and poll backends, and do not allow +environment settings to be taken into account: + + ev_default_loop (EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV); + +=item struct ev_loop *ev_loop_new (unsigned int flags) + +This will create and initialise a new event loop object. If the loop +could not be initialised, returns false. -The default loop is the only loop that can handle C and -C watchers, and to do this, it always registers a handler -for C. If this is a problem for your application you can either -create a dynamic loop with C that doesn't do that, or you -can simply overwrite the C signal handler I calling -C. +This function is thread-safe, and one common way to use libev with +threads is indeed to create one loop per thread, and using the default +loop in the "main" or "initial" thread. The flags argument can be used to specify special behaviour or specific backends to use, and is usually specified as C<0> (or C). @@ -368,14 +423,14 @@ =item C When this flag is specified, then libev will not attempt to use the -I API for it's C watchers. Apart from debugging and +I API for its C watchers. Apart from debugging and testing, this flag can be useful to conserve inotify file descriptors, as otherwise each loop using C watchers consumes one inotify handle. =item C When this flag is specified, then libev will attempt to use the -I API for it's C (and C) watchers. This API +I API for its C (and C) watchers. This API delivers signals synchronously, which makes it both faster and might make it possible to get the queued signal data. It can also simplify signal handling with threads, as long as you properly block signals in your @@ -385,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 @@ -421,27 +491,38 @@ 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 dropping file descriptors, requiring a system call per change per file -descriptor (and unnecessary guessing of parameters), problems with dup and -so on. The biggest issue is fork races, however - if a program forks then -I parent and child process have to recreate the epoll 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. +descriptor (and unnecessary guessing of parameters), problems with dup, +returning before the timeout value, resulting in additional iterations +(and only giving 5ms accuracy while select on the same platform gives +0.1ms) and so on. The biggest issue is fork races, however - if a program +forks then I parent and child process have to recreate the epoll +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. 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 @@ -1624,7 +1757,7 @@ ev_io stdin_readable; ev_io_init (&stdin_readable, stdin_readable_cb, STDIN_FILENO, EV_READ); ev_io_start (loop, &stdin_readable); - ev_loop (loop, 0); + ev_run (loop, 0); =head2 C - relative and optionally repeating timeouts @@ -1643,7 +1776,7 @@ 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). +no longer true when a callback calls C recursively). =head3 Be smart about timeouts @@ -1739,7 +1872,7 @@ // if last_activity + 60. is older than now, we did time out if (timeout < now) { - // timeout occured, take action + // timeout occurred, take action } else { @@ -1776,7 +1909,7 @@ And when there is some activity, simply store the current time in C, no libev calls at all: - last_actiivty = ev_now (loop); + last_activity = ev_now (loop); This technique is slightly more complex, but in most cases where the time-out is unlikely to be triggered, much more efficient. @@ -1824,7 +1957,7 @@ Establishing the current time is a costly operation (it usually takes at least two system calls): EV therefore updates its idea of the current -time only before and after C collects new events, which causes a +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. @@ -1892,7 +2025,7 @@ =item ev_timer_again (loop, ev_timer *) -This will act as if the timer timed out and restart it again if it is +This will act as if the timer timed out and restarts it again if it is repeating. The exact semantics are: If the timer is pending, its pending status is cleared. @@ -1951,7 +2084,7 @@ ev_timer mytimer; ev_timer_init (&mytimer, timeout_cb, 0., 10.); /* note, only repeat used */ ev_timer_again (&mytimer); /* start timer */ - ev_loop (loop, 0); + ev_run (loop, 0); // and in some piece of code that gets executed on any "activity": // reset the timeout to start ticking again at 10 seconds @@ -1987,7 +2120,7 @@ point in time where it is supposed to trigger has passed. If multiple timers become ready during the same loop iteration then the ones with earlier time-out values are invoked before ones with later time-out values -(but this is no longer true when a callback calls C recursively). +(but this is no longer true when a callback calls C recursively). =head3 Watcher-Specific Functions and Data Members @@ -2032,9 +2165,12 @@ C will try to run the callback in this mode at the next possible time where C