--- libev/ev.pod 2009/06/30 06:24:38 1.245 +++ libev/ev.pod 2009/07/19 01:36:34 1.259 @@ -623,6 +623,18 @@ "ticks" the number of loop iterations), as it roughly corresponds with C and C calls. +=item unsigned int ev_loop_depth (loop) + +Returns the number of times C was entered minus the number of +times C was exited, in other words, the recursion depth. + +Outside C, this number is zero. In a callback, this number is +C<1>, unless C was invoked recursively (or from another thread), +in which case it is higher. + +Leaving C abnormally (setjmp/longjmp, cancelling the thread +etc.), doesn't count as exit. + =item unsigned int ev_backend (loop) Returns one of the C flags indicating the event backend in @@ -846,6 +858,71 @@ ev_set_timeout_collect_interval (EV_DEFAULT_UC_ 0.1); ev_set_io_collect_interval (EV_DEFAULT_UC_ 0.01); +=item ev_invoke_pending (loop) + +This call will simply invoke all pending watchers while resetting their +pending state. Normally, C does this automatically when required, +but when overriding the invoke callback this call comes handy. + +=item int ev_pending_count (loop) + +Returns the number of pending watchers - zero indicates that no watchers +are pending. + +=item ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(EV_P)) + +This overrides the invoke pending functionality of the loop: Instead of +invoking all pending watchers when there are any, C will call +this callback instead. This is useful, for example, when you want to +invoke the actual watchers inside another context (another thread etc.). + +If you want to reset the callback, use C as new +callback. + +=item ev_set_loop_release_cb (loop, void (*release)(EV_P), void (*acquire)(EV_P)) + +Sometimes you want to share the same loop between multiple threads. This +can be done relatively simply by putting mutex_lock/unlock calls around +each call to a libev function. + +However, C can run an indefinite time, so it is not feasible to +wait for it to return. One way around this is to wake up the loop via +C and C, another way is to set these I +and I callbacks on the loop. + +When set, then C will be called just before the thread is +suspended waiting for new events, and C is called just +afterwards. + +Ideally, C will just call your mutex_unlock function, and +C will just call the mutex_lock function again. + +While event loop modifications are allowed between invocations of +C and C (that's their only purpose after all), no +modifications done will affect the event loop, i.e. adding watchers will +have no effect on the set of file descriptors being watched, or the time +waited. USe an C watcher to wake up C when you want it +to take note of any changes you made. + +In theory, threads executing C will be async-cancel safe between +invocations of C and C. + +See also the locking example in the C section later in this +document. + +=item ev_set_userdata (loop, void *data) + +=item ev_userdata (loop) + +Set and retrieve a single C associated with a loop. When +C has never been called, then C returns +C<0.> + +These two functions can be used to associate arbitrary data with a loop, +and are intended solely for the C, C and +C callbacks described above, but of course can be (ab-)used for +any other purpose as well. + =item ev_loop_verify (loop) This function only does something when C support has been @@ -1482,8 +1559,8 @@ passed (not I, so on systems with very low-resolution clocks this 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 with later time-out values (but this is no longer true when a -callback calls C recursively). +before ones of the same priority with later time-out values (but this is +no longer true when a callback calls C recursively). =head3 Be smart about timeouts @@ -1680,6 +1757,36 @@ update of the time returned by C by calling C. +=head3 The special problems of suspended animation + +When you leave the server world it is quite customary to hit machines that +can suspend/hibernate - what happens to the clocks during such a suspend? + +Some quick tests made with a Linux 2.6.28 indicate that a suspend freezes +all processes, while the clocks (C, C) continue +to run until the system is suspended, but they will not advance while the +system is suspended. That means, on resume, it will be as if the program +was frozen for a few seconds, but the suspend time will not be counted +towards C when a monotonic clock source is used. The real time +clock advanced as expected, but if it is used as sole clocksource, then a +long suspend would be detected as a time jump by libev, and timers would +be adjusted accordingly. + +I would not be surprised to see different behaviour in different between +operating systems, OS versions or even different hardware. + +The other form of suspend (job control, or sending a SIGSTOP) will see a +time jump in the monotonic clocks and the realtime clock. If the program +is suspended for a very long time, and monotonic clock sources are in use, +then you can expect Cs to expire as the full suspension time +will be counted towards the timers. When no monotonic clock source is in +use, then libev will again assume a timejump and adjust accordingly. + +It might be beneficial for this latter case to call C +and C in code that handles C, to at least get +deterministic behaviour in this case (you can do nothing against +C). + =head3 Watcher-Specific Functions and Data Members =over 4 @@ -1715,6 +1822,18 @@ This sounds a bit complicated, see L, above, for a usage example. +=item 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 +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. + =item ev_tstamp repeat [read-write] The current C value. Will be used each time the watcher times out @@ -1959,22 +2078,28 @@ will try it's best to deliver signals synchronously, i.e. as part of the normal event processing, like any other event. +Note that only the default loop supports registering signal watchers +currently. + If you want signals asynchronously, just use C as you would do without libev and forget about sharing the signal. You can even use C from a signal handler to synchronously wake up an event loop. You can configure as many watchers as you like per signal. Only when the -first watcher gets started will libev actually register a signal handler -with the kernel (thus it coexists with your own signal handlers as long as -you don't register any with libev for the same signal). Similarly, when -the last signal watcher for a signal is stopped, libev will reset the -signal handler to SIG_DFL (regardless of what it was set to before). +first watcher gets started will libev actually register something with +the kernel (thus it coexists with your own signal handlers as long as you +don't register any with libev for the same signal). + +Both the signal mask state (C) and the signal handler state +(C) are unspecified after starting a signal watcher (and after +sotpping it again), that is, libev might or might not block the signal, +and might or might not set or restore the installed signal handler. If possible and supported, libev will install its handlers with -C behaviour enabled, so system calls should not be unduly -interrupted. If you have a problem with system calls getting interrupted by -signals you can block all signals in an C watcher and unblock -them in an C watcher. +C (or equivalent) behaviour enabled, so system calls should +not be unduly interrupted. If you have a problem with system calls getting +interrupted by signals you can block all signals in an C watcher +and unblock them in an C watcher. =head3 Watcher-Specific Functions and Data Members @@ -2022,11 +2147,15 @@ Only the default event loop is capable of handling signals, and therefore you can only register child watchers in the default event loop. +Due to some design glitches inside libev, child watchers will always be +handled at maximum priority (their priority is set to C by +libev) + =head3 Process Interaction Libev grabs C as soon as the default event loop is -initialised. This is necessary to guarantee proper behaviour even if -the first child watcher is started after the child exits. The occurrence +initialised. This is necessary to guarantee proper behaviour even if the +first child watcher is started after the child exits. The occurrence of C is recorded asynchronously, but child reaping is done synchronously as part of the event loop processing. Libev always reaps all children, even ones not watched. @@ -2046,7 +2175,8 @@ Currently, the child watcher never gets stopped, even when the child terminates, so normally one needs to stop the watcher in the callback. Future versions of libev might stop the watcher automatically -when a child exit is detected. +when a child exit is detected (calling C twice is not a +problem). =head3 Watcher-Specific Functions and Data Members @@ -3657,9 +3787,19 @@ =item EV_MINIMAL If you need to shave off some kilobytes of code at the expense of some -speed, 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. +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 EV_PID_HASHSIZE @@ -3855,14 +3995,152 @@ =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. + =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 -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. +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 @@ -4079,7 +4357,9 @@ The type C is used to represent timestamps. It is required to have at least 51 bits of mantissa (and 9 bits of exponent), which is good enough for at least into the year 4000. This requirement is fulfilled by -implementations implementing IEEE 754 (basically all existing ones). +implementations implementing IEEE 754, which is basically all existing +ones. With IEEE 754 doubles, you get microsecond accuracy until at least +2200. =back