From b888bee1b720814f32b472e22410cebfd2a95f47 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 28 Apr 2009 00:50:19 +0000 Subject: 3.6 --- Changes | 4 +- configure.ac | 2 +- ev.3 | 448 +++++++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 360 insertions(+), 94 deletions(-) diff --git a/Changes b/Changes index ece5cb7..25b9adc 100644 --- a/Changes +++ b/Changes @@ -1,8 +1,6 @@ Revision history for libev, a high-performance and full-featured event loop. -TODO: ev_walk -TODO: fix signal handling(?) under win32 -3.54 +3.6 Tue Apr 28 02:49:30 CEST 2009 - multiple timers becoming ready within an event loop iteration will be invoked in the "correct" order now. - do not leave the event loop early just because we have no active diff --git a/configure.ac b/configure.ac index 3fd55ec..37df519 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_INIT AC_CONFIG_SRCDIR([ev_epoll.c]) -AM_INIT_AUTOMAKE(libev,3.53) +AM_INIT_AUTOMAKE(libev,3.6) AC_CONFIG_HEADERS([config.h]) AM_MAINTAINER_MODE diff --git a/ev.3 b/ev.3 index ec7414a..e87b7f7 100644 --- a/ev.3 +++ b/ev.3 @@ -132,7 +132,7 @@ .\" ======================================================================== .\" .IX Title "LIBEV 3" -.TH LIBEV 3 "2009-02-06" "libev-3.53" "libev - high performance full featured event loop" +.TH LIBEV 3 "2009-04-25" "libev-3.6" "libev - high performance full featured event loop" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -203,12 +203,23 @@ libev \- a high performance full\-featured event loop written in C \& return 0; \& } .Ve -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" +.SH "ABOUT THIS DOCUMENT" +.IX Header "ABOUT THIS DOCUMENT" +This document documents the libev software package. +.PP 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: . .PP +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. +.PP +Familarity with event based programming techniques in general is assumed +throughout this document. +.SH "ABOUT LIBEV" +.IX Header "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. @@ -248,12 +259,12 @@ name \f(CW\*(C`loop\*(C'\fR (which is always of type \f(CW\*(C`ev_loop *\*(C'\fR this argument. .Sh "\s-1TIME\s0 \s-1REPRESENTATION\s0" .IX Subsection "TIME REPRESENTATION" -Libev represents time as a single floating point number, representing the -(fractional) number of seconds since the (\s-1POSIX\s0) epoch (somewhere near -the beginning of 1970, details are complicated, don't ask). This type is -called \f(CW\*(C`ev_tstamp\*(C'\fR, which is what you should use too. It usually aliases -to the \f(CW\*(C`double\*(C'\fR 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 (\s-1POSIX\s0) epoch (somewhere +near the beginning of 1970, details are complicated, don't ask). This +type is called \f(CW\*(C`ev_tstamp\*(C'\fR, which is what you should use too. It usually +aliases to the \f(CW\*(C`double\*(C'\fR 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 \f(CW\*(C`stamp\*(C'\fR might indicate, it is also used for time differences throughout libev. .SH "ERROR HANDLING" @@ -762,6 +773,33 @@ very long time without entering the event loop, updating libev's idea of the current time is a good idea. .Sp See also \*(L"The special problem of time updates\*(R" in the \f(CW\*(C`ev_timer\*(C'\fR section. +.IP "ev_suspend (loop)" 4 +.IX Item "ev_suspend (loop)" +.PD 0 +.IP "ev_resume (loop)" 4 +.IX Item "ev_resume (loop)" +.PD +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. +.Sp +A typical use case would be an interactive program such as a game: When +the user presses \f(CW\*(C`^Z\*(C'\fR 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 \f(CW\*(C`ev_suspend\*(C'\fR +in your \f(CW\*(C`SIGTSTP\*(C'\fR handler, sending yourself a \f(CW\*(C`SIGSTOP\*(C'\fR and calling +\&\f(CW\*(C`ev_resume\*(C'\fR directly afterwards to resume timer processing. +.Sp +Effectively, all \f(CW\*(C`ev_timer\*(C'\fR watchers will be delayed by the time spend +between \f(CW\*(C`ev_suspend\*(C'\fR and \f(CW\*(C`ev_resume\*(C'\fR, and all \f(CW\*(C`ev_periodic\*(C'\fR watchers +will be rescheduled (that is, they will lose any events that would have +occured while suspended). +.Sp +After calling \f(CW\*(C`ev_suspend\*(C'\fR you \fBmust not\fR call \fIany\fR function on the +given loop other than \f(CW\*(C`ev_resume\*(C'\fR, and you \fBmust not\fR call \f(CW\*(C`ev_resume\*(C'\fR +without a previous call to \f(CW\*(C`ev_suspend\*(C'\fR. +.Sp +Calling \f(CW\*(C`ev_suspend\*(C'\fR/\f(CW\*(C`ev_resume\*(C'\fR has the side effect of updating the +event loop time (see \f(CW\*(C`ev_now_update\*(C'\fR). .IP "ev_loop (loop, int flags)" 4 .IX Item "ev_loop (loop, int flags)" Finally, this is it, the event handler. This function usually is called @@ -858,13 +896,15 @@ If you have a watcher you never unregister that should not keep \f(CW\*(C`ev_loo from returning, call \fIev_unref()\fR after starting, and \fIev_ref()\fR before stopping it. .Sp -As an example, libev itself uses this for its internal signal pipe: It is -not visible to the libev user and should not keep \f(CW\*(C`ev_loop\*(C'\fR 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 \fIunref after start\fR and \fIref before stop\fR -(but only if the watcher wasn't active before, or was active before, -respectively). +As an example, libev itself uses this for its internal signal pipe: It +is not visible to the libev user and should not keep \f(CW\*(C`ev_loop\*(C'\fR 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 \fIunref after start\fR and \fIref +before stop\fR (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 \f(CW\*(C`ev_ref\*(C'\fR +in the callback). .Sp Example: Create a signal watcher, but keep it from keeping \f(CW\*(C`ev_loop\*(C'\fR running when nothing else is active. @@ -1062,6 +1102,11 @@ The event loop has been resumed in the child process after fork (see .el .IP "\f(CWEV_ASYNC\fR" 4 .IX Item "EV_ASYNC" The given async watcher has been asynchronously notified (see \f(CW\*(C`ev_async\*(C'\fR). +.ie n .IP """EV_CUSTOM""" 4 +.el .IP "\f(CWEV_CUSTOM\fR" 4 +.IX Item "EV_CUSTOM" +Not ever sent (or otherwise used) by libev itself, but can be freely used +by libev users to signal watchers (e.g. via \f(CW\*(C`ev_feed_event\*(C'\fR). .ie n .IP """EV_ERROR""" 4 .el .IP "\f(CWEV_ERROR\fR" 4 .IX Item "EV_ERROR" @@ -1186,23 +1231,21 @@ integer between \f(CW\*(C`EV_MAXPRI\*(C'\fR (default: \f(CW2\fR) and \f(CW\*(C`E before watchers with lower priority, but priority will not keep watchers from being executed (except for \f(CW\*(C`ev_idle\*(C'\fR watchers). .Sp -This means that priorities are \fIonly\fR used for ordering callback -invocation after new events have been received. This is useful, for -example, to reduce latency after idling, or more often, to bind two -watchers on the same event and make sure one is called first. -.Sp If you need to suppress invocation when higher priority events are pending you need to look at \f(CW\*(C`ev_idle\*(C'\fR watchers, which provide this functionality. .Sp You \fImust not\fR change the priority of a watcher as long as it is active or pending. .Sp -The default priority used by watchers when no priority has been set is -always \f(CW0\fR, which is supposed to not be too high and not be too low :). -.Sp Setting a priority outside the range of \f(CW\*(C`EV_MINPRI\*(C'\fR to \f(CW\*(C`EV_MAXPRI\*(C'\fR is fine, as long as you do not mind that the priority value you query might or might not have been clamped to the valid range. +.Sp +The default priority used by watchers when no priority has been set is +always \f(CW0\fR, which is supposed to not be too high and not be too low :). +.Sp +See \*(L"\s-1WATCHER\s0 \s-1PRIORITY\s0 \s-1MODELS\s0\*(R", below, for a more thorough treatment of +priorities. .IP "ev_invoke (loop, ev_TYPE *watcher, int revents)" 4 .IX Item "ev_invoke (loop, ev_TYPE *watcher, int revents)" Invoke the \f(CW\*(C`watcher\*(C'\fR with the given \f(CW\*(C`loop\*(C'\fR and \f(CW\*(C`revents\*(C'\fR. Neither @@ -1289,6 +1332,110 @@ programmers): \& (((char *)w) \- offsetof (struct my_biggy, t2)); \& } .Ve +.Sh "\s-1WATCHER\s0 \s-1PRIORITY\s0 \s-1MODELS\s0" +.IX Subsection "WATCHER PRIORITY MODELS" +Many event loops support \fIwatcher priorities\fR, which are usually small +integers that influence the ordering of event callback invocation +between watchers in some way, all else being equal. +.PP +In libev, Watcher priorities can be set using \f(CW\*(C`ev_set_priority\*(C'\fR. See its +description for the more technical details such as the actual priority +range. +.PP +There are two common ways how these these priorities are being interpreted +by event loops: +.PP +In the more common lock-out model, higher priorities \*(L"lock out\*(R" invocation +of lower priority watchers, which means as long as higher priority +watchers receive events, lower priority watchers are not being invoked. +.PP +The less common only-for-ordering model uses priorities solely to order +callback invocation within a single event loop iteration: Higher priority +watchers are invoked before lower priority ones, but they all get invoked +before polling for new events. +.PP +Libev uses the second (only-for-ordering) model for all its watchers +except for idle watchers (which use the lock-out model). +.PP +The rationale behind this is that implementing the lock-out model for +watchers is not well supported by most kernel interfaces, and most event +libraries will just poll for the same events again and again as long as +their callbacks have not been executed, which is very inefficient in the +common case of one high-priority watcher locking out a mass of lower +priority ones. +.PP +Static (ordering) priorities are most useful when you have two or more +watchers handling the same resource: a typical usage example is having an +\&\f(CW\*(C`ev_io\*(C'\fR watcher to receive data, and an associated \f(CW\*(C`ev_timer\*(C'\fR to handle +timeouts. Under load, data might be received while the program handles +other jobs, but since timers normally get invoked first, the timeout +handler will be executed before checking for data. In that case, giving +the timer a lower priority than the I/O watcher ensures that I/O will be +handled first even under adverse conditions (which is usually, but not +always, what you want). +.PP +Since idle watchers use the \*(L"lock-out\*(R" model, meaning that idle watchers +will only be executed when no same or higher priority watchers have +received events, they can be used to implement the \*(L"lock-out\*(R" model when +required. +.PP +For example, to emulate how many other event libraries handle priorities, +you can associate an \f(CW\*(C`ev_idle\*(C'\fR watcher to each such watcher, and in +the normal watcher callback, you just start the idle watcher. The real +processing is done in the idle watcher callback. This causes libev to +continously poll and process kernel event data for the watcher, but when +the lock-out case is known to be rare (which in turn is rare :), this is +workable. +.PP +Usually, however, the lock-out model implemented that way will perform +miserably under the type of load it was designed to handle. In that case, +it might be preferable to stop the real watcher before starting the +idle watcher, so the kernel will not have to process the event in case +the actual processing will be delayed for considerable time. +.PP +Here is an example of an I/O watcher that should run at a strictly lower +priority than the default, and which should only process data when no +other events are pending: +.PP +.Vb 2 +\& ev_idle idle; // actual processing watcher +\& ev_io io; // actual event watcher +\& +\& static void +\& io_cb (EV_P_ ev_io *w, int revents) +\& { +\& // stop the I/O watcher, we received the event, but +\& // are not yet ready to handle it. +\& ev_io_stop (EV_A_ w); +\& +\& // start the idle watcher to ahndle the actual event. +\& // it will not be executed as long as other watchers +\& // with the default priority are receiving events. +\& ev_idle_start (EV_A_ &idle); +\& } +\& +\& static void +\& idle\-cb (EV_P_ ev_idle *w, int revents) +\& { +\& // actual processing +\& read (STDIN_FILENO, ...); +\& +\& // have to start the I/O watcher again, as +\& // we have handled the event +\& ev_io_start (EV_P_ &io); +\& } +\& +\& // initialisation +\& ev_idle_init (&idle, idle_cb); +\& ev_io_init (&io, io_cb, STDIN_FILENO, EV_READ); +\& ev_io_start (EV_DEFAULT_ &io); +.Ve +.PP +In the \*(L"real\*(R" world, it might also be beneficial to start a timer, so that +low-priority connections can not be locked out forever under load. This +enables your program to keep a lower latency for important connections +during short periods of high load, while not completely locking out less +important ones. .SH "WATCHER TYPES" .IX Header "WATCHER TYPES" This section describes each watcher in detail, but will not repeat @@ -1321,7 +1468,9 @@ required if you know what you are doing). .PP If you cannot use non-blocking mode, then force the use of a known-to-be-good backend (at the time of this writing, this includes only -\&\f(CW\*(C`EVBACKEND_SELECT\*(C'\fR and \f(CW\*(C`EVBACKEND_POLL\*(C'\fR). +\&\f(CW\*(C`EVBACKEND_SELECT\*(C'\fR and \f(CW\*(C`EVBACKEND_POLL\*(C'\fR). The same applies to file +descriptors for which non-blocking operation makes no sense (such as +files) \- libev doesn't guarentee any specific behaviour in that case. .PP Another thing you have to watch out for is that it is quite easy to receive \*(L"spurious\*(R" readiness notifications, that is your callback might @@ -1453,8 +1602,11 @@ detecting time jumps is hard, and some inaccuracies are unavoidable (the monotonic clock option helps a lot here). .PP The callback is guaranteed to be invoked only \fIafter\fR its timeout has -passed, but if multiple timers become ready during the same loop iteration -then order of execution is undefined. +passed (not \fIat\fR, 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 \f(CW\*(C`ev_loop\*(C'\fR recursively). .PP \fIBe smart about timeouts\fR .IX Subsection "Be smart about timeouts" @@ -1745,51 +1897,62 @@ inactivity. Periodic watchers are also timers of a kind, but they are very versatile (and unfortunately a bit complex). .PP -Unlike \f(CW\*(C`ev_timer\*(C'\fR's, they are not based on real time (or relative time) -but on wall clock time (absolute time). You can tell a periodic watcher -to trigger after some specific point in time. For example, if you tell a -periodic watcher to trigger in 10 seconds (by specifying e.g. \f(CW\*(C`ev_now () -+ 10.\*(C'\fR, that is, an absolute time not a delay) and then reset your system -clock to January of the previous year, then it will take more than year -to trigger the event (unlike an \f(CW\*(C`ev_timer\*(C'\fR, which would still trigger -roughly 10 seconds later as it uses a relative timeout). -.PP -\&\f(CW\*(C`ev_periodic\*(C'\fRs can also be used to implement vastly more complex timers, -such as triggering an event on each \*(L"midnight, local time\*(R", or other -complicated rules. +Unlike \f(CW\*(C`ev_timer\*(C'\fR, periodic watchers are not based on real time (or +relative time, the physical time that passes) but on wall clock time +(absolute time, the thing you can read on your calender or clock). The +difference is that wall clock time can run faster or slower than real +time, and time jumps are not uncommon (e.g. when you adjust your +wrist-watch). +.PP +You can tell a periodic watcher to trigger after some specific point +in time: for example, if you tell a periodic watcher to trigger \*(L"in 10 +seconds\*(R" (by specifying e.g. \f(CW\*(C`ev_now () + 10.\*(C'\fR, that is, an absolute time +not a delay) and then reset your system clock to January of the previous +year, then it will take a year or more to trigger the event (unlike an +\&\f(CW\*(C`ev_timer\*(C'\fR, which would still trigger roughly 10 seconds after starting +it, as it uses a relative timeout). +.PP +\&\f(CW\*(C`ev_periodic\*(C'\fR watchers can also be used to implement vastly more complex +timers, such as triggering an event on each \*(L"midnight, local time\*(R", or +other complicated rules. This cannot be done with \f(CW\*(C`ev_timer\*(C'\fR watchers, as +those cannot react to time jumps. .PP As with timers, the callback is guaranteed to be invoked only when the -time (\f(CW\*(C`at\*(C'\fR) has passed, but if multiple periodic timers become ready -during the same loop iteration, then order of execution is undefined. +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 \f(CW\*(C`ev_loop\*(C'\fR recursively). .PP \fIWatcher-Specific Functions and Data Members\fR .IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_periodic_init (ev_periodic *, callback, ev_tstamp at, ev_tstamp interval, reschedule_cb)" 4 -.IX Item "ev_periodic_init (ev_periodic *, callback, ev_tstamp at, ev_tstamp interval, reschedule_cb)" +.IP "ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" 4 +.IX Item "ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" .PD 0 -.IP "ev_periodic_set (ev_periodic *, ev_tstamp after, ev_tstamp repeat, reschedule_cb)" 4 -.IX Item "ev_periodic_set (ev_periodic *, ev_tstamp after, ev_tstamp repeat, reschedule_cb)" +.IP "ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" 4 +.IX Item "ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" .PD -Lots of arguments, lets sort it out... There are basically three modes of +Lots of arguments, let's sort it out... There are basically three modes of operation, and we will explain them from simplest to most complex: .RS 4 .IP "\(bu" 4 -absolute timer (at = time, interval = reschedule_cb = 0) +absolute timer (offset = absolute time, interval = 0, reschedule_cb = 0) .Sp In this configuration the watcher triggers an event after the wall clock -time \f(CW\*(C`at\*(C'\fR has passed. It will not repeat and will not adjust when a time -jump occurs, that is, if it is to be run at January 1st 2011 then it will -only run when the system clock reaches or surpasses this time. +time \f(CW\*(C`offset\*(C'\fR has passed. It will not repeat and will not adjust when a +time jump occurs, that is, if it is to be run at January 1st 2011 then it +will be stopped and invoked when the system clock reaches or surpasses +this point in time. .IP "\(bu" 4 -repeating interval timer (at = offset, interval > 0, reschedule_cb = 0) +repeating interval timer (offset = offset within interval, interval > 0, reschedule_cb = 0) .Sp In this mode the watcher will always be scheduled to time out at the next -\&\f(CW\*(C`at + N * interval\*(C'\fR time (for some integer N, which can also be negative) -and then repeat, regardless of any time jumps. +\&\f(CW\*(C`offset + N * interval\*(C'\fR time (for some integer N, which can also be +negative) and then repeat, regardless of any time jumps. The \f(CW\*(C`offset\*(C'\fR +argument is merely an offset into the \f(CW\*(C`interval\*(C'\fR periods. .Sp This can be used to create timers that do not drift with respect to the -system clock, for example, here is a \f(CW\*(C`ev_periodic\*(C'\fR that triggers each -hour, on the hour: +system clock, for example, here is an \f(CW\*(C`ev_periodic\*(C'\fR that triggers each +hour, on the hour (with respect to \s-1UTC\s0): .Sp .Vb 1 \& ev_periodic_set (&periodic, 0., 3600., 0); @@ -1802,9 +1965,9 @@ by 3600. .Sp Another way to think about it (for the mathematically inclined) is that \&\f(CW\*(C`ev_periodic\*(C'\fR will try to run the callback in this mode at the next possible -time where \f(CW\*(C`time = at (mod interval)\*(C'\fR, regardless of any time jumps. +time where \f(CW\*(C`time = offset (mod interval)\*(C'\fR, regardless of any time jumps. .Sp -For numerical stability it is preferable that the \f(CW\*(C`at\*(C'\fR value is near +For numerical stability it is preferable that the \f(CW\*(C`offset\*(C'\fR value is near \&\f(CW\*(C`ev_now ()\*(C'\fR (the current time), but there is no range requirement for this value, and in fact is often specified as zero. .Sp @@ -1813,15 +1976,16 @@ speed for example), so if \f(CW\*(C`interval\*(C'\fR is very small then timing s will of course deteriorate. Libev itself tries to be exact to be about one millisecond (if the \s-1OS\s0 supports it and the machine is fast enough). .IP "\(bu" 4 -manual reschedule mode (at and interval ignored, reschedule_cb = callback) +manual reschedule mode (offset ignored, interval ignored, reschedule_cb = callback) .Sp -In this mode the values for \f(CW\*(C`interval\*(C'\fR and \f(CW\*(C`at\*(C'\fR are both being +In this mode the values for \f(CW\*(C`interval\*(C'\fR and \f(CW\*(C`offset\*(C'\fR are both being ignored. Instead, each time the periodic watcher gets scheduled, the reschedule callback will be called with the watcher as first, and the current time as second argument. .Sp -\&\s-1NOTE:\s0 \fIThis callback \s-1MUST\s0 \s-1NOT\s0 stop or destroy any periodic watcher, -ever, or make \s-1ANY\s0 event loop modifications whatsoever\fR. +\&\s-1NOTE:\s0 \fIThis callback \s-1MUST\s0 \s-1NOT\s0 stop or destroy any periodic watcher, ever, +or make \s-1ANY\s0 other event loop modifications whatsoever, unless explicitly +allowed by documentation here\fR. .Sp If you need to stop it, return \f(CW\*(C`now + 1e30\*(C'\fR (or so, fudge fudge) and stop it afterwards (e.g. by starting an \f(CW\*(C`ev_prepare\*(C'\fR watcher, which is the @@ -1862,12 +2026,15 @@ a different time than the last time it was called (e.g. in a crond like program when the crontabs have changed). .IP "ev_tstamp ev_periodic_at (ev_periodic *)" 4 .IX Item "ev_tstamp ev_periodic_at (ev_periodic *)" -When active, returns the absolute time that the watcher is supposed to -trigger next. +When active, returns the absolute time that the watcher is supposed +to trigger next. This is not the same as the \f(CW\*(C`offset\*(C'\fR argument to +\&\f(CW\*(C`ev_periodic_set\*(C'\fR, but indeed works even in interval and manual +rescheduling modes. .IP "ev_tstamp offset [read\-write]" 4 .IX Item "ev_tstamp offset [read-write]" When repeating, this contains the offset value, otherwise this is the -absolute point in time (the \f(CW\*(C`at\*(C'\fR value passed to \f(CW\*(C`ev_periodic_set\*(C'\fR). +absolute point in time (the \f(CW\*(C`offset\*(C'\fR value passed to \f(CW\*(C`ev_periodic_set\*(C'\fR, +although libev might modify this value for better numerical stability). .Sp Can be modified any time, but changes only take effect when the periodic timer fires or \f(CW\*(C`ev_periodic_again\*(C'\fR is being called. @@ -2329,8 +2496,8 @@ event loop has handled all outstanding events. .PP \fIWatcher-Specific Functions and Data Members\fR .IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_idle_init (ev_signal *, callback)" 4 -.IX Item "ev_idle_init (ev_signal *, callback)" +.IP "ev_idle_init (ev_idle *, callback)" 4 +.IX Item "ev_idle_init (ev_idle *, callback)" Initialises and configures the idle watcher \- it has no parameters of any kind. There is a \f(CW\*(C`ev_idle_set\*(C'\fR macro, but using it is utterly pointless, believe me. @@ -2700,6 +2867,40 @@ and only in the child after the fork. If whoever good citizen calling \&\f(CW\*(C`ev_default_fork\*(C'\fR cheats and calls it in the wrong process, the fork handlers will be invoked, too, of course. .PP +\fIThe special problem of life after fork \- how is it possible?\fR +.IX Subsection "The special problem of life after fork - how is it possible?" +.PP +Most uses of \f(CW\*(C`fork()\*(C'\fR consist of forking, then some simple calls to ste +up/change the process environment, followed by a call to \f(CW\*(C`exec()\*(C'\fR. This +sequence should be handled by libev without any problems. +.PP +This changes when the application actually wants to do event handling +in the child, or both parent in child, in effect \*(L"continuing\*(R" after the +fork. +.PP +The default mode of operation (for libev, with application help to detect +forks) is to duplicate all the state in the child, as would be expected +when \fIeither\fR the parent \fIor\fR the child process continues. +.PP +When both processes want to continue using libev, then this is usually the +wrong result. In that case, usually one process (typically the parent) is +supposed to continue with all watchers in place as before, while the other +process typically wants to start fresh, i.e. without any active watchers. +.PP +The cleanest and most efficient way to achieve that with libev is to +simply create a new event loop, which of course will be \*(L"empty\*(R", and +use that for new watchers. This has the advantage of not touching more +memory than necessary, and thus avoiding the copy-on-write, and the +disadvantage of having to use multiple event loops (which do not support +signal watchers). +.PP +When this is not possible, or you want to use the default loop for +other reasons, then in the process that wants to start \*(L"fresh\*(R", call +\&\f(CW\*(C`ev_default_destroy ()\*(C'\fR followed by \f(CW\*(C`ev_default_loop (...)\*(C'\fR. Destroying +the default loop will \*(L"orphan\*(R" (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. +.PP \fIWatcher-Specific Functions and Data Members\fR .IX Subsection "Watcher-Specific Functions and Data Members" .IP "ev_fork_init (ev_signal *, callback)" 4 @@ -2827,9 +3028,14 @@ an \f(CW\*(C`EV_ASYNC\*(C'\fR event on the watcher into the event loop. Unlike similar contexts (see the discussion of \f(CW\*(C`EV_ATOMIC_T\*(C'\fR in the embedding section below on what exactly this means). .Sp -This call incurs the overhead of a system call only once per loop iteration, -so while the overhead might be noticeable, it doesn't apply to repeated -calls to \f(CW\*(C`ev_async_send\*(C'\fR. +Note that, as with other watchers in libev, multiple events might get +compressed into a single callback invocation (another way to look at this +is that \f(CW\*(C`ev_async\*(C'\fR watchers are level-triggered, set on \f(CW\*(C`ev_async_send\*(C'\fR, +reset when the event loop detects that). +.Sp +This call incurs the overhead of a system call only once per event loop +iteration, so while the overhead might be noticeable, it doesn't apply to +repeated calls to \f(CW\*(C`ev_async_send\*(C'\fR for the same event loop. .IP "bool = ev_async_pending (ev_async *)" 4 .IX Item "bool = ev_async_pending (ev_async *)" Returns a non-zero value when \f(CW\*(C`ev_async_send\*(C'\fR has been called on the @@ -2841,8 +3047,10 @@ the loop iterates next and checks for the watcher to have become active, it will reset the flag again. \f(CW\*(C`ev_async_pending\*(C'\fR can be used to very quickly check whether invoking the loop might be a good idea. .Sp -Not that this does \fInot\fR check whether the watcher itself is pending, only -whether it has been requested to make this watcher pending. +Not that this does \fInot\fR check whether the watcher itself is pending, +only whether it has been requested to make this watcher pending: there +is a time window between the event loop checking and resetting the async +notification, and the callback being invoked. .SH "OTHER FUNCTIONS" .IX Header "OTHER FUNCTIONS" There are some other functions of possible interest. Described. Here. Now. @@ -3133,11 +3341,7 @@ It can be found and installed via \s-1CPAN\s0, its homepage is at .IP "Python" 4 .IX Item "Python" Python bindings can be found at . It -seems to be quite complete and well-documented. Note, however, that the -patch they require for libev is outright dangerous as it breaks the \s-1ABI\s0 -for everybody else, and therefore, should never be applied in an installed -libev (if python requires an incompatible \s-1ABI\s0 then it needs to embed -libev). +seems to be quite complete and well-documented. .IP "Ruby" 4 .IX Item "Ruby" Tony Arcieri has written a ruby extension that offers access to a subset @@ -3147,6 +3351,10 @@ more on top of it. It can be found via gem servers. Its homepage is at .Sp Roger Pack reports that using the link order \f(CW\*(C`\-lws2_32 \-lmsvcrt\-ruby\-190\*(C'\fR makes rev work even on mingw. +.IP "Haskell" 4 +.IX Item "Haskell" +A haskell binding to libev is available at +. .IP "D" 4 .IX Item "D" Leandro Lucarella has written a D language binding (\fIev.d\fR) for libev, to @@ -3825,6 +4033,9 @@ way (note also that glib is the slowest event library known to man). There is no supported compilation method available on windows except embedding it into other applications. .PP +Sensible signal handling is officially unsupported by Microsoft \- libev +tries its best, but under most conditions, signals will simply not work. +.PP Not a libev limitation but worth mentioning: windows apparently doesn't accept large writes: instead of resulting in a partial write, windows will either accept everything or return \f(CW\*(C`ENOBUFS\*(C'\fR if the buffer is too large, @@ -3838,7 +4049,7 @@ is not recommended (and not reasonable). If your program needs to use more than a hundred or so sockets, then likely it needs to use a totally different implementation for windows, as libev offers the \s-1POSIX\s0 readiness notification model, which cannot be implemented efficiently on windows -(Microsoft monopoly games). +(due to Microsoft monopoly games). .PP A typical way to use libev under windows is to embed it (see the embedding section for details) and use the following \fIevwrap.h\fR header file instead @@ -3886,24 +4097,22 @@ Early versions of winsocket's select only supported waiting for a maximum of \f(CW64\fR handles (probably owning to the fact that all windows kernels can only wait for \f(CW64\fR 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!). .Sp Newer versions support more handles, but you need to define \f(CW\*(C`FD_SETSIZE\*(C'\fR to some high number (e.g. \f(CW2048\fR) 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). .Sp Another limit is the number of file descriptors in the Microsoft runtime -libraries, which by default is \f(CW64\fR (there must be a hidden \fI64\fR fetish -or something like this inside Microsoft). You can increase this by calling -\&\f(CW\*(C`_setmaxstdio\*(C'\fR, which can increase this limit to \f(CW2048\fR (another -arbitrary limit), but is broken in many versions of the Microsoft runtime -libraries. -.Sp -This might get you to about \f(CW512\fR or \f(CW2048\fR 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(nA\*^X)) will likely make this unworkable. +libraries, which by default is \f(CW64\fR (there must be a hidden \fI64\fR +fetish or something like this inside Microsoft). You can increase this +by calling \f(CW\*(C`_setmaxstdio\*(C'\fR, which can increase this limit to \f(CW2048\fR +(another arbitrary limit), but is broken in many versions of the Microsoft +runtime libraries. This might get you to about \f(CW512\fR or \f(CW2048\fR 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(nA\*^X)) will likely make this unworkable. .Sh "\s-1PORTABILITY\s0 \s-1REQUIREMENTS\s0" .IX Subsection "PORTABILITY REQUIREMENTS" In addition to a working ISO-C implementation and of course the @@ -4016,6 +4225,65 @@ watchers becomes O(1) with respect to priority handling. Sending involves a system call \fIiff\fR there were no other \f(CW\*(C`ev_async_send\*(C'\fR calls in the current loop iteration. Checking for async and signal events involves iterating over all running async watchers or all signal numbers. +.SH "GLOSSARY" +.IX Header "GLOSSARY" +.IP "active" 4 +.IX 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). +.IP "application" 4 +.IX Item "application" +In this document, an application is whatever is using libev. +.IP "callback" 4 +.IX 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. +.IP "callback invocation" 4 +.IX Item "callback invocation" +The act of calling the callback associated with a watcher. +.IP "event" 4 +.IX 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. +.Sp +In libev, events are represented as single bits (such as \f(CW\*(C`EV_READ\*(C'\fR or +\&\f(CW\*(C`EV_TIMEOUT\*(C'\fR). +.IP "event library" 4 +.IX Item "event library" +A software package implementing an event model and loop. +.IP "event loop" 4 +.IX Item "event loop" +An entity that handles and processes external events and converts them +into callback invocations. +.IP "event model" 4 +.IX Item "event model" +The model used to describe how an event loop handles and processes +watchers and events. +.IP "pending" 4 +.IX 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. +.Sp +A watcher can be pending, but not active. Stopping a watcher also clears +its pending status. +.IP "real time" 4 +.IX Item "real time" +The physical time that is observed. It is apparently strictly monotonic :) +.IP "wall-clock time" 4 +.IX 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. +.IP "watcher" 4 +.IX 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. +.IP "watcher invocation" 4 +.IX Item "watcher invocation" +The act of calling the callback associated with a watcher. .SH "AUTHOR" .IX Header "AUTHOR" Marc Lehmann , with repeated corrections by Mikael Magnusson. -- cgit v1.2.3