--- libev/ev.pod 2011/01/11 01:40:25 1.354 +++ libev/ev.pod 2011/02/03 16:21:08 1.366 @@ -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; } @@ -444,6 +444,9 @@ 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) @@ -867,7 +870,7 @@ ... queue jobs here, make sure they register event watchers as long ... as they still have work to do (even an idle watcher will do..) ev_run (my_loop, 0); - ... jobs done or somebody called unloop. yeah! + ... jobs done or somebody called break. yeah! =item ev_break (loop, how) @@ -1359,70 +1362,8 @@ =back -=head2 ASSOCIATING CUSTOM DATA WITH A WATCHER - -Each watcher has, by default, a member C that you can change -and read 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 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 type -instead have been omitted. - -Another common scenario is to use some data structure with multiple -embedded watchers: - - 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 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)); - } +See also the L and L idioms. =head2 WATCHER STATES @@ -1439,8 +1380,10 @@ initialised. This can be done with a call to C, or calls to C followed by the watcher-specific C function. -In this state it is simply some block of memory that is suitable for use -in an event loop. It can be moved around, freed, reused etc. at will. +In this state it is simply some block of memory that is suitable for +use in an event loop. It can be moved around, freed, reused etc. at +will - as long as you either keep the memory contents intact, or call +C again. =item started/running/active @@ -1478,8 +1421,9 @@ freeing it is often a good idea. While stopped (and not pending) the watcher is essentially in the -initialised state, that is it can be reused, moved, modified in any way -you wish. +initialised state, that is, it can be reused, moved, modified in any way +you wish (but when you trash the memory block, you need to C +it again). =back @@ -1682,8 +1626,8 @@ 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 it's own, but in the case of files, there is no such thing: the disk -will not send data on it's own, simply because it doesn't know what you +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 @@ -2364,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 @@ -3245,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). @@ -3365,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 instantly +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 @@ -3458,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: + + 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)); + } -=item Model/nested event loop invocations and exit conditions. +=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 @@ -3499,10 +3512,10 @@ // exit both exit_main_loop = exit_nested_loop = 1; -=item Thread locking example +=head2 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 +thread from where callbacks are being invoked and watchers are created/added/removed. For a real-world example, see the C perl module, @@ -3538,7 +3551,7 @@ 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 + // then create the thread running ev_run pthread_create (&u->tid, 0, l_run, EV_A); } @@ -3637,7 +3650,63 @@ about the newly added timer. By waking up the loop it will pick up any new watchers in the next event loop iteration. -=back +=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 @@ -4577,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 @@ -4638,7 +4707,7 @@ =back -See also L. +See also L. =head3 COROUTINES @@ -5157,7 +5226,7 @@ =item wall-clock time The time and date as shown on clocks. Unlike real time, it can actually -be wrong and jump forwards and backwards, e.g. when the you adjust your +be wrong and jump forwards and backwards, e.g. when you adjust your clock. =item watcher @@ -5170,5 +5239,5 @@ =head1 AUTHOR Marc Lehmann , with repeated corrections by Mikael -Magnusson and Emanuele Giaquinta. +Magnusson and Emanuele Giaquinta, and minor corrections by many others.