--- libev/ev.pod 2010/11/10 14:36:42 1.345 +++ libev/ev.pod 2011/01/30 22:38:59 1.363 @@ -60,7 +60,7 @@ // now wait for events to arrive ev_run (loop, 0); - // unloop was called, so exit + // break was called, so exit return 0; } @@ -301,6 +301,19 @@ ... ev_set_syserr_cb (fatal_error); +=item ev_feed_signal (int signum) + +This function can be used to "simulate" a signal receive. It is completely +safe to call this function at any time, from any context, including signal +handlers or random threads. + +Its main use is to customise signal handling in your process, especially +in the presence of threads. For example, you could block signals +by default in all threads (and specifying C when +creating any loops), and in one thread, use C or any other +mechanism to wait for signals, then "deliver" them to libev by calling +C. + =back =head1 FUNCTIONS CONTROLLING EVENT LOOPS @@ -421,6 +434,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 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) This is your standard select(2) backend. Not I standard, as @@ -483,7 +511,9 @@ 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 @@ -2298,7 +2308,8 @@ 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 @@ -2322,6 +2333,20 @@ you expect it to be empty, you have a race condition in your code>. 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 =over 4 @@ -3165,7 +3190,7 @@ =head2 C - how to wake up an event loop -In general, you cannot use an C from multiple threads or other +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). @@ -3177,7 +3202,10 @@ 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. @@ -3282,10 +3310,12 @@ =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 from other threads, signal or -similar contexts (see the discussion of C in the embedding -section below on what exactly this means). +an C event on the watcher into the event loop, and instanlty +returns. + +Unlike C, this call is safe to do from other threads, +signal or similar contexts (see the discussion of C in the +embedding section below on what exactly this means). Note that, as with other watchers in libev, multiple events might get compressed into a single callback invocation (another way to look at this @@ -3363,8 +3393,8 @@ =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 @@ -3375,9 +3405,75 @@ obvious. Note that examples are sprinkled over the whole manual, and this section only contains stuff that wouldn't fit anywhere else. -=over 4 +=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: -=item Model/nested event loop invocations and exit conditions. + 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 @@ -3416,7 +3512,201 @@ // exit both exit_main_loop = exit_nested_loop = 1; -=back +=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_run + 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 @@ -3429,7 +3719,7 @@ =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 uncanged in 2010. +and is still mostly unchanged in 2010. =item * Use it by including , as usual. @@ -3474,11 +3764,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: @@ -4356,7 +4646,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 @@ -4417,143 +4707,7 @@ =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_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. +See also L. =head3 COROUTINES