--- libev/ev.pod 2009/08/29 08:15:11 1.268 +++ libev/ev.pod 2011/01/17 12:11:12 1.360 @@ -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,7 +58,7 @@ 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 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 @@ -120,19 +128,20 @@ more info about various configuration options please have a look at B section in this manual. If libev was configured without support for multiple event loops, then all functions taking an initial argument of -name C (which is always of type C) will not have +name C (which is always of type C) will not have this argument. =head2 TIME REPRESENTATION Libev represents time as a single floating point number, representing -the (fractional) number of seconds since the (POSIX) epoch (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 any calculations -on it, you should treat it as some floating point value. Unlike the name -component C might indicate, it is also used for time differences -throughout libev. +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 +any calculations on it, you should treat it as some floating point value. + +Unlike the name component C might indicate, it is also used for +time differences (e.g. delays) throughout libev. =head1 ERROR HANDLING @@ -166,7 +175,8 @@ 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) @@ -193,7 +203,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 @@ -214,24 +225,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 @@ -267,7 +279,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 @@ -289,40 +301,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). @@ -347,9 +397,8 @@ =item C -Instead of calling C or C manually after -a fork, you can also make libev check for a fork in each iteration by -enabling this flag. +Instead of calling C manually after a fork, you can also +make libev check for a fork in each iteration by enabling this flag. 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 @@ -368,17 +417,37 @@ =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 +=item C -When this flag is specified, then libev will not attempt to use the -I API for it's C (and C) watchers. This is -probably only useful to work around any bugs in libev. Consequently, this -flag might go away once the signalfd functionality is considered stable, -so it's useful mostly in environment variables and not in program code. +When this flag is specified, then libev will attempt to use the +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 +threads that are not interested in handling them. + +Signalfd will not be used by default as this changes your signal mask, and +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 ahve 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) @@ -413,6 +482,9 @@ =item C (value 4, Linux) +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), @@ -421,11 +493,13 @@ 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. +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 @@ -433,7 +507,13 @@ 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. +events to filter out spurious ones, recreating the set when required. 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 @@ -1517,6 +1663,44 @@ ignore SIGPIPE (and maybe make sure you log the exit status of your daemon somewhere, as that would have given you a big clue). +=head3 The special problem of accept()ing when you can't + +Many implementations of the POSIX C function (for example, +found in post-2004 Linux) have the peculiar behaviour of not removing a +connection from the pending queue in all error cases. + +For example, larger servers often run out of file descriptors (because +of resource limits), causing C to fail with C but not +rejecting the connection, leading to libev signalling readiness on +the next iteration again (the connection still exists after all), and +typically causing the program to loop at 100% CPU usage. + +Unfortunately, the set of errors that cause this issue differs between +operating systems, there is usually little the app can do to remedy the +situation, and no known thread-safe method of removing the connection to +cope with overload is known (to me). + +One of the easiest ways to handle this situation is to just ignore it +- when the program encounters an overload, it will just loop until the +situation is over. While this is a form of busy waiting, no OS offers an +event-based way to handle this situation, so it's the best one can do. + +A better way to handle the situation is to log any errors other than +C and C, making sure not to flood the log with such +messages, and continue as usual, which at least gives the user an idea of +what could be wrong ("raise the ulimit!"). For extra points one could stop +the C watcher on the listening fd "for a while", which reduces CPU +usage. + +If your program is single-threaded, then you could also keep a dummy file +descriptor for overload situations (e.g. by opening F), and +when you run into C or C, close it, run C, +close that fd, and create a new dummy fd. This will gracefully refuse +clients under typical overload conditions. + +The last way to handle it is to simply log the error and C, as +is often done with C failures, but this results in an easy +opportunity for a DoS attack. =head3 Watcher-Specific Functions @@ -1558,7 +1742,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 @@ -1577,7 +1761,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 @@ -1673,7 +1857,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 { @@ -1705,12 +1889,12 @@ ev_init (timer, callback); last_activity = ev_now (loop); - callback (loop, timer, EV_TIMEOUT); + callback (loop, timer, EV_TIMER); 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. @@ -1758,7 +1942,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. @@ -1839,14 +2023,14 @@ This sounds a bit complicated, see L, above, for a usage example. -=item ev_timer_remaining (loop, ev_timer *) +=item ev_tstamp ev_timer_remaining (loop, ev_timer *) Returns the remaining time until a timer fires. If the timer is active, then this time is relative to the current event loop time, otherwise it's the timeout value currently configured. That is, after an C, C returns -C<5>. When the timer is started and one second passes, C +C<5>. When the timer is started and one second passes, C will return C<4>. When the timer expires and is restarted, it will return roughly C<7> (likely slightly less as callback invocation takes some time, too), and so on. @@ -1885,7 +2069,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 @@ -1921,7 +2105,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 @@ -2059,7 +2243,7 @@ potentially a lot of jitter, but good long-term stability. static void - clock_cb (struct ev_loop *loop, ev_io *w, int revents) + clock_cb (struct ev_loop *loop, ev_periodic *w, int revents) { ... its now a full hour (UTC, or TAI or whatever your clock follows) } @@ -2092,7 +2276,7 @@ Signal watchers will trigger an event when the process receives a specific signal one or more times. Even though signals are very asynchronous, libev -will try it's best to deliver signals synchronously, i.e. as part of the +will try its best to deliver signals synchronously, i.e. as part of the normal event processing, like any other event. If you want signals to be delivered truly asynchronously, just use @@ -2116,12 +2300,13 @@ interrupted by signals you can block all signals in an C watcher and unblock them in an C watcher. -=head3 The special problem of inheritance over execve +=head3 The special problem of inheritance over fork/execve/pthread_create Both the signal mask (C) and the signal disposition (C) are unspecified after starting a signal watcher (and after stopping it again), that is, libev might or might not block the signal, -and might or might not set or restore the installed signal handler. +and might or might not set or restore the installed signal handler (but +see C). While this does not matter for the signal disposition (libev never sets signals to C, so handlers will be reset to C on @@ -2136,10 +2321,28 @@ to install a fork handler with C that resets it. That will catch fork calls done by libraries (such as the libc) as well. -In current versions of libev, you can also ensure that the signal mask is -not blocking any signals (except temporarily, so thread users watch out) -by specifying the C when creating the event loop. This -is not guaranteed for future versions, however. +In current versions of libev, the signal will not be blocked indefinitely +unless you use the C API (C). While this reduces +the window of opportunity for problems, it will not go away, as libev +I to modify the signal mask, at least temporarily. + +So I can't stress this enough: I. This +is not a libev-specific thing, this is true for most event libraries. + +=head3 The special problem of threads signal handling + +POSIX threads has problematic signal handling semantics, specifically, +a lot of functionality (sigfd, sigwait etc.) only really works if all +threads in a process block signals, which is hard to achieve. + +When you want to use sigwait (or mix libev signal handling with your own +for the same signals), you can tackle this problem by globally blocking +all signals before creating any threads (or creating them with a fully set +sigprocmask) and also specifying the C when creating +loops. Then designate one thread as "signal receiver thread" which handles +these signals. You can pass on any signals that libev might be interested +in by calling C. =head3 Watcher-Specific Functions and Data Members @@ -2165,7 +2368,7 @@ static void sigint_cb (struct ev_loop *loop, ev_signal *w, int revents) { - ev_unloop (loop, EVUNLOOP_ALL); + ev_break (loop, EVBREAK_ALL); } ev_signal signal_watcher; @@ -2561,7 +2764,7 @@ prepare watchers get invoked before the process blocks and check watchers afterwards. -You I call C or similar functions that enter +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 @@ -2739,7 +2942,7 @@ // create/start timer // poll - ev_loop (EV_A_ 0); + ev_run (EV_A_ 0); // stop timer again if (timeout >= 0) @@ -2827,7 +3030,7 @@ =item ev_embed_sweep (loop, ev_embed *) Make a single, non-blocking sweep over the embedded loop. This works -similarly to C, but in the most +similarly to C, but in the most appropriate way for embedded loops. =item struct ev_loop *other [read-only] @@ -2897,7 +3100,7 @@ =head3 The special problem of life after fork - how is it possible? -Most uses of C consist of forking, then some simple calls to ste +Most uses of C consist of forking, then some simple calls to set up/change the process environment, followed by a call to C. This sequence should be handled by libev without any problems. @@ -2923,40 +3126,83 @@ When this is not possible, or you want to use the default loop for other reasons, then in the process that wants to start "fresh", call -C followed by C. Destroying -the default loop will "orphan" (not stop) all registered watchers, so you -have to be careful not to execute code that modifies those watchers. Note -also that in that case, you have to re-register any signal watchers. +C followed by C. +Destroying the default loop will "orphan" (not stop) all registered +watchers, so you have to be careful not to execute code that modifies +those watchers. Note also that in that case, you have to re-register any +signal watchers. =head3 Watcher-Specific Functions and Data Members =over 4 -=item ev_fork_init (ev_signal *, callback) +=item ev_fork_init (ev_fork *, callback) Initialises and configures the fork watcher - it has no parameters of any kind. There is a C macro, but using it is utterly pointless, -believe me. +really. =back -=head2 C - how to wake up another event loop +=head2 C - even the best things end + +Cleanup watchers are called just before the event loop is being destroyed +by a call to C. + +While there is no guarantee that the event loop gets destroyed, cleanup +watchers provide a convenient method to install cleanup hooks for your +program, worker threads and so on - you just to make sure to destroy the +loop when you want them to be invoked. + +Cleanup watchers are invoked in the same way as any other watcher. Unlike +all other watchers, they do not keep a reference to the event loop (which +makes a lot of sense if you think about it). Like all other watchers, you +can call libev functions in the callback, except C. + +=head3 Watcher-Specific Functions and Data Members + +=over 4 -In general, you cannot use an C from multiple threads or other +=item ev_cleanup_init (ev_cleanup *, callback) + +Initialises and configures the cleanup watcher - it has no parameters of +any kind. There is a C macro, but using it is utterly +pointless, I assure you. + +=back + +Example: Register an atexit handler to destroy the default loop, so any +cleanup functions are called. + + static void + program_exits (void) + { + ev_loop_destroy (EV_DEFAULT_UC); + } + + ... + atexit (program_exits); + + +=head2 C - how to wake up an 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. +Sometimes, however, you need to wake up an 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). +C calls). In fact, you could use signal watchers as a kind +of "global async watchers" by using a watcher on an otherwise unused +signal, and C to signal this watcher from another thread, +even without knowing which loop owns the signal. Unlike C watchers, C works with any event loop, not just the default loop. @@ -2966,7 +3212,8 @@ 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. +need elaborate support such as pthreads or unportable memory access +semantics. That means that if you want to queue data, you have to provide your own queue. But at least I can tell you how to implement locking around your @@ -3115,9 +3362,9 @@ started. Otherwise an C watcher with after = C (and repeat = 0) will be started. C<0> is a valid timeout. -The callback has the type C and gets +The callback has the type C and is passed an C set like normal event callbacks (a combination of -C, C, C or C) and the C +C, C, C or C) and the C value passed to C. Note that it is possible to receive I a timeout and an io event at the same time - you probably should give io events precedence. @@ -3128,31 +3375,335 @@ { if (revents & EV_READ) /* stdin might have data for us, joy! */; - else if (revents & EV_TIMEOUT) + else if (revents & EV_TIMER) /* doh, nothing entered */; } ev_once (STDIN_FILENO, EV_READ, 10., stdin_ready, 0); -=item ev_feed_event (struct ev_loop *, watcher *, int revents) - -Feeds the given event set into the event loop, as if the specified event -had happened for the specified watcher (which must be a pointer to an -initialised but not necessarily started event watcher). - -=item ev_feed_fd_event (struct ev_loop *, int fd, int revents) +=item ev_feed_fd_event (loop, int fd, int revents) Feed an event on the given fd, as if a file descriptor backend detected the given events it. -=item ev_feed_signal_event (struct ev_loop *loop, int signum) +=item ev_feed_signal_event (loop, int signum) -Feed an event as if the given signal occurred (C must be the default -loop!). +Feed an event as if the given signal occurred. See also C, +which is async-safe. =back +=head1 COMMON OR USEFUL IDIOMS (OR BOTH) + +This section explains some common idioms that are not immediately +obvious. Note that examples are sprinkled over the whole manual, and this +section only contains stuff that wouldn't fit anywhere else. + +=head2 ASSOCIATING CUSTOM DATA WITH A WATCHER + +Each watcher has, by default, a C member that you can read +or modify at any time: libev will completely ignore it. This can be used +to associate arbitrary data with your watcher. If you need more data and +don't want to allocate memory separately and store a pointer to it in that +data member, you can also "subclass" the watcher type and provide your own +data: + + struct my_io + { + ev_io io; + int otherfd; + void *somedata; + struct whatever *mostinteresting; + }; + + ... + struct my_io w; + ev_io_init (&w.io, my_cb, fd, EV_READ); + +And since your callback will be called with a pointer to the watcher, you +can cast it back to your own type: + + static void my_cb (struct ev_loop *loop, ev_io *w_, int revents) + { + struct my_io *w = (struct my_io *)w_; + ... + } + +More interesting and less C-conformant ways of casting your callback +function type instead have been omitted. + +=head2 BUILDING YOUR OWN COMPOSITE WATCHERS + +Another common scenario is to use some data structure with multiple +embedded watchers, in effect creating your own watcher that combines +multiple libev event sources into one "super-watcher": + + struct my_biggy + { + int some_data; + ev_timer t1; + ev_timer t2; + } + +In this case getting the pointer to C is a bit more +complicated: Either you store the address of your C struct in +the C member of the watcher (for woozies or C++ coders), or you need +to use some pointer arithmetic using C inside your watchers (for +real programmers): + + #include + + static void + t1_cb (EV_P_ ev_timer *w, int revents) + { + struct my_biggy big = (struct my_biggy *) + (((char *)w) - offsetof (struct my_biggy, t1)); + } + + static void + t2_cb (EV_P_ ev_timer *w, int revents) + { + struct my_biggy big = (struct my_biggy *) + (((char *)w) - offsetof (struct my_biggy, t2)); + } + +=head2 MODEL/NESTED EVENT LOOP INVOCATIONS AND EXIT CONDITIONS + +Often (especially in GUI toolkits) there are places where you have +I interaction, which is most easily implemented by recursively +invoking C. + +This brings the problem of exiting - a callback might want to finish the +main C call, but not the nested one (e.g. user clicked "Quit", but +a modal "Are you sure?" dialog is still waiting), or just the nested one +and not the main one (e.g. user clocked "Ok" in a modal dialog), or some +other combination: In these cases, C will not work alone. + +The solution is to maintain "break this loop" variable for each C +invocation, and use a loop around C until the condition is +triggered, using C: + + // main loop + int exit_main_loop = 0; + + while (!exit_main_loop) + ev_run (EV_DEFAULT_ EVRUN_ONCE); + + // in a model watcher + int exit_nested_loop = 0; + + while (!exit_nested_loop) + ev_run (EV_A_ EVRUN_ONCE); + +To exit from any of these loops, just set the corresponding exit variable: + + // exit modal loop + exit_nested_loop = 1; + + // exit main program, after modal loop is finished + exit_main_loop = 1; + + // exit both + exit_main_loop = exit_nested_loop = 1; + +=head2 THREAD LOCKING EXAMPLE + +Here is a fictitious example of how to run an event loop in a different +thread from where callbacks are being invoked and watchers are +created/added/removed. + +For a real-world example, see the C perl module, +which uses exactly this technique (which is suited for many high-level +languages). + +The example uses a pthread mutex to protect the loop data, a condition +variable to wait for callback invocations, an async watcher to notify the +event loop thread and an unspecified mechanism to wake up the main thread. + +First, you need to associate some data with the event loop: + + typedef struct { + mutex_t lock; /* global loop lock */ + ev_async async_w; + thread_t tid; + cond_t invoke_cv; + } userdata; + + void prepare_loop (EV_P) + { + // for simplicity, we use a static userdata struct. + static userdata u; + + ev_async_init (&u->async_w, async_cb); + ev_async_start (EV_A_ &u->async_w); + + pthread_mutex_init (&u->lock, 0); + pthread_cond_init (&u->invoke_cv, 0); + + // now associate this with the loop + ev_set_userdata (EV_A_ u); + ev_set_invoke_pending_cb (EV_A_ l_invoke); + ev_set_loop_release_cb (EV_A_ l_release, l_acquire); + + // then create the thread running ev_loop + pthread_create (&u->tid, 0, l_run, EV_A); + } + +The callback for the C watcher does nothing: the watcher is used +solely to wake up the event loop so it takes notice of any new watchers +that might have been added: + + static void + async_cb (EV_P_ ev_async *w, int revents) + { + // just used for the side effects + } + +The C and C callbacks simply unlock/lock the mutex +protecting the loop data, respectively. + + static void + l_release (EV_P) + { + userdata *u = ev_userdata (EV_A); + pthread_mutex_unlock (&u->lock); + } + + static void + l_acquire (EV_P) + { + userdata *u = ev_userdata (EV_A); + pthread_mutex_lock (&u->lock); + } + +The event loop thread first acquires the mutex, and then jumps straight +into C: + + void * + l_run (void *thr_arg) + { + struct ev_loop *loop = (struct ev_loop *)thr_arg; + + l_acquire (EV_A); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); + ev_run (EV_A_ 0); + l_release (EV_A); + + return 0; + } + +Instead of invoking all pending watchers, the C callback will +signal the main thread via some unspecified mechanism (signals? pipe +writes? C?) and then waits until all pending watchers +have been called (in a while loop because a) spurious wakeups are possible +and b) skipping inter-thread-communication when there are no pending +watchers is very beneficial): + + static void + l_invoke (EV_P) + { + userdata *u = ev_userdata (EV_A); + + while (ev_pending_count (EV_A)) + { + wake_up_other_thread_in_some_magic_or_not_so_magic_way (); + pthread_cond_wait (&u->invoke_cv, &u->lock); + } + } + +Now, whenever the main thread gets told to invoke pending watchers, it +will grab the lock, call C and then signal the loop +thread to continue: + + static void + real_invoke_pending (EV_P) + { + userdata *u = ev_userdata (EV_A); + + pthread_mutex_lock (&u->lock); + ev_invoke_pending (EV_A); + pthread_cond_signal (&u->invoke_cv); + pthread_mutex_unlock (&u->lock); + } + +Whenever you want to start/stop a watcher or do other modifications to an +event loop, you will now have to lock: + + ev_timer timeout_watcher; + userdata *u = ev_userdata (EV_A); + + ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); + + pthread_mutex_lock (&u->lock); + ev_timer_start (EV_A_ &timeout_watcher); + ev_async_send (EV_A_ &u->async_w); + pthread_mutex_unlock (&u->lock); + +Note that sending the C watcher is required because otherwise +an event loop currently blocking in the kernel will have no knowledge +about the newly added timer. By waking up the loop it will pick up any new +watchers in the next event loop iteration. + +=head2 THREADS, COROUTINES, CONTINUATIONS, QUEUES... INSTEAD OF CALLBACKS + +While the overhead of a callback that e.g. schedules a thread is small, it +is still an overhead. If you embed libev, and your main usage is with some +kind of threads or coroutines, you might want to customise libev so that +doesn't need callbacks anymore. + +Imagine you have coroutines that you can switch to using a function +C, that libev runs in a coroutine called C +and that due to some magic, the currently active coroutine is stored in a +global called C. Then you can build your own "wait for libev +event" primitive by changing C and C (note +the differing C<;> conventions): + + #define EV_CB_DECLARE(type) struct my_coro *cb; + #define EV_CB_INVOKE(watcher) switch_to ((watcher)->cb) + +That means instead of having a C callback function, you store the +coroutine to switch to in each watcher, and instead of having libev call +your callback, you instead have it switch to that coroutine. + +A coroutine might now wait for an event with a function called +C. (the watcher needs to be started, as always, but it doesn't +matter when, or whether the watcher is active or not when this function is +called): + + void + wait_for_event (ev_watcher *w) + { + ev_cb_set (w) = current_coro; + switch_to (libev_coro); + } + +That basically suspends the coroutine inside C and +continues the libev coroutine, which, when appropriate, switches back to +this or any other coroutine. I am sure if you sue this your own :) + +You can do similar tricks if you have, say, threads with an event queue - +instead of storing a coroutine, you store the queue object and instead of +switching to a coroutine, you push the watcher onto the queue and notify +any waiters. + +To embed libev, see L, but in short, it's easiest to create two +files, F and F that include the respective libev files: + + // my_ev.h + #define EV_CB_DECLARE(type) struct my_coro *cb; + #define EV_CB_INVOKE(watcher) switch_to ((watcher)->cb); + #include "../libev/ev.h" + + // my_ev.c + #define EV_H "my_ev.h" + #include "../libev/ev.c" + +And then use F when you would normally use F, and compile +F into your project. When properly specifying include paths, you +can even use F as header file name directly. + + =head1 LIBEVENT EMULATION Libev offers a compatibility emulation layer for libevent. It cannot @@ -3160,6 +3711,11 @@ =over 4 +=item * Only the libevent-1.4.1-beta API is being emulated. + +This was the newest libevent version available when libev was implemented, +and is still mostly unchanged in 2010. + =item * Use it by including , as usual. =item * The following members are fully supported: ev_base, ev_callback, @@ -3174,7 +3730,7 @@ is an ev_pri field. =item * In libevent, the last base created gets the signals, in libev, the -first base created (== the default loop) gets the signals. +base that registered the signal gets the signals. =item * Other members are not supported. @@ -3203,11 +3759,11 @@ that the watcher is associated with (or no additional members at all if you disable C when embedding libev). -Currently, functions, and static and non-static member functions can be -used as callbacks. Other types should be easy to add as long as they only -need one additional pointer for context. If you need support for other -types of functors please contact the author (preferably after implementing -it). +Currently, functions, static and non-static member functions and classes +with C can be used as callbacks. Other types should be easy +to add as long as they only need one additional pointer for context. If +you need support for other types of functors please contact the author +(preferably after implementing it). Here is a list of things available in the C namespace: @@ -3235,7 +3791,7 @@ =item ev::TYPE::TYPE () -=item ev::TYPE::TYPE (struct ev_loop *) +=item ev::TYPE::TYPE (loop) =item ev::TYPE::~TYPE @@ -3279,8 +3835,6 @@ =item w->set (object *) -This is an B feature that might go away in a future version. - This is a variation of a method callback - leaving out the method to call will default the method to C, which makes it possible to use functor objects without having to manually specify the C all @@ -3322,23 +3876,29 @@ static void io_cb (ev::io &w, int revents) { } iow.set (); -=item w->set (struct ev_loop *) +=item w->set (loop) Associates a different C with this watcher. You can only do this when the watcher is inactive (and not pending either). =item w->set ([arguments]) -Basically the same as C, with the same arguments. Must be -called at least once. Unlike the C counterpart, an active watcher gets -automatically stopped and restarted when reconfiguring it with this -method. +Basically the same as C, with the same arguments. Either this +method or a suitable start method must be called at least once. Unlike the +C counterpart, an active watcher gets automatically stopped and restarted +when reconfiguring it with this method. =item w->start () Starts the watcher. Note that there is no C argument, as the constructor already stores the event loop. +=item w->start ([arguments]) + +Instead of calling C and C methods separately, it is often +convenient to wrap them in one call. Uses the same type of arguments as +the configure C method of the watcher. + =item w->stop () Stops the watcher if it is active. Again, no C argument. @@ -3360,20 +3920,25 @@ =back -Example: Define a class with an IO and idle watcher, start one of them in -the constructor. +Example: Define a class with two I/O and idle watchers, start the I/O +watchers in the constructor. class myclass { ev::io io ; void io_cb (ev::io &w, int revents); + ev::io2 io2 ; void io2_cb (ev::io &w, int revents); ev::idle idle; void idle_cb (ev::idle &w, int revents); myclass (int fd) { io .set (this); + io2 .set (this); idle.set (this); - io.start (fd, ev::READ); + io.set (fd, ev::WRITE); // configure the watcher + io.start (); // start it whenever convenient + + io2.start (fd, ev::READ); // set + start in one call } }; @@ -3431,8 +3996,8 @@ =item Lua -Brian Maher has written a partial interface to libev -for lua (only C and C), to be found at +Brian Maher has written a partial interface to libev for lua (at the +time of this writing, only C and C), to be found at L. =back @@ -3457,7 +4022,7 @@ ev_unref (EV_A); ev_timer_add (EV_A_ watcher); - ev_loop (EV_A_ 0); + ev_run (EV_A_ 0); It assumes the variable C of type C is in scope, which is often provided by the following macro. @@ -3507,7 +4072,7 @@ ev_check check; ev_check_init (&check, check_cb); ev_check_start (EV_DEFAULT_ &check); - ev_loop (EV_DEFAULT_ 0); + ev_run (EV_DEFAULT_ 0); =head1 EMBEDDING @@ -3597,12 +4162,35 @@ =head2 PREPROCESSOR SYMBOLS/MACROS Libev can be configured via a variety of preprocessor symbols you have to -define before including any of its files. The default in the absence of -autoconf is documented for every option. +define before including (or compiling) any of its files. The default in +the absence of autoconf is documented for every option. + +Symbols marked with "(h)" do not change the ABI, and can have different +values when compiling libev vs. including F, so it is permissible +to redefine them before including F without breaking compatibility +to a compiled library. All other symbols change the ABI, which means all +users of libev and the libev code itself must be compiled with compatible +settings. =over 4 -=item EV_STANDALONE +=item EV_COMPAT3 (h) + +Backwards compatibility is a major concern for libev. This is why this +release of libev comes with wrappers for the functions and symbols that +have been renamed between libev version 3 and 4. + +You can disable these wrappers (to test compatibility with future +versions) by defining C to C<0> when compiling your +sources. This has the additional advantage that you can drop the C +from C declarations, as libev will provide an C +typedef in that case. + +In some future version, the default for C will become C<0>, +and in some even more future version the compatibility code will be +removed completely. + +=item EV_STANDALONE (h) Must always be C<1> if you do not use autoconf configuration, which keeps libev from including F, and it also defines dummy @@ -3762,24 +4350,24 @@ In the absence of this define, libev will use C (from F), which is usually good enough on most platforms. -=item EV_H +=item EV_H (h) The name of the F header file used to include it. The default if undefined is C<"ev.h"> in F, F and F. This can be used to virtually rename the F header file in case of conflicts. -=item EV_CONFIG_H +=item EV_CONFIG_H (h) If C isn't C<1>, this variable can be used to override F's idea of where to find the F file, similarly to C, above. -=item EV_EVENT_H +=item EV_EVENT_H (h) Similarly to C, this macro can be used to override F's idea of how the F header can be found, the default is C<"event.h">. -=item EV_PROTOTYPES +=item EV_PROTOTYPES (h) If defined to be C<0>, then F will not define any function prototypes, but still define all the structs and other symbols. This is @@ -3811,55 +4399,106 @@ If your embedding application does not need any priorities, defining these both to C<0> will save some memory and CPU. -=item EV_PERIODIC_ENABLE +=item EV_PERIODIC_ENABLE, EV_IDLE_ENABLE, EV_EMBED_ENABLE, EV_STAT_ENABLE, +EV_PREPARE_ENABLE, EV_CHECK_ENABLE, EV_FORK_ENABLE, EV_SIGNAL_ENABLE, +EV_ASYNC_ENABLE, EV_CHILD_ENABLE. + +If undefined or defined to be C<1> (and the platform supports it), then +the respective watcher type is supported. If defined to be C<0>, then it +is not. Disabling watcher types mainly saves code size. -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_FEATURES -=item EV_IDLE_ENABLE +If you need to shave off some kilobytes of code at the expense of some +speed (but with the full API), you can define this symbol to request +certain subsets of functionality. The default is to enable all features +that can be enabled on the platform. + +A typical way to use this symbol is to define it to C<0> (or to a bitset +with some broad features you want) and then selectively re-enable +additional parts you want, for example if you want everything minimal, +but multiple event loop support, async and child watchers and the poll +backend, use this: + + #define EV_FEATURES 0 + #define EV_MULTIPLICITY 1 + #define EV_USE_POLL 1 + #define EV_CHILD_ENABLE 1 + #define EV_ASYNC_ENABLE 1 -If undefined or defined to be C<1>, then idle watchers are supported. If -defined to be C<0>, then they are not. Disabling them saves a few kB of -code. +The actual value is a bitset, it can be a combination of the following +values: -=item EV_EMBED_ENABLE +=over 4 -If undefined or defined to be C<1>, then embed watchers are supported. If -defined to be C<0>, then they are not. Embed watchers rely on most other -watcher types, which therefore must not be disabled. +=item C<1> - faster/larger code -=item EV_STAT_ENABLE +Use larger code to speed up some operations. -If undefined or defined to be C<1>, then stat watchers are supported. If -defined to be C<0>, then they are not. +Currently this is used to override some inlining decisions (enlarging the +code size by roughly 30% on amd64). -=item EV_FORK_ENABLE +When optimising for size, use of compiler flags such as C<-Os> with +gcc is recommended, as well as C<-DNDEBUG>, as libev contains a number of +assertions. -If undefined or defined to be C<1>, then fork watchers are supported. If -defined to be C<0>, then they are not. +=item C<2> - faster/larger data structures -=item EV_ASYNC_ENABLE +Replaces the small 2-heap for timer management by a faster 4-heap, larger +hash table sizes and so on. This will usually further increase code size +and can additionally have an effect on the size of data structures at +runtime. -If undefined or defined to be C<1>, then async watchers are supported. If -defined to be C<0>, then they are not. +=item C<4> - full API configuration -=item EV_MINIMAL +This enables priorities (sets C=2 and C=-2), and +enables multiplicity (C=1). -If you need to shave off some kilobytes of code at the expense of some -speed (but with the full API), define this symbol to C<1>. Currently this -is used to override some inlining decisions, saves roughly 30% code size -on amd64. It also selects a much smaller 2-heap for timer management over -the default 4-heap. - -You can save even more by disabling watcher types you do not need -and setting C == C. Also, disabling C -(C<-DNDEBUG>) will usually reduce code size a lot. - -Defining C to C<2> will additionally reduce the core API to -provide a bare-bones event library. See C for details on what parts -of the API are still available, and do not complain if this subset changes -over time. +=item C<8> - full API + +This enables a lot of the "lesser used" API functions. See C for +details on which parts of the API are still available without this +feature, and do not complain if this subset changes over time. + +=item C<16> - enable all optional watcher types + +Enables all optional watcher types. If you want to selectively enable +only some watcher types other than I/O and timers (e.g. prepare, +embed, async, child...) you can enable them manually by defining +C to C<1> instead. + +=item C<32> - enable all backends + +This enables all backends - without this feature, you need to enable at +least one backend manually (C is a good choice). + +=item C<64> - enable OS-specific "helper" APIs + +Enable inotify, eventfd, signalfd and similar OS-specific helper APIs by +default. + +=back + +Compiling with C +reduces the compiled size of libev from 24.7Kb code/2.8Kb data to 6.5Kb +code/0.3Kb data on my GNU/Linux amd64 system, while still giving you I/O +watchers, timers and monotonic clock support. + +With an intelligent-enough linker (gcc+binutils are intelligent enough +when you use C<-Wl,--gc-sections -ffunction-sections>) functions unused by +your program might be left out as well - a binary starting a timer and an +I/O watcher then might come out at only 5Kb. + +=item EV_AVOID_STDIO + +If this is set to C<1> at compiletime, then libev will avoid using stdio +functions (printf, scanf, perror etc.). This will increase the code size +somewhat, but if your program doesn't otherwise depend on stdio and your +libc allows it, this avoids linking in the stdio library which is quite +big. + +Note that error messages might become less precise when this option is +enabled. =item EV_NSIG @@ -3867,23 +4506,23 @@ signals): Normally, libev tries to deduce the maximum number of signals automatically, but sometimes this fails, in which case it can be specified. Also, using a lower number than detected (C<32> should be -good for about any system in existance) can save some memory, as libev +good for about any system in existence) can save some memory, as libev statically allocates some 12-24 bytes per signal number. =item EV_PID_HASHSIZE C watchers use a small hash table to distribute workload by -pid. The default size is C<16> (or C<1> with C), usually more -than enough. If you need to manage thousands of children you might want to -increase this value (I be a power of two). +pid. The default size is C<16> (or C<1> with C disabled), +usually more than enough. If you need to manage thousands of children you +might want to increase this value (I be a power of two). =item EV_INOTIFY_HASHSIZE C watchers use a small hash table to distribute workload by -inotify watch id. The default size is C<16> (or C<1> with C), -usually more than enough. If you need to manage thousands of C -watchers you might want to increase this value (I be a power of -two). +inotify watch id. The default size is C<16> (or C<1> with C +disabled), usually more than enough. If you need to manage thousands of +C watchers you might want to increase this value (I be a +power of two). =item EV_USE_4HEAP @@ -3892,8 +4531,8 @@ to C<1>. The 4-heap uses more complicated (longer) code but has noticeably faster performance with many (thousands) of watchers. -The default is C<1> unless C is set in which case it is C<0> -(disabled). +The default is C<1>, unless C overrides it, in which case it +will be C<0>. =item EV_HEAP_CACHE_AT @@ -3904,12 +4543,12 @@ but avoids random read accesses on heap changes. This improves performance noticeably with many (hundreds) of watchers. -The default is C<1> unless C is set in which case it is C<0> -(disabled). +The default is C<1>, unless C overrides it, in which case it +will be C<0>. =item EV_VERIFY -Controls how much internal verification (see C) will +Controls how much internal verification (see C) will be done: If set to C<0>, no internal verification code will be compiled in. If set to C<1>, then verification code will be compiled in, but not called. If set to C<2>, then the internal verification code will be @@ -3917,13 +4556,13 @@ verification code will be called very frequently, which will slow down libev considerably. -The default is C<1>, unless C is set, in which case it will be -C<0>. +The default is C<1>, unless C overrides it, in which case it +will be C<0>. =item EV_COMMON By default, all watchers have a C member. By redefining -this macro to a something else you can include more and other types of +this macro to something else you can include more and other types of members. You have to define it each time you include one of the files, though, and it must be identical each time. @@ -3986,15 +4625,14 @@ The usage in rxvt-unicode is simpler. It has a F header file that everybody includes and which overrides some configure choices: - #define EV_MINIMAL 1 - #define EV_USE_POLL 0 - #define EV_MULTIPLICITY 0 - #define EV_PERIODIC_ENABLE 0 - #define EV_STAT_ENABLE 0 - #define EV_FORK_ENABLE 0 + #define EV_FEATURES 8 + #define EV_USE_SELECT 1 + #define EV_PREPARE_ENABLE 1 + #define EV_IDLE_ENABLE 1 + #define EV_SIGNAL_ENABLE 1 + #define EV_CHILD_ENABLE 1 + #define EV_USE_STDEXCEPT 0 #define EV_CONFIG_H - #define EV_MINPRI 0 - #define EV_MAXPRI 0 #include "ev++.h" @@ -4003,7 +4641,7 @@ #include "ev_cpp.h" #include "ev.c" -=head1 INTERACTION WITH OTHER PROGRAMS OR LIBRARIES +=head1 INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT =head2 THREADS AND COROUTINES @@ -4064,155 +4702,19 @@ =back -=head4 THREAD LOCKING EXAMPLE - -Here is a fictitious example of how to run an event loop in a different -thread than where callbacks are being invoked and watchers are -created/added/removed. - -For a real-world example, see the C perl module, -which uses exactly this technique (which is suited for many high-level -languages). - -The example uses a pthread mutex to protect the loop data, a condition -variable to wait for callback invocations, an async watcher to notify the -event loop thread and an unspecified mechanism to wake up the main thread. - -First, you need to associate some data with the event loop: - - typedef struct { - mutex_t lock; /* global loop lock */ - ev_async async_w; - thread_t tid; - cond_t invoke_cv; - } userdata; - - void prepare_loop (EV_P) - { - // for simplicity, we use a static userdata struct. - static userdata u; - - ev_async_init (&u->async_w, async_cb); - ev_async_start (EV_A_ &u->async_w); - - pthread_mutex_init (&u->lock, 0); - pthread_cond_init (&u->invoke_cv, 0); - - // now associate this with the loop - ev_set_userdata (EV_A_ u); - ev_set_invoke_pending_cb (EV_A_ l_invoke); - ev_set_loop_release_cb (EV_A_ l_release, l_acquire); - - // then create the thread running ev_loop - pthread_create (&u->tid, 0, l_run, EV_A); - } - -The callback for the C watcher does nothing: the watcher is used -solely to wake up the event loop so it takes notice of any new watchers -that might have been added: - - static void - async_cb (EV_P_ ev_async *w, int revents) - { - // just used for the side effects - } - -The C and C callbacks simply unlock/lock the mutex -protecting the loop data, respectively. - - static void - l_release (EV_P) - { - userdata *u = ev_userdata (EV_A); - pthread_mutex_unlock (&u->lock); - } - - static void - l_acquire (EV_P) - { - userdata *u = ev_userdata (EV_A); - pthread_mutex_lock (&u->lock); - } - -The event loop thread first acquires the mutex, and then jumps straight -into C: - - void * - l_run (void *thr_arg) - { - struct ev_loop *loop = (struct ev_loop *)thr_arg; - - l_acquire (EV_A); - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); - ev_loop (EV_A_ 0); - l_release (EV_A); - - return 0; - } - -Instead of invoking all pending watchers, the C callback will -signal the main thread via some unspecified mechanism (signals? pipe -writes? C?) and then waits until all pending watchers -have been called (in a while loop because a) spurious wakeups are possible -and b) skipping inter-thread-communication when there are no pending -watchers is very beneficial): - - static void - l_invoke (EV_P) - { - userdata *u = ev_userdata (EV_A); - - while (ev_pending_count (EV_A)) - { - wake_up_other_thread_in_some_magic_or_not_so_magic_way (); - pthread_cond_wait (&u->invoke_cv, &u->lock); - } - } - -Now, whenever the main thread gets told to invoke pending watchers, it -will grab the lock, call C and then signal the loop -thread to continue: - - static void - real_invoke_pending (EV_P) - { - userdata *u = ev_userdata (EV_A); - - pthread_mutex_lock (&u->lock); - ev_invoke_pending (EV_A); - pthread_cond_signal (&u->invoke_cv); - pthread_mutex_unlock (&u->lock); - } - -Whenever you want to start/stop a watcher or do other modifications to an -event loop, you will now have to lock: - - ev_timer timeout_watcher; - userdata *u = ev_userdata (EV_A); - - ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); - - pthread_mutex_lock (&u->lock); - ev_timer_start (EV_A_ &timeout_watcher); - ev_async_send (EV_A_ &u->async_w); - pthread_mutex_unlock (&u->lock); - -Note that sending the C watcher is required because otherwise -an event loop currently blocking in the kernel will have no knowledge -about the newly added timer. By waking up the loop it will pick up any new -watchers in the next event loop iteration. +See also L. =head3 COROUTINES Libev is very accommodating to coroutines ("cooperative threads"): libev fully supports nesting calls to its functions from different -coroutines (e.g. you can call C on the same loop from two +coroutines (e.g. you can call C on the same loop from two different coroutines, and switch freely between both coroutines running the loop, as long as you don't confuse yourself). The only exception is that you must not do this from C reschedule callbacks. Care has been taken to ensure that libev does not keep local state inside -C, and other calls do not usually allow for coroutine switches as +C, and other calls do not usually allow for coroutine switches as they do not call any callbacks. =head2 COMPILER WARNINGS @@ -4233,7 +4735,7 @@ And of course, some compiler warnings are just plain stupid, or simply wrong (because they don't actually warn about the condition their message seems to warn about). For example, certain older gcc versions had some -warnings that resulted an extreme number of false positives. These have +warnings that resulted in an extreme number of false positives. These have been fixed, but some people still insist on making code warn-free with such buggy versions. @@ -4279,19 +4781,109 @@ =head1 PORTABILITY NOTES +=head2 GNU/LINUX 32 BIT LIMITATIONS + +GNU/Linux is the only common platform that supports 64 bit file/large file +interfaces but I them by default. + +That means that libev compiled in the default environment doesn't support +files larger than 2GiB or so, which mainly affects C watchers. + +Unfortunately, many programs try to work around this GNU/Linux issue +by enabling the large file API, which makes them incompatible with the +standard libev compiled for their system. + +Likewise, libev cannot enable the large file API itself as this would +suddenly make it incompatible to the default compile time environment, +i.e. all programs not using special compile switches. + +=head2 OS/X AND DARWIN BUGS + +The whole thing is a bug if you ask me - basically any system interface +you touch is broken, whether it is locales, poll, kqueue or even the +OpenGL drivers. + +=head3 C is buggy + +The kqueue syscall is broken in all known versions - most versions support +only sockets, many support pipes. + +Libev tries to work around this by not using C by default on this +rotten platform, but of course you can still ask for it when creating a +loop - embedding a socket-only kqueue loop into a select-based one is +probably going to work well. + +=head3 C is buggy + +Instead of fixing C, Apple replaced their (working) C +implementation by something calling C internally around the 10.5.6 +release, so now C I C are broken. + +Libev tries to work around this by not using C by default on +this rotten platform, but of course you can still ask for it when creating +a loop. + +=head3 C, and of course Apple found a way to fuck this +one up as well: On OS/X, C backends. + +=head2 AIX POLL BUG + +AIX unfortunately has a broken C header. Libev works around +this by trying to avoid the poll backend altogether (i.e. it's not even +compiled in), which normally isn't a big problem as C function The winsocket C