--- libev/ev.pod 2010/10/18 07:36:05 1.306 +++ libev/ev.pod 2011/01/30 22:38:59 1.363 @@ -28,8 +28,8 @@ // with its corresponding stop function. ev_io_stop (EV_A_ w); - // this causes all nested ev_loop's to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ALL); + // this causes all nested ev_run's to stop iterating + ev_break (EV_A_ EVBREAK_ALL); } // another callback, this time for a time-out @@ -37,15 +37,15 @@ timeout_cb (EV_P_ ev_timer *w, int revents) { puts ("timeout"); - // this causes the innermost ev_loop to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ONE); + // this causes the innermost ev_run to stop iterating + ev_break (EV_A_ EVBREAK_ONE); } int main (void) { // use the default event loop unless you have special needs - struct ev_loop *loop = ev_default_loop (0); + struct ev_loop *loop = EV_DEFAULT; // initialise an io watcher, then start it // this one will watch for stdin to become readable @@ -58,9 +58,9 @@ ev_timer_start (loop, &timeout_watcher); // now wait for events to arrive - ev_loop (loop, 0); + ev_run (loop, 0); - // unloop was called, so exit + // break was called, so exit return 0; } @@ -80,6 +80,14 @@ Familiarity with event based programming techniques in general is assumed throughout this document. +=head1 WHAT TO READ WHEN IN A HURRY + +This manual tries to be very detailed, but unfortunately, this also makes +it very long. If you just want to know the basics of libev, I suggest +reading L, then the L above and +look up the missing functions in L and the C and +C sections in L. + =head1 ABOUT LIBEV Libev is an event loop: you register interest in certain events (such as a @@ -126,7 +134,7 @@ =head2 TIME REPRESENTATION Libev represents time as a single floating point number, representing -the (fractional) number of seconds since the (POSIX) epoch (in practise +the (fractional) number of seconds since the (POSIX) epoch (in practice somewhere near the beginning of 1970, details are complicated, don't ask). This type is called C, which is what you should use too. It usually aliases to the C type in C. When you need to do @@ -167,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) @@ -194,7 +203,8 @@ not a problem. Example: Make sure we haven't accidentally been linked against the wrong -version (note, however, that this will not detect ABI mismatches :). +version (note, however, that this will not detect other ABI mismatches, +such as LFS or reentrancy). assert (("libev version mismatch", ev_version_major () == EV_VERSION_MAJOR @@ -215,24 +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 @@ -268,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 @@ -290,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) -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 will create and initialise a new event loop object. If the loop +could not be initialised, returns false. + +This function is thread-safe, and one common way to use libev with +threads is indeed to create one loop per thread, and using the default +loop in the "main" or "initial" thread. The flags argument can be used to specify special behaviour or specific backends to use, and is usually specified as C<0> (or C). @@ -368,14 +417,14 @@ =item C When this flag is specified, then libev will not attempt to use the -I API for it's C watchers. Apart from debugging and +I API for its C watchers. Apart from debugging and testing, this flag can be useful to conserve inotify file descriptors, as otherwise each loop using C watchers consumes one inotify handle. =item C When this flag is specified, then libev will attempt to use the -I API for it's C (and C) watchers. This API +I API for its C (and C) watchers. This API delivers signals synchronously, which makes it both faster and might make it possible to get the queued signal data. It can also simplify signal handling with threads, as long as you properly block signals in your @@ -385,6 +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 @@ -429,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 @@ -445,6 +511,10 @@ 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 @@ -1626,7 +1745,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 @@ -1645,7 +1764,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 @@ -1826,7 +1945,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. @@ -1953,7 +2072,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 @@ -1989,7 +2108,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 @@ -2160,7 +2279,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 @@ -2189,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 @@ -2213,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 @@ -2237,7 +2371,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; @@ -2633,7 +2767,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 @@ -2811,7 +2945,7 @@ // create/start timer // poll - ev_loop (EV_A_ 0); + ev_run (EV_A_ 0); // stop timer again if (timeout >= 0) @@ -2899,7 +3033,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] @@ -2995,23 +3129,64 @@ 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 - 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 + +=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 @@ -3027,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. @@ -3132,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 @@ -3213,12 +3393,322 @@ =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_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 Libev offers a compatibility emulation layer for libevent. It cannot @@ -3226,6 +3716,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, @@ -3240,7 +3735,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. @@ -3269,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: @@ -3393,16 +3888,22 @@ =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. @@ -3424,20 +3925,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 } }; @@ -3521,7 +4027,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. @@ -3571,7 +4077,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 @@ -3673,6 +4179,22 @@ =over 4 +=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 @@ -4031,7 +4553,7 @@ =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 @@ -4124,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 @@ -4185,155 +4707,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 @@ -4427,9 +4813,10 @@ 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. +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 @@ -4458,19 +4845,21 @@ The default compile environment on Solaris is unfortunately so thread-unsafe that you can't even use components/libraries compiled -without C<-D_REENTRANT> (as long as they use C), which, of course, -isn't defined by default. +without C<-D_REENTRANT> in a threaded program, which, of course, isn't +defined by default. A valid, if stupid, implementation choice. If you want to use libev in threaded environments you have to make sure it's compiled with C<_REENTRANT> defined. =head3 Event port backend -The scalable event interface for Solaris is called "event ports". Unfortunately, -this mechanism is very buggy. If you run into high CPU usage, your program -freezes or you get a large number of spurious wakeups, make sure you have -all the relevant and latest kernel patches applied. No, I don't know which -ones, but there are multiple ones. +The scalable event interface for Solaris is called "event +ports". Unfortunately, this mechanism is very buggy in all major +releases. If you run into high CPU usage, your program freezes or you get +a large number of spurious wakeups, make sure you have all the relevant +and latest kernel patches applied. No, I don't know which ones, but there +are multiple ones to apply, and afterwards, event ports actually work +great. If you can't get it to work, you can try running the program by setting the environment variable C to only allow C and @@ -4481,7 +4870,7 @@ 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