--- libev/ev.pod 2008/06/01 01:13:59 1.165 +++ libev/ev.pod 2009/06/30 06:24:38 1.245 @@ -11,15 +11,17 @@ // a single header file is required #include + #include // for puts + // every watcher type has its own typedef'd struct - // with the name ev_ + // with the name ev_TYPE ev_io stdin_watcher; ev_timer timeout_watcher; // all watcher callbacks have a similar signature // this callback is called when data is readable on stdin static void - stdin_cb (EV_P_ struct ev_io *w, int revents) + stdin_cb (EV_P_ ev_io *w, int revents) { puts ("stdin ready"); // for one-shot events, one must manually stop the watcher @@ -32,7 +34,7 @@ // another callback, this time for a time-out static void - timeout_cb (EV_P_ struct ev_timer *w, int revents) + timeout_cb (EV_P_ ev_timer *w, int revents) { puts ("timeout"); // this causes the innermost ev_loop to stop iterating @@ -62,12 +64,24 @@ return 0; } -=head1 DESCRIPTION +=head1 ABOUT THIS DOCUMENT + +This document documents the libev software package. The newest version of this document is also available as an html-formatted web page you might find easier to navigate when reading it for the first time: L. +While this document tries to be as complete as possible in documenting +libev, its usage and the rationale behind its design, it is not a tutorial +on event-based programming, nor will it introduce event-based programming +with libev. + +Familarity with event based programming techniques in general is assumed +throughout this document. + +=head1 ABOUT LIBEV + Libev is an event loop: you register interest in certain events (such as a file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events. @@ -105,17 +119,17 @@ 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, and when you need to do any calculations on -it, you should treat it as some floating point value. Unlike the name +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. @@ -216,7 +230,7 @@ See the description of C watchers for more info. -=item ev_set_allocator (void *(*cb)(void *ptr, long size)) +=item ev_set_allocator (void *(*cb)(void *ptr, long size)) [NOT REENTRANT] Sets the allocation function to use (the prototype is similar - the semantics are identical to the C C89/SuS/POSIX function). It is @@ -252,7 +266,7 @@ ... ev_set_allocator (persistent_realloc); -=item ev_set_syserr_cb (void (*cb)(const char *msg)); +=item ev_set_syserr_cb (void (*cb)(const char *msg)); [NOT REENTRANT] 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 @@ -278,9 +292,13 @@ =head1 FUNCTIONS CONTROLLING THE EVENT LOOP -An event loop is described by a C. The library knows two -types of such loops, the I loop, which supports signals and child -events, and dynamically created loops which do not. +An event loop is described by a C (the C +is I optional in this case, as there is also an C +I). + +The library knows two types of such loops, the I loop, which +supports signals and child events, and dynamically created loops which do +not. =over 4 @@ -296,7 +314,7 @@ 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 bes hared easily between threads anyway). +as loops cannot be shared easily between threads anyway). The default loop is the only loop that can handle C and C watchers, and to do this, it always registers a handler @@ -361,6 +379,10 @@ a look at C to increase the amount of readiness notifications you get per iteration. +This backend maps C to the C set and C to the +C set (and to work around Microsoft Windows bugs, also onto the +C set on that platform). + =item C (value 2, poll backend, available everywhere except on windows) And this is your standard poll(2) backend. It's more complicated @@ -370,40 +392,67 @@ i.e. O(total_fds). See the entry for C, above, for performance tips. +This backend maps C to C, and +C to C. + =item C (value 4, Linux) 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), -epoll scales either O(1) or O(active_fds). The epoll design has a number -of shortcomings, such as silently dropping events in some hard-to-detect -cases and requiring a system call per fd change, no fork support and bad -support for dup. +epoll scales either O(1) or O(active_fds). + +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. + +Epoll is also notoriously buggy - embedding epoll fds I work, but +of course I, and epoll just loves to report events for totally +I file descriptors (even already closed ones, so one cannot +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. While stopping, setting and starting an I/O watcher in the same iteration -will result in some caching, there is still a system call per such incident -(because the fd could point to a different file description now), so its -best to avoid that. Also, C'ed file descriptors might not work -very well if you register events for both fds. - -Please note that epoll sometimes generates spurious notifications, so you -need to use non-blocking I/O or other means to avoid blocking when no data -(or space) is available. +will result in some caching, there is still a system call per such +incident (because the same I could point to a different +I now), so its best to avoid that. Also, C'ed +file descriptors might not work very well if you register events for both +file descriptors. Best performance from this backend is achieved by not unregistering all -watchers for a file descriptor until it has been closed, if possible, i.e. -keep at least one watcher active per fd at all times. +watchers for a file descriptor until it has been closed, if possible, +i.e. keep at least one watcher active per fd at all times. Stopping and +starting a watcher (without re-setting it) also usually doesn't cause +extra overhead. A fork can both result in spurious notifications as well +as in libev having to destroy and recreate the epoll object, which can +take considerable time and thus should be avoided. + +All this means that, in practice, C can be as fast or +faster than epoll for maybe up to a hundred file descriptors, depending on +the usage. So sad. While nominally embeddable in other event loops, this feature is broken in all kernel versions tested so far. +This backend maps C and C in the same way as +C. + =item C (value 8, most BSD clones) Kqueue deserves special mention, as at the time of this writing, it was broken on all BSDs except NetBSD (usually it doesn't work reliably with anything but sockets and pipes, except on Darwin, where of course -it's completely useless). For this reason it's not being "auto-detected" -unless you explicitly specify it explicitly in the flags (i.e. using +it's completely useless). Unlike epoll, however, whose brokenness +is by design, these kqueue bugs can (and eventually will) be fixed +without API changes to existing programs. For this reason it's not being +"auto-detected" unless you explicitly specify it in the flags (i.e. using C) or libev was compiled on a known-to-be-good (-enough) system like NetBSD. @@ -415,8 +464,9 @@ kernel is more efficient (which says nothing about its actual speed, of course). While stopping, setting and starting an I/O watcher does never cause an extra system call as with C, it still adds up to -two event changes per incident, support for C is very bad and it -drops fds silently in similarly hard-to-detect cases. +two event changes per incident. Support for C is very bad (but +sane, unlike epoll) and it drops fds silently in similarly hard-to-detect +cases This backend usually performs well under most conditions. @@ -424,8 +474,12 @@ everywhere, so you might need to test for this. And since it is broken almost everywhere, you should only use it when you have a lot of sockets (for which it usually works), by embedding it into another event loop -(e.g. C or C) and using it only for -sockets. +(e.g. C or C (but C is of course +also broken on OS X)) and, did I mention it, using it only for sockets. + +This backend maps C into an C kevent with +C, and C into an C kevent with +C. =item C (value 16, Solaris 8) @@ -448,9 +502,13 @@ descriptors a "slow" C or C backend might perform better. -On the positive side, ignoring the spurious readiness notifications, this -backend actually performed to specification in all tests and is fully -embeddable, which is a rare feat among the OS-specific backends. +On the positive side, with the exception of the spurious readiness +notifications, this backend actually performed fully to specification +in all tests and is fully embeddable, which is a rare feat among the +OS-specific backends (I vastly prefer correctness over speed hacks). + +This backend maps C and C in the same way as +C. =item C @@ -466,19 +524,20 @@ backends will be tried (in the reverse order as listed here). If none are specified, all backends in C will be tried. -The most typical usage is like this: +Example: This is the most typical usage. if (!ev_default_loop (0)) fatal ("could not initialise libev, bad $LIBEV_FLAGS in environment?"); -Restrict libev to the select and poll backends, and do not allow +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); -Use whatever libev has to offer, but make sure that kqueue is used if -available (warning, breaks stuff, best use only with your own private -event loop and only if you know the OS supports your types of fds): +Example: Use whatever libev has to offer, but make sure that kqueue is +used if available (warning, breaks stuff, best use only with your own +private event loop and only if you know the OS supports your types of +fds): ev_default_loop (ev_recommended_backends () | EVBACKEND_KQUEUE); @@ -509,9 +568,9 @@ the easiest thing, you can just ignore the watchers and/or C them for example). -Note that certain global state, such as signal state, will not be freed by -this function, and related watchers (such as signal and child watchers) -would need to be stopped manually. +Note that certain global state, such as signal state (and installed signal +handlers), will not be freed by this function, and related watchers (such +as signal and child watchers) would need to be stopped manually. In general it is not advisable to call this function except in the rare occasion where you really need to free e.g. the signal handling @@ -546,11 +605,13 @@ Like C, but acts on an event loop created by C. Yes, you have to call this on every allocated event loop -after fork, and how you do this is entirely your own problem. +after fork that you want to re-use in the child, and how you do this is +entirely your own problem. =item int ev_is_default_loop (loop) -Returns true when the given loop actually is the default loop, false otherwise. +Returns true when the given loop is, in fact, the default loop, and false +otherwise. =item unsigned int ev_loop_count (loop) @@ -575,6 +636,44 @@ time used for relative timers. You can treat it as the timestamp of the event occurring (or more correctly, libev finding out about it). +=item ev_now_update (loop) + +Establishes the current time by querying the kernel, updating the time +returned by C in the progress. This is a costly operation and +is usually done automatically within C. + +This function is rarely useful, but when some event callback runs for a +very long time without entering the event loop, updating libev's idea of +the current time is a good idea. + +See also L in the C section. + +=item ev_suspend (loop) + +=item ev_resume (loop) + +These two functions suspend and resume a loop, for use when the loop is +not used for a while and timeouts should not be processed. + +A typical use case would be an interactive program such as a game: When +the user presses C<^Z> to suspend the game and resumes it an hour later it +would be best to handle timeouts as if no time had actually passed while +the program was suspended. This can be achieved by calling C +in your C handler, sending yourself a C and calling +C directly afterwards to resume timer processing. + +Effectively, all C watchers will be delayed by the time spend +between C and C, and all C watchers +will be rescheduled (that is, they will lose any events that would have +occured while suspended). + +After calling C you B call I function on the +given loop other than C, and you B call C +without a previous call to C. + +Calling C/C has the side effect of updating the +event loop time (see C). + =item ev_loop (loop, int flags) Finally, this is it, the event handler. This function usually is called @@ -586,41 +685,48 @@ Please note that an explicit C is usually better than relying on all watchers to be stopped when deciding when a program has -finished (especially in interactive programs), but having a program that -automatically loops as long as it has to and no longer by virtue of -relying on its watchers stopping correctly is a thing of beauty. +finished (especially in interactive programs), but having a program +that automatically loops as long as it has to and no longer by virtue +of relying on its watchers stopping correctly, that is truly a thing of +beauty. A flags value of C will look for new events, will handle -those events and any outstanding ones, but will not block your process in -case there are no events and will return after one iteration of the loop. +those events and any already outstanding ones, but will not block your +process in case there are no events and will return after one iteration of +the loop. A flags value of C will look for new events (waiting if -necessary) and will handle those and any outstanding ones. It will block -your process until at least one new event arrives, and will return after -one iteration of the loop. This is useful if you are waiting for some -external event in conjunction with something not expressible using other -libev watchers. However, a pair of C/C watchers is +necessary) and will handle those and any already outstanding ones. It +will block your process until at least one new event arrives (which could +be an event internal to libev itself, so there is no guarantee that a +user-registered callback will be called), and will return after one +iteration of the loop. + +This is useful if you are waiting for some external event in conjunction +with something not expressible using other libev watchers (i.e. "roll your +own C"). However, a pair of C/C watchers is usually a better approach for this kind of thing. Here are the gory details of what C does: - Before the first iteration, call any pending watchers. * If EVFLAG_FORKCHECK was used, check for a fork. - - If a fork was detected, queue and call all fork watchers. + - If a fork was detected (by any means), queue and call all fork watchers. - Queue and call all prepare watchers. - - If we have been forked, recreate the kernel state. + - If we have been forked, detach and recreate the kernel state + as to not disturb the other process. - Update the kernel state with all outstanding changes. - - Update the "event loop time". + - Update the "event loop time" (ev_now ()). - Calculate for how long to sleep or block, if at all (active idle watchers, EVLOOP_NONBLOCK or not having any active watchers at all will result in not sleeping). - Sleep if the I/O and timer collect interval say so. - Block the process, waiting for any events. - Queue all outstanding I/O (fd) events. - - Update the "event loop time" and do time jump handling. - - Queue all outstanding timers. - - Queue all outstanding periodics. - - If no events are pending now, queue all idle watchers. + - Update the "event loop time" (ev_now ()), and do time jump adjustments. + - Queue all expired timers. + - Queue all expired periodics. + - Unless any events are pending now, queue all idle watchers. - Queue all check watchers. - Call all queued watchers in reverse order (i.e. check watchers first). Signals and child watchers are implemented as I/O watchers, and will @@ -635,7 +741,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_loop (my_loop, 0); - ... jobs done. yeah! + ... jobs done or somebody called unloop. yeah! =item ev_unloop (loop, how) @@ -646,27 +752,34 @@ This "unloop state" will be cleared when entering C again. +It is safe to call C from otuside any C calls. + =item ev_ref (loop) =item ev_unref (loop) Ref/unref can be used to add or remove a reference count on the event loop: Every watcher keeps one reference, and as long as the reference -count is nonzero, C will not return on its own. If you have -a watcher you never unregister that should not keep C from -returning, ev_unref() after starting, and ev_ref() before stopping it. For -example, libev itself uses this for its internal signal pipe: It is not -visible to the libev user and should not keep C from exiting if -no event watchers registered by it are active. It is also an excellent -way to do this for generic recurring timers or from within third-party -libraries. Just remember to I and I -(but only if the watcher wasn't active before, or was active before, -respectively). +count is nonzero, C will not return on its own. + +If you have a watcher you never unregister that should not keep C +from returning, call ev_unref() after starting, and ev_ref() before +stopping it. + +As an example, libev itself uses this for its internal signal pipe: It +is not visible to the libev user and should not keep C from +exiting if no event watchers registered by it are active. It is also an +excellent way to do this for generic recurring timers or from within +third-party libraries. Just remember to I and I (but only if the watcher wasn't active before, or was active +before, respectively. Note also that libev might stop watchers itself +(e.g. non-repeating timers) in which case you have to C +in the callback). Example: Create a signal watcher, but keep it from keeping C running when nothing else is active. - struct ev_signal exitsig; + ev_signal exitsig; ev_signal_init (&exitsig, sig_cb, SIGINT); ev_signal_start (loop, &exitsig); evf_unref (loop); @@ -681,16 +794,18 @@ =item ev_set_timeout_collect_interval (loop, ev_tstamp interval) These advanced functions influence the time that libev will spend waiting -for events. Both are by default C<0>, meaning that libev will try to -invoke timer/periodic callbacks and I/O callbacks with minimum latency. +for events. Both time intervals are by default C<0>, meaning that libev +will try to invoke timer/periodic callbacks and I/O callbacks with minimum +latency. Setting these to a higher value (the C I be >= C<0>) -allows libev to delay invocation of I/O and timer/periodic callbacks to -increase efficiency of loop iterations. - -The background is that sometimes your program runs just fast enough to -handle one (or very few) event(s) per loop iteration. While this makes -the program responsive, it also wastes a lot of CPU time to poll for new +allows libev to delay invocation of I/O and timer/periodic callbacks +to increase efficiency of loop iterations (or to increase power-saving +opportunities). + +The idea is that sometimes your program runs just fast enough to handle +one (or very few) event(s) per loop iteration. While this makes the +program responsive, it also wastes a lot of CPU time to poll for new events, especially with backends like C function doesn't follow POSIX in that it requires socket I and not socket I (it is also extremely buggy). This makes select very inefficient, and also -requires a mapping from file descriptors to socket handles. See the +requires a mapping from file descriptors to socket handles (the Microsoft +C runtime provides the function C<_open_osfhandle> for this). See the discussion of the C, C and C preprocessor symbols for more info. @@ -3347,32 +4011,29 @@ of C<64> handles (probably owning to the fact that all windows kernels can only wait for C<64> things at the same time internally; Microsoft recommends spawning a chain of threads and wait for 63 handles and the -previous thread in each. Great). +previous thread in each. Sounds great!). Newer versions support more handles, but you need to define C to some high number (e.g. C<2048>) before compiling the winsocket select -call (which might be in libev or elsewhere, for example, perl does its own -select emulation on windows). +call (which might be in libev or elsewhere, for example, perl and many +other interpreters do their own select emulation on windows). Another limit is the number of file descriptors in the Microsoft runtime -libraries, which by default is C<64> (there must be a hidden I<64> fetish -or something like this inside Microsoft). You can increase this by calling -C<_setmaxstdio>, which can increase this limit to C<2048> (another -arbitrary limit), but is broken in many versions of the Microsoft runtime -libraries. - -This might get you to about C<512> or C<2048> sockets (depending on -windows version and/or the phase of the moon). To get more, you need to -wrap all I/O functions and provide your own fd management, but the cost of -calling select (O(n²)) will likely make this unworkable. +libraries, which by default is C<64> (there must be a hidden I<64> +fetish or something like this inside Microsoft). You can increase this +by calling C<_setmaxstdio>, which can increase this limit to C<2048> +(another arbitrary limit), but is broken in many versions of the Microsoft +runtime libraries. This might get you to about C<512> or C<2048> sockets +(depending on windows version and/or the phase of the moon). To get more, +you need to wrap all I/O functions and provide your own fd management, but +the cost of calling select (O(n²)) will likely make this unworkable. =back +=head2 PORTABILITY REQUIREMENTS -=head1 PORTABILITY REQUIREMENTS - -In addition to a working ISO-C implementation, libev relies on a few -additional extensions: +In addition to a working ISO-C implementation and of course the +backend-specific APIs, libev relies on a few additional extensions: =over 4 @@ -3388,7 +4049,7 @@ =item C must be thread-atomic as well The type C (or whatever is defined as -C) must be atomic w.r.t. accesses from different +C) must be atomic with respect to accesses from different threads. This is not part of the specification for C, but is believed to be sufficiently portable. @@ -3407,11 +4068,11 @@ =item C must be large enough for common memory allocation sizes -To improve portability and simplify using libev, libev uses C -internally instead of C when allocating its data structures. On -non-POSIX systems (Microsoft...) this might be unexpectedly low, but -is still at least 31 bits everywhere, which is enough for hundreds of -millions of watchers. +To improve portability and simplify its API, libev uses C internally +instead of C when allocating its data structures. On non-POSIX +systems (Microsoft...) this might be unexpectedly low, but is still at +least 31 bits everywhere, which is enough for hundreds of millions of +watchers. =item C must hold a time value in seconds with enough accuracy @@ -3425,59 +4086,154 @@ If you know of other additional requirements drop me a note. -=head1 COMPILER WARNINGS +=head1 ALGORITHMIC COMPLEXITIES -Depending on your compiler and compiler settings, you might get no or a -lot of warnings when compiling libev code. Some people are apparently -scared by this. +In this section the complexities of (many of) the algorithms used inside +libev will be documented. For complexity discussions about backends see +the documentation for C. -However, these are unavoidable for many reasons. For one, each compiler -has different warnings, and each user has different tastes regarding -warning options. "Warn-free" code therefore cannot be a goal except when -targeting a specific compiler and compiler-version. +All of the following are about amortised time: If an array needs to be +extended, libev needs to realloc and move the whole array, but this +happens asymptotically rarer with higher number of elements, so O(1) might +mean that libev does a lengthy realloc operation in rare cases, but on +average it is much faster and asymptotically approaches constant time. -Another reason is that some compiler warnings require elaborate -workarounds, or other changes to the code that make it less clear and less -maintainable. +=over 4 -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). +=item Starting and stopping timer/periodic watchers: O(log skipped_other_timers) -While libev is written to generate as few warnings as possible, -"warn-free" code is not a goal, and it is recommended not to build libev -with any compiler warnings enabled unless you are prepared to cope with -them (e.g. by ignoring them). Remember that warnings are just that: -warnings, not errors, or proof of bugs. +This means that, when you have a watcher that triggers in one hour and +there are 100 watchers that would trigger before that, then inserting will +have to skip roughly seven (C) of these watchers. +=item Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers) -=head1 VALGRIND +That means that changing a timer costs less than removing/adding them, +as only the relative motion in the event queue has to be paid for. -Valgrind has a special section here because it is a popular tool that is -highly useful, but valgrind reports are very hard to interpret. +=item Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1) -If you think you found a bug (memory leak, uninitialised data access etc.) -in libev, then check twice: If valgrind reports something like: +These just add the watcher into an array or at the head of a list. - ==2274== definitely lost: 0 bytes in 0 blocks. - ==2274== possibly lost: 0 bytes in 0 blocks. - ==2274== still reachable: 256 bytes in 1 blocks. +=item Stopping check/prepare/idle/fork/async watchers: O(1) -Then there is no memory leak. Similarly, under some circumstances, -valgrind might report kernel bugs as if it were a bug in libev, or it -might be confused (it is a very good tool, but only a tool). +=item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE)) -If you are unsure about something, feel free to contact the mailing list -with the full valgrind report and an explanation on why you think this is -a bug in libev. However, don't be annoyed when you get a brisk "this is -no bug" answer and take the chance of learning how to interpret valgrind -properly. +These watchers are stored in lists, so they need to be walked to find the +correct watcher to remove. The lists are usually short (you don't usually +have many watchers waiting for the same fd or signal: one is typical, two +is rare). -If you need, for some reason, empty reports from valgrind for your project -I suggest using suppression lists. +=item Finding the next timer in each loop iteration: O(1) + +By virtue of using a binary or 4-heap, the next timer is always found at a +fixed position in the storage array. + +=item Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd) + +A change means an I/O watcher gets started or stopped, which requires +libev to recalculate its status (and possibly tell the kernel, depending +on backend and whether C was used). + +=item Activating one watcher (putting it into the pending state): O(1) + +=item Priority handling: O(number_of_priorities) + +Priorities are implemented by allocating some space for each +priority. When doing priority-based operations, libev usually has to +linearly search all the priorities, but starting/stopping and activating +watchers becomes O(1) with respect to priority handling. + +=item Sending an ev_async: O(1) + +=item Processing ev_async_send: O(number_of_async_watchers) + +=item Processing signals: O(max_signal_number) + +Sending involves a system call I there were no other C +calls in the current loop iteration. Checking for async and signal events +involves iterating over all running async watchers or all signal numbers. + +=back + + +=head1 GLOSSARY + +=over 4 + +=item active + +A watcher is active as long as it has been started (has been attached to +an event loop) but not yet stopped (disassociated from the event loop). + +=item application + +In this document, an application is whatever is using libev. + +=item callback + +The address of a function that is called when some event has been +detected. Callbacks are being passed the event loop, the watcher that +received the event, and the actual event bitset. +=item callback invocation + +The act of calling the callback associated with a watcher. + +=item event + +A change of state of some external event, such as data now being available +for reading on a file descriptor, time having passed or simply not having +any other events happening anymore. + +In libev, events are represented as single bits (such as C or +C). + +=item event library + +A software package implementing an event model and loop. + +=item event loop + +An entity that handles and processes external events and converts them +into callback invocations. + +=item event model + +The model used to describe how an event loop handles and processes +watchers and events. + +=item pending + +A watcher is pending as soon as the corresponding event has been detected, +and stops being pending as soon as the watcher will be invoked or its +pending status is explicitly cleared by the application. + +A watcher can be pending, but not active. Stopping a watcher also clears +its pending status. + +=item real time + +The physical time that is observed. It is apparently strictly monotonic :) + +=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 +clock. + +=item watcher + +A data structure that describes interest in certain events. Watchers need +to be started (attached to an event loop) before they can receive events. + +=item watcher invocation + +The act of calling the callback associated with a watcher. + +=back =head1 AUTHOR -Marc Lehmann . +Marc Lehmann , with repeated corrections by Mikael Magnusson.