--- libev/ev.pod 2007/12/20 07:12:57 1.91 +++ libev/ev.pod 2008/03/13 13:06:16 1.136 @@ -6,56 +6,70 @@ #include -=head1 EXAMPLE PROGRAM +=head2 EXAMPLE PROGRAM + // a single header file is required #include + // every watcher type has its own typedef'd struct + // with the name ev_ ev_io stdin_watcher; ev_timer timeout_watcher; - /* called when data readable on stdin */ + // all watcher callbacks have a similar signature + // this callback is called when data is readable on stdin static void stdin_cb (EV_P_ struct ev_io *w, int revents) { - /* puts ("stdin ready"); */ - ev_io_stop (EV_A_ w); /* just a syntax example */ - ev_unloop (EV_A_ EVUNLOOP_ALL); /* leave all loop calls */ + puts ("stdin ready"); + // for one-shot events, one must manually stop the watcher + // 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); } + // another callback, this time for a time-out static void timeout_cb (EV_P_ struct ev_timer *w, int revents) { - /* puts ("timeout"); */ - ev_unloop (EV_A_ EVUNLOOP_ONE); /* leave one loop call */ + puts ("timeout"); + // this causes the innermost ev_loop to stop iterating + ev_unloop (EV_A_ EVUNLOOP_ONE); } int main (void) { + // use the default event loop unless you have special needs struct ev_loop *loop = ev_default_loop (0); - /* initialise an io watcher, then start it */ + // initialise an io watcher, then start it + // this one will watch for stdin to become readable ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); ev_io_start (loop, &stdin_watcher); - /* simple non-repeating 5.5 second timeout */ + // initialise a timer watcher, then start it + // simple non-repeating 5.5 second timeout ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); ev_timer_start (loop, &timeout_watcher); - /* loop till timeout or data ready */ + // now wait for events to arrive ev_loop (loop, 0); + // unloop was called, so exit return 0; } =head1 DESCRIPTION -The newest version of this document is also available as a html-formatted +The newest version of this document is also available as an html-formatted web page you might find easier to navigate when reading it for the first time: L. Libev is an event loop: you register interest in certain events (such as a -file descriptor being readable or a timeout occuring), and it will manage +file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events. To do this, it must take more or less complete control over your process @@ -67,7 +81,7 @@ details of the event, and then hand it over to libev by I the watcher. -=head1 FEATURES +=head2 FEATURES Libev supports C which have a high +overhead for the actual polling but can deliver many events at once. + +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 +introduce an additional C call into most loop iterations. + +Likewise, by setting a higher I you allow libev +to spend more time collecting timeouts, at the expense of increased +latency (the watcher callback will be called later). C watchers +will not be affected. Setting this to a non-null value will not introduce +any overhead in libev. + +Many (busy) programs can usually benefit by setting the io collect +interval to a value near C<0.1> or so, which is often enough for +interactive servers (of course not for games), likewise for timeouts. It +usually doesn't make much sense to set it to a lower value than C<0.01>, +as this approsaches the timing granularity of most systems. + =back @@ -673,6 +795,10 @@ The event loop has been resumed in the child process after fork (see C). +=item C + +The given async watcher has been asynchronously notified (see C). + =item C An unspecified error has occured, the watcher has been stopped. This might @@ -899,12 +1025,6 @@ descriptors to non-blocking mode is also usually a good idea (but not required if you know what you are doing). -You have to be careful with dup'ed file descriptors, though. Some backends -(the linux epoll backend is a notable example) cannot handle dup'ed file -descriptors correctly if you register interest in two or more fds pointing -to the same underlying file/socket/etc. description (that is, they share -the same underlying "file open"). - If you must do this, then force the use of a known-to-be-good backend (at the time of this writing, this includes only C and C). @@ -926,7 +1046,7 @@ =head3 The special problem of disappearing file descriptors -Some backends (e.g kqueue, epoll) need to be told about closing a file +Some backends (e.g. kqueue, epoll) need to be told about closing a file descriptor (either by calling C explicitly or by 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 @@ -945,6 +1065,28 @@ the libev application should not optimise around libev but should leave optimisations to libev. +=head3 The special problem of dup'ed file descriptors + +Some backends (e.g. epoll), cannot register events for file descriptors, +but only events for the underlying file descriptions. That means when you +have C'ed file descriptors or weirder constellations, and register +events for them, only one file descriptor might actually receive events. + +There is no workaround possible except not registering events +for potentially C'ed file descriptors, or to resort to +C or C. + +=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. + +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. + =head3 Watcher-Specific Functions @@ -968,6 +1110,8 @@ =back +=head3 Examples + Example: Call C when STDIN_FILENO has become, well readable, but only once. Since it is likely line-buffered, you could attempt to read a whole line in the callback. @@ -1029,7 +1173,7 @@ the timer (because it takes longer than those 10 seconds to do stuff) the timer will not fire more than once per event loop iteration. -=item ev_timer_again (loop) +=item ev_timer_again (loop, ev_timer *) This will act as if the timer timed out and restart it again if it is repeating. The exact semantics are: @@ -1074,6 +1218,8 @@ =back +=head3 Examples + Example: Create a timer that fires after 60 seconds. static void @@ -1146,7 +1292,7 @@ that is, if it is to be run at January 1st 2011 then it will run when the system time reaches or surpasses this time. -=item * non-repeating interval timer (at = offset, interval > 0, reschedule_cb = 0) +=item * repeating interval timer (at = offset, interval > 0, reschedule_cb = 0) In this mode the watcher will always be scheduled to time out at the next C time (for some integer N, which can also be negative) @@ -1240,6 +1386,8 @@ =back +=head3 Examples + Example: Call a callback every hour, or, more precisely, whenever the system clock is divisible by 3600. The callback invocation times have potentially a lot of jittering, but good long-term stability. @@ -1288,6 +1436,12 @@ watcher for a signal is stopped libev will reset the signal handler to SIG_DFL (regardless of what it was set to before). +If possible and supported, libev will install its handlers with +C behaviour enabled, so syscalls should not be unduly +interrupted. If you have a problem with syscalls getting interrupted by +signals you can block all signals in an C watcher and unblock +them in an C watcher. + =head3 Watcher-Specific Functions and Data Members =over 4 @@ -1305,26 +1459,67 @@ =back +=head3 Examples + +Example: Try to exit cleanly on SIGINT and SIGTERM. + + static void + sigint_cb (struct ev_loop *loop, struct ev_signal *w, int revents) + { + ev_unloop (loop, EVUNLOOP_ALL); + } + + struct ev_signal signal_watcher; + ev_signal_init (&signal_watcher, sigint_cb, SIGINT); + ev_signal_start (loop, &sigint_cb); + =head2 C - watch out for process status changes Child watchers trigger when your process receives a SIGCHLD in response to -some child status changes (most typically when a child of yours dies). +some child status changes (most typically when a child of yours dies). It +is permissible to install a child watcher I the child has been +forked (which implies it might have already exited), as long as the event +loop isn't entered (or is continued from a watcher). + +Only the default event loop is capable of handling signals, and therefore +you can only rgeister child watchers in the default event loop. + +=head3 Process Interaction + +Libev grabs C as soon as the default event loop is +initialised. This is necessary to guarantee proper behaviour even if +the first child watcher is started after the child exits. The occurance +of C is recorded asynchronously, but child reaping is done +synchronously as part of the event loop processing. Libev always reaps all +children, even ones not watched. + +=head3 Overriding the Built-In Processing + +Libev offers no special support for overriding the built-in child +processing, but if your application collides with libev's default child +handler, you can override it easily by installing your own handler for +C after initialising the default loop, and making sure the +default loop never gets destroyed. You are encouraged, however, to use an +event-based approach to child reaping and thus use libev's support for +that, so other libev users can use C watchers freely. =head3 Watcher-Specific Functions and Data Members =over 4 -=item ev_child_init (ev_child *, callback, int pid) +=item ev_child_init (ev_child *, callback, int pid, int trace) -=item ev_child_set (ev_child *, int pid) +=item ev_child_set (ev_child *, int pid, int trace) Configures the watcher to wait for status changes of process C (or I process if C is specified as C<0>). The callback can look at the C member of the C watcher structure to see the status word (use the macros from C and see your systems C documentation). The C member contains the pid of the -process causing the status change. +process causing the status change. C must be either C<0> (only +activate the watcher when the process terminates) or C<1> (additionally +activate the watcher when the process is stopped or continued). =item int pid [read-only] @@ -1341,17 +1536,34 @@ =back -Example: Try to exit cleanly on SIGINT and SIGTERM. +=head3 Examples + +Example: C a new process and install a child handler to wait for +its completion. + + ev_child cw; static void - sigint_cb (struct ev_loop *loop, struct ev_signal *w, int revents) + child_cb (EV_P_ struct ev_child *w, int revents) { - ev_unloop (loop, EVUNLOOP_ALL); + ev_child_stop (EV_A_ w); + printf ("process %d exited with status %x\n", w->rpid, w->rstatus); } - struct ev_signal signal_watcher; - ev_signal_init (&signal_watcher, sigint_cb, SIGINT); - ev_signal_start (loop, &sigint_cb); + pid_t pid = fork (); + + if (pid < 0) + // error + else if (pid == 0) + { + // the forked child executes here + exit (1); + } + else + { + ev_child_init (&cw, child_cb, pid, 0); + ev_child_start (EV_DEFAULT_ &cw); + } =head2 C - did the file attributes just change? @@ -1390,6 +1602,39 @@ usually detected immediately, and if the file exists there will be no polling. +=head3 Inotify + +When C support has been compiled into libev (generally only +available on Linux) and present at runtime, it will be used to speed up +change detection where possible. The inotify descriptor will be created lazily +when the first C watcher is being started. + +Inotify presense does not change the semantics of C watchers +except that changes might be detected earlier, and in some cases, to avoid +making regular C calls. Even in the presense of inotify support +there are many cases where libev has to resort to regular C polling. + +(There is no support for kqueue, as apparently it cannot be used to +implement this functionality, due to the requirement of having a file +descriptor open on the object at all times). + +=head3 The special problem of stat time resolution + +The C syscall only supports full-second resolution portably, and +even on systems where the resolution is higher, many filesystems still +only support whole seconds. + +That means that, if the time is the only thing that changes, you might +miss updates: on the first update, C detects a change and calls +your callback, which does something. When there is another update within +the same second, C will be unable to detect it. + +The solution to this is to delay acting on a change for a second (or till +the next second boundary), using a roughly one-second delay C +(C). The C<.01> +is added to work around small timing inconsistencies of some operating +systems. + =head3 Watcher-Specific Functions and Data Members =over 4 @@ -1408,7 +1653,7 @@ relative to the attributes at the time the watcher was started (or the last change was detected). -=item ev_stat_stat (ev_stat *) +=item ev_stat_stat (loop, ev_stat *) Updates the stat buffer immediately with new values. If you change the watched path in your callback, you could call this fucntion to avoid @@ -1437,6 +1682,8 @@ =back +=head3 Examples + Example: Watch C for attribute changes. static void @@ -1458,8 +1705,36 @@ ... ev_stat passwd; - ev_stat_init (&passwd, passwd_cb, "/etc/passwd"); + ev_stat_init (&passwd, passwd_cb, "/etc/passwd", 0.); + ev_stat_start (loop, &passwd); + +Example: Like above, but additionally use a one-second delay so we do not +miss updates (however, frequent updates will delay processing, too, so +one might do the work both on C callback invocation I on +C callback invocation). + + static ev_stat passwd; + static ev_timer timer; + + static void + timer_cb (EV_P_ ev_timer *w, int revents) + { + ev_timer_stop (EV_A_ w); + + /* now it's one second after the most recent passwd change */ + } + + static void + stat_cb (EV_P_ ev_stat *w, int revents) + { + /* reset the one-second timer */ + ev_timer_again (EV_A_ &timer); + } + + ... + ev_stat_init (&passwd, stat_cb, "/etc/passwd", 0.); ev_stat_start (loop, &passwd); + ev_timer_init (&timer, timer_cb, 0., 1.01); =head2 C - when you've got nothing better to do... @@ -1495,6 +1770,8 @@ =back +=head3 Examples + Example: Dynamically allocate an C watcher, start it, and in the callback, free it. Also, use no error checking, as usual. @@ -1503,7 +1780,7 @@ { free (w); // now do something you wanted to do when the program has - // no longer asnything immediate to do. + // no longer anything immediate to do. } struct ev_idle *idle_watcher = malloc (sizeof (struct ev_idle)); @@ -1555,11 +1832,11 @@ priority, to ensure that they are being run before any other watchers after the poll. Also, C watchers (and C watchers, too) should not activate ("feed") events into libev. While libev fully -supports this, they will be called before other C watchers did -their job. As C watchers are often used to embed other event -loops those other event loops might be in an unusable state until their -C watcher ran (always remind yourself to coexist peacefully with -others). +supports this, they will be called before other C watchers +did their job. As C watchers are often used to embed other +(non-libev) event loops those other event loops might be in an unusable +state until their C watcher ran (always remind yourself to +coexist peacefully with others). =head3 Watcher-Specific Functions and Data Members @@ -1575,6 +1852,8 @@ =back +=head3 Examples + 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 that does this, which you could @@ -1752,26 +2031,7 @@ So when you want to use this feature you will always have to be prepared that you cannot get an embeddable loop. The recommended way to get around this is to have a separate variables for your embeddable loop, try to -create it, and if that fails, use the normal loop for everything: - - struct ev_loop *loop_hi = ev_default_init (0); - struct ev_loop *loop_lo = 0; - struct ev_embed embed; - - // see if there is a chance of getting one that works - // (remember that a flags value of 0 means autodetection) - loop_lo = ev_embeddable_backends () & ev_recommended_backends () - ? ev_loop_new (ev_embeddable_backends () & ev_recommended_backends ()) - : 0; - - // if we got one, then embed it, otherwise default to loop_hi - if (loop_lo) - { - ev_embed_init (&embed, 0, loop_lo); - ev_embed_start (loop_hi, &embed); - } - else - loop_lo = loop_hi; +create it, and if that fails, use the normal loop for everything. =head3 Watcher-Specific Functions and Data Members @@ -1799,6 +2059,54 @@ =back +=head3 Examples + +Example: Try to get an embeddable event loop and embed it into the default +event loop. If that is not possible, use the default loop. The default +loop is stored in C, while the mebeddable loop is stored in +C (which is C in the acse no embeddable loop can be +used). + + struct ev_loop *loop_hi = ev_default_init (0); + struct ev_loop *loop_lo = 0; + struct ev_embed embed; + + // see if there is a chance of getting one that works + // (remember that a flags value of 0 means autodetection) + loop_lo = ev_embeddable_backends () & ev_recommended_backends () + ? ev_loop_new (ev_embeddable_backends () & ev_recommended_backends ()) + : 0; + + // if we got one, then embed it, otherwise default to loop_hi + if (loop_lo) + { + ev_embed_init (&embed, 0, loop_lo); + ev_embed_start (loop_hi, &embed); + } + else + loop_lo = loop_hi; + +Example: Check if kqueue is available but not recommended and create +a kqueue backend for use with sockets (which usually work with any +kqueue implementation). Store the kqueue/socket-only event loop in +C. (One might optionally use C, too). + + struct ev_loop *loop = ev_default_init (0); + struct ev_loop *loop_socket = 0; + struct ev_embed embed; + + if (ev_supported_backends () & ~ev_recommended_backends () & EVBACKEND_KQUEUE) + if ((loop_socket = ev_loop_new (EVBACKEND_KQUEUE)) + { + ev_embed_init (&embed, 0, loop_socket); + ev_embed_start (loop, &embed); + } + + if (!loop_socket) + loop_socket = loop; + + // now use loop_socket for all sockets, and loop for everything else + =head2 C - the audacity to resume the event loop after a fork @@ -1823,6 +2131,137 @@ =back +=head2 C - how to wake up another event loop + +In general, you cannot use an C from multiple threads or other +asynchronous sources such as signal handlers (as opposed to multiple event +loops - those are of course safe to use in different threads). + +Sometimes, however, you need to wake up another event loop you do not +control, for example because it belongs to another thread. This is what +C watchers do: as long as the C watcher is active, you +can signal it by calling C, which is thread- and signal +safe. + +This functionality is very similar to C watchers, as signals, +too, are asynchronous in nature, and signals, too, will be compressed +(i.e. the number of callback invocations may be less than the number of +C calls). + +Unlike C watchers, C works with any event loop, not +just the default loop. + +=head3 Queueing + +C does not support queueing of data in any way. The reason +is that the author does not know of a simple (or any) algorithm for a +multiple-writer-single-reader queue that works in all cases and doesn't +need elaborate support such as pthreads. + +That means that if you want to queue data, you have to provide your own +queue. But at least I can tell you would implement locking around your +queue: + +=over 4 + +=item queueing from a signal handler context + +To implement race-free queueing, you simply add to the queue in the signal +handler but you block the signal handler in the watcher callback. Here is an example that does that for +some fictitiuous SIGUSR1 handler: + + static ev_async mysig; + + static void + sigusr1_handler (void) + { + sometype data; + + // no locking etc. + queue_put (data); + ev_async_send (EV_DEFAULT_ &mysig); + } + + static void + mysig_cb (EV_P_ ev_async *w, int revents) + { + sometype data; + sigset_t block, prev; + + sigemptyset (&block); + sigaddset (&block, SIGUSR1); + sigprocmask (SIG_BLOCK, &block, &prev); + + while (queue_get (&data)) + process (data); + + if (sigismember (&prev, SIGUSR1) + sigprocmask (SIG_UNBLOCK, &block, 0); + } + +(Note: pthreads in theory requires you to use C +instead of C when you use threads, but libev doesn't do it +either...). + +=item queueing from a thread context + +The strategy for threads is different, as you cannot (easily) block +threads but you can easily preempt them, so to queue safely you need to +employ a traditional mutex lock, such as in this pthread example: + + static ev_async mysig; + static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; + + static void + otherthread (void) + { + // only need to lock the actual queueing operation + pthread_mutex_lock (&mymutex); + queue_put (data); + pthread_mutex_unlock (&mymutex); + + ev_async_send (EV_DEFAULT_ &mysig); + } + + static void + mysig_cb (EV_P_ ev_async *w, int revents) + { + pthread_mutex_lock (&mymutex); + + while (queue_get (&data)) + process (data); + + pthread_mutex_unlock (&mymutex); + } + +=back + + +=head3 Watcher-Specific Functions and Data Members + +=over 4 + +=item ev_async_init (ev_async *, callback) + +Initialises and configures the async watcher - it has no parameters of any +kind. There is a C macro, but using it is utterly pointless, +believe me. + +=item ev_async_send (loop, ev_async *) + +Sends/signals/activates the given C watcher, that is, feeds +an C event on the watcher into the event loop. Unlike +C, this call is safe to do in other threads, signal or +similar contexts (see the dicusssion of C in the embedding +section below on what exactly this means). + +This call incurs the overhead of a syscall only once per loop iteration, +so while the overhead might be noticable, it doesn't apply to repeated +calls to C. + +=back + + =head1 OTHER FUNCTIONS There are some other functions of possible interest. Described. Here. Now. @@ -2059,19 +2498,52 @@ class myclass { - ev_io io; void io_cb (ev::io &w, int revents); - ev_idle idle void idle_cb (ev::idle &w, int revents); + ev::io io; void io_cb (ev::io &w, int revents); + ev:idle idle void idle_cb (ev::idle &w, int revents); - myclass (); - } + myclass (int fd) + { + io .set (this); + idle.set (this); - myclass::myclass (int fd) - { - io .set (this); - idle.set (this); + io.start (fd, ev::READ); + } + }; - io.start (fd, ev::READ); - } + +=head1 OTHER LANGUAGE BINDINGS + +Libev does not offer other language bindings itself, but bindings for a +numbe rof languages exist in the form of third-party packages. If you know +any interesting language binding in addition to the ones listed here, drop +me a note. + +=over 4 + +=item Perl + +The EV module implements the full libev API and is actually used to test +libev. EV is developed together with libev. Apart from the EV core module, +there are additional modules that implement libev-compatible interfaces +to C (C), C (C) and the +C event core (C and C). + +It can be found and installed via CPAN, its homepage is found at +L. + +=item Ruby + +Tony Arcieri has written a ruby extension that offers access to a subset +of the libev API and adds filehandle abstractions, asynchronous DNS and +more on top of it. It can be found via gem servers. Its homepage is at +L. + +=item D + +Leandro Lucarella has written a D language binding (F) for libev, to +be found at L. + +=back =head1 MACRO MAGIC @@ -2242,7 +2714,7 @@ monotonic clock option at both compiletime and runtime. Otherwise no use of the monotonic clock option will be attempted. If you enable this, you usually have to link against librt or something similar. Enabling it when -the functionality isn't available is safe, though, althoguh you have +the functionality isn't available is safe, though, although you have to make sure you link against any libraries where the C function is hiding in (often F<-lrt>). @@ -2255,6 +2727,11 @@ (CLOCK_REALTIME, ...)> and will not normally affect correctness. See the note about libraries in the description of C, though. +=item EV_USE_NANOSLEEP + +If defined to be C<1>, libev will assume that C is available +and will use it for delays. Otherwise it will use C function doesn't follow POSIX in that it requires +socket I and not socket I. This makes select +very inefficient, and also requires a mapping from file descriptors +to socket handles. See the discussion of the C, +C and C preprocessor +symbols for more info. + +The configuration for a "naked" win32 using the microsoft runtime +libraries and raw winsocket select is: + + #define EV_USE_SELECT 1 + #define EV_SELECT_IS_WINSOCKET 1 /* forces EV_SELECT_USE_FD_SET, too */ + +Note that winsockets handling of fd sets is O(n), so you can easily get a +complexity in the O(n²) range when using win32. + +=item Limited number of file descriptors + +Windows has numerous arbitrary (and low) limits on things. Early versions +of winsocket's select only supported waiting for a max. of C<64> handles +(probably owning to the fact that all windows kernels can only wait for +C<64> things at the same time internally; microsoft recommends spawning a +chain of threads and wait for 63 handles and the previous thread in each). + +Newer versions support more handles, but you need to define C +to some high number (e.g. C<2048>) before compiling the winsocket select +call (which might be in libev or elsewhere, for example, perl does its own +select emulation on windows). + +Another limit is the number of file descriptors in the microsoft runtime +libraries, which by default is C<64> (there must be a hidden I<64> fetish +or something like this inside microsoft). You can increase this by calling +C<_setmaxstdio>, which can increase this limit to C<2048> (another +arbitrary limit), but is broken in many versions of the microsoft runtime +libraries. + +This might get you to about C<512> or C<2048> sockets (depending on +windows version and/or the phase of the moon). To get more, you need to +wrap all I/O functions and provide your own fd management, but the cost of +calling select (O(n²)) will likely make this unworkable. =back