summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes1
-rw-r--r--ev.3194
-rw-r--r--ev.pod2
3 files changed, 141 insertions, 56 deletions
diff --git a/Changes b/Changes
index 3216dd0..cab1e19 100644
--- a/Changes
+++ b/Changes
@@ -13,6 +13,7 @@ Revision history for libev, a high-performance and full-featured event loop.
- add/document ev_periodic_at, retract direct access to ->at.
- improve ev_stat docs.
- add portability requirements section.
+ - fix manpage headers etc.
3.31 Wed Apr 16 20:45:04 CEST 2008
- added last minute fix for ev_poll.c by Brandon Black.
diff --git a/ev.3 b/ev.3
index 560dc01..543a10c 100644
--- a/ev.3
+++ b/ev.3
@@ -131,8 +131,8 @@
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
-.IX Title "EV 1"
-.TH EV 1 "2008-04-11" "perl v5.10.0" "User Contributed Perl Documentation"
+.IX Title "LIBEV 3"
+.TH LIBEV 3 "2008-05-09" "libev-1.1" "libev - high perfromance 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
@@ -1513,6 +1513,10 @@ Simply stops and restarts the periodic watcher again. This is only useful
when you changed some parameters or the reschedule callback would return
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.
.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
@@ -1530,10 +1534,6 @@ called.
The current reschedule callback, or \f(CW0\fR, if this functionality is
switched off. Can be changed any time, but changes only take effect when
the periodic timer fires or \f(CW\*(C`ev_periodic_again\*(C'\fR is being called.
-.IP "ev_tstamp at [read\-only]" 4
-.IX Item "ev_tstamp at [read-only]"
-When active, contains the absolute time that the watcher is supposed to
-trigger next.
.PP
\fIExamples\fR
.IX Subsection "Examples"
@@ -1749,11 +1749,12 @@ resource-intensive.
.PP
At the time of this writing, only the Linux inotify interface is
implemented (implementing kqueue support is left as an exercise for the
-reader). Inotify will be used to give hints only and should not change the
-semantics of \f(CW\*(C`ev_stat\*(C'\fR watchers, which means that libev sometimes needs
-to fall back to regular polling again even with inotify, but changes are
-usually detected immediately, and if the file exists there will be no
-polling.
+reader, note, however, that the author sees no way of implementing ev_stat
+semantics with kqueue). Inotify will be used to give hints only and should
+not change the semantics of \f(CW\*(C`ev_stat\*(C'\fR watchers, which means that libev
+sometimes needs to fall back to regular polling again even with inotify,
+but changes are usually detected immediately, and if the file exists there
+will be no polling.
.PP
\fI\s-1ABI\s0 Issues (Largefile Support)\fR
.IX Subsection "ABI Issues (Largefile Support)"
@@ -1775,9 +1776,9 @@ available on Linux) and present at runtime, it will be used to speed up
change detection where possible. The inotify descriptor will be created lazily
when the first \f(CW\*(C`ev_stat\*(C'\fR watcher is being started.
.PP
-Inotify presense does not change the semantics of \f(CW\*(C`ev_stat\*(C'\fR watchers
+Inotify presence does not change the semantics of \f(CW\*(C`ev_stat\*(C'\fR watchers
except that changes might be detected earlier, and in some cases, to avoid
-making regular \f(CW\*(C`stat\*(C'\fR calls. Even in the presense of inotify support
+making regular \f(CW\*(C`stat\*(C'\fR calls. Even in the presence of inotify support
there are many cases where libev has to resort to regular \f(CW\*(C`stat\*(C'\fR polling.
.PP
(There is no support for kqueue, as apparently it cannot be used to
@@ -1791,16 +1792,25 @@ The \f(CW\*(C`stat ()\*(C'\fR syscall only supports full-second resolution porta
even on systems where the resolution is higher, many filesystems still
only support whole seconds.
.PP
-That means that, if the time is the only thing that changes, you might
-miss updates: on the first update, \f(CW\*(C`ev_stat\*(C'\fR detects a change and calls
-your callback, which does something. When there is another update within
-the same second, \f(CW\*(C`ev_stat\*(C'\fR will be unable to detect it.
-.PP
-The solution to this is to delay acting on a change for a second (or till
-the next second boundary), using a roughly one-second delay \f(CW\*(C`ev_timer\*(C'\fR
-(\f(CW\*(C`ev_timer_set (w, 0., 1.01); ev_timer_again (loop, w)\*(C'\fR). The \f(CW.01\fR
-is added to work around small timing inconsistencies of some operating
-systems.
+That means that, if the time is the only thing that changes, you can
+easily miss updates: on the first update, \f(CW\*(C`ev_stat\*(C'\fR detects a change and
+calls your callback, which does something. When there is another update
+within the same second, \f(CW\*(C`ev_stat\*(C'\fR will be unable to detect it as the stat
+data does not change.
+.PP
+The solution to this is to delay acting on a change for slightly more
+than second (or till slightly after the next full second boundary), using
+a roughly one-second-delay \f(CW\*(C`ev_timer\*(C'\fR (e.g. \f(CW\*(C`ev_timer_set (w, 0., 1.02);
+ev_timer_again (loop, w)\*(C'\fR).
+.PP
+The \f(CW.02\fR offset is added to work around small timing inconsistencies
+of some operating systems (where the second counter of the current time
+might be be delayed. One such system is the Linux kernel, where a call to
+\&\f(CW\*(C`gettimeofday\*(C'\fR might return a timestamp with a full second later than
+a subsequent \f(CW\*(C`time\*(C'\fR call \- if the equivalent of \f(CW\*(C`time ()\*(C'\fR is used to
+update file times then there will be a small window where the kernel uses
+the previous second to update file times but libev might already execute
+the timer callback).
.PP
\fIWatcher-Specific Functions and Data Members\fR
.IX Subsection "Watcher-Specific Functions and Data Members"
@@ -1816,25 +1826,29 @@ be detected and should normally be specified as \f(CW0\fR to let libev choose
a suitable value. The memory pointed to by \f(CW\*(C`path\*(C'\fR must point to the same
path for as long as the watcher is active.
.Sp
-The callback will be receive \f(CW\*(C`EV_STAT\*(C'\fR when a change was detected,
-relative to the attributes at the time the watcher was started (or the
-last change was detected).
+The callback will receive \f(CW\*(C`EV_STAT\*(C'\fR when a change was detected, relative
+to the attributes at the time the watcher was started (or the last change
+was detected).
.IP "ev_stat_stat (loop, ev_stat *)" 4
.IX Item "ev_stat_stat (loop, ev_stat *)"
Updates the stat buffer immediately with new values. If you change the
-watched path in your callback, you could call this fucntion to avoid
-detecting this change (while introducing a race condition). Can also be
-useful simply to find out the new values.
+watched path in your callback, you could call this function to avoid
+detecting this change (while introducing a race condition if you are not
+the only one changing the path). Can also be useful simply to find out the
+new values.
.IP "ev_statdata attr [read\-only]" 4
.IX Item "ev_statdata attr [read-only]"
-The most-recently detected attributes of the file. Although the type is of
+The most-recently detected attributes of the file. Although the type is
\&\f(CW\*(C`ev_statdata\*(C'\fR, this is usually the (or one of the) \f(CW\*(C`struct stat\*(C'\fR types
-suitable for your system. If the \f(CW\*(C`st_nlink\*(C'\fR member is \f(CW0\fR, then there
-was some error while \f(CW\*(C`stat\*(C'\fRing the file.
+suitable for your system, but you can only rely on the POSIX-standardised
+members to be present. If the \f(CW\*(C`st_nlink\*(C'\fR member is \f(CW0\fR, then there was
+some error while \f(CW\*(C`stat\*(C'\fRing the file.
.IP "ev_statdata prev [read\-only]" 4
.IX Item "ev_statdata prev [read-only]"
The previous attributes of the file. The callback gets invoked whenever
-\&\f(CW\*(C`prev\*(C'\fR != \f(CW\*(C`attr\*(C'\fR.
+\&\f(CW\*(C`prev\*(C'\fR != \f(CW\*(C`attr\*(C'\fR, or, more precisely, one or more of these members
+differ: \f(CW\*(C`st_dev\*(C'\fR, \f(CW\*(C`st_ino\*(C'\fR, \f(CW\*(C`st_mode\*(C'\fR, \f(CW\*(C`st_nlink\*(C'\fR, \f(CW\*(C`st_uid\*(C'\fR,
+\&\f(CW\*(C`st_gid\*(C'\fR, \f(CW\*(C`st_rdev\*(C'\fR, \f(CW\*(C`st_size\*(C'\fR, \f(CW\*(C`st_atime\*(C'\fR, \f(CW\*(C`st_mtime\*(C'\fR, \f(CW\*(C`st_ctime\*(C'\fR.
.IP "ev_tstamp interval [read\-only]" 4
.IX Item "ev_tstamp interval [read-only]"
The specified interval.
@@ -1898,7 +1912,7 @@ one might do the work both on \f(CW\*(C`ev_stat\*(C'\fR callback invocation \fIa
\& ...
\& ev_stat_init (&passwd, stat_cb, "/etc/passwd", 0.);
\& ev_stat_start (loop, &passwd);
-\& ev_timer_init (&timer, timer_cb, 0., 1.01);
+\& ev_timer_init (&timer, timer_cb, 0., 1.02);
.Ve
.ie n .Sh """ev_idle"" \- when you've got nothing better to do..."
.el .Sh "\f(CWev_idle\fP \- when you've got nothing better to do..."
@@ -1994,7 +2008,7 @@ It is recommended to give \f(CW\*(C`ev_check\*(C'\fR watchers highest (\f(CW\*(C
priority, to ensure that they are being run before any other watchers
after the poll. Also, \f(CW\*(C`ev_check\*(C'\fR watchers (and \f(CW\*(C`ev_prepare\*(C'\fR watchers,
too) should not activate (\*(L"feed\*(R") events into libev. While libev fully
-supports this, they will be called before other \f(CW\*(C`ev_check\*(C'\fR watchers
+supports this, they might get executed before other \f(CW\*(C`ev_check\*(C'\fR watchers
did their job. As \f(CW\*(C`ev_check\*(C'\fR watchers are often used to embed other
(non-libev) event loops those other event loops might be in an unusable
state until their \f(CW\*(C`ev_check\*(C'\fR watcher ran (always remind yourself to
@@ -2018,9 +2032,9 @@ macros, but using them is utterly, utterly and completely pointless.
There are a number of principal ways to embed other event loops or modules
into libev. Here are some ideas on how to include libadns into libev
(there is a Perl module named \f(CW\*(C`EV::ADNS\*(C'\fR that does this, which you could
-use for an actually working example. Another Perl module named \f(CW\*(C`EV::Glib\*(C'\fR
-embeds a Glib main context into libev, and finally, \f(CW\*(C`Glib::EV\*(C'\fR embeds \s-1EV\s0
-into the Glib event loop).
+use as a working example. Another Perl module named \f(CW\*(C`EV::Glib\*(C'\fR embeds a
+Glib main context into libev, and finally, \f(CW\*(C`Glib::EV\*(C'\fR embeds \s-1EV\s0 into the
+Glib event loop).
.PP
Method 1: Add \s-1IO\s0 watchers and a timeout watcher in a prepare handler,
and in a check watcher, destroy them and call into libadns. What follows
@@ -3054,8 +3068,9 @@ defined to be \f(CW0\fR, then they are not.
.IP "\s-1EV_MINIMAL\s0" 4
.IX Item "EV_MINIMAL"
If you need to shave off some kilobytes of code at the expense of some
-speed, define this symbol to \f(CW1\fR. Currently only used for gcc to override
-some inlining decisions, saves roughly 30% codesize of amd64.
+speed, define this symbol to \f(CW1\fR. Currently this is used to override some
+inlining decisions, saves roughly 30% codesize of amd64. It also selects a
+much smaller 2\-heap for timer management over the default 4\-heap.
.IP "\s-1EV_PID_HASHSIZE\s0" 4
.IX Item "EV_PID_HASHSIZE"
\&\f(CW\*(C`ev_child\*(C'\fR watchers use a small hash table to distribute workload by
@@ -3069,6 +3084,26 @@ inotify watch id. The default size is \f(CW16\fR (or \f(CW1\fR with \f(CW\*(C`EV
usually more than enough. If you need to manage thousands of \f(CW\*(C`ev_stat\*(C'\fR
watchers you might want to increase this value (\fImust\fR be a power of
two).
+.IP "\s-1EV_USE_4HEAP\s0" 4
+.IX Item "EV_USE_4HEAP"
+Heaps are not very cache-efficient. To improve the cache-efficiency of the
+timer and periodics heap, libev uses a 4\-heap when this symbol is defined
+to \f(CW1\fR. The 4\-heap uses more complicated (longer) code but has a
+noticable after performance with many (thousands) of watchers.
+.Sp
+The default is \f(CW1\fR unless \f(CW\*(C`EV_MINIMAL\*(C'\fR is set in which case it is \f(CW0\fR
+(disabled).
+.IP "\s-1EV_HEAP_CACHE_AT\s0" 4
+.IX Item "EV_HEAP_CACHE_AT"
+Heaps are not very cache-efficient. To improve the cache-efficiency of the
+timer and periodics heap, libev can cache the timestamp (\fIat\fR) within
+the heap structure (selected by defining \f(CW\*(C`EV_HEAP_CACHE_AT\*(C'\fR to \f(CW1\fR),
+which uses 8\-12 bytes more per watcher and a few hundred bytes more code,
+but avoids random read accesses on heap changes. This noticably improves
+performance noticably with with many (hundreds) of watchers.
+.Sp
+The default is \f(CW1\fR unless \f(CW\*(C`EV_MINIMAL\*(C'\fR is set in which case it is \f(CW0\fR
+(disabled).
.IP "\s-1EV_COMMON\s0" 4
.IX Item "EV_COMMON"
By default, all watchers have a \f(CW\*(C`void *data\*(C'\fR member. By redefining
@@ -3244,8 +3279,8 @@ correct watcher to remove. The lists are usually short (you don't usually
have many watchers waiting for the same fd or signal).
.IP "Finding the next timer in each loop iteration: O(1)" 4
.IX Item "Finding the next timer in each loop iteration: O(1)"
-By virtue of using a binary heap, the next timer is always found at the
-beginning of the storage array.
+By virtue of using a binary or 4\-heap, the next timer is always found at a
+fixed position in the storage array.
.IP "Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)" 4
.IX 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
@@ -3281,15 +3316,21 @@ the form of the \f(CW\*(C`EVBACKEND_SELECT\*(C'\fR backend, and only supports so
descriptors. This only applies when using Win32 natively, not when using
e.g. cygwin.
.PP
+Lifting these limitations would basically require the full
+re-implementation of the I/O system. If you are into these kinds of
+things, then note that glib does exactly that for you in a very portable
+way (note also that glib is the slowest event library known to man).
+.PP
There is no supported compilation method available on windows except
embedding it into other applications.
.PP
-Due to the many, low, and arbitrary limits on the win32 platform and the
-abysmal performance of winsockets, using a large number of sockets 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 model, which cannot
-be implemented efficiently on windows (microsoft monopoly games).
+Due to the many, low, and arbitrary limits on the win32 platform and
+the abysmal performance of winsockets, using a large number of sockets
+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 readyness
+notification model, which cannot be implemented efficiently on windows
+(microsoft monopoly games).
.IP "The winsocket select function" 4
.IX Item "The winsocket select function"
The winsocket \f(CW\*(C`select\*(C'\fR function doesn't follow \s-1POSIX\s0 in that it requires
@@ -3311,11 +3352,13 @@ Note that winsockets handling of fd sets is O(n), so you can easily get a
complexity in the O(nA\*^X) range when using win32.
.IP "Limited number of file descriptors" 4
.IX Item "Limited number of file descriptors"
-Windows has numerous arbitrary (and low) limits on things. Early versions
-of winsocket's select only supported waiting for a max. 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).
+Windows has numerous arbitrary (and low) limits on things.
+.Sp
+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).
.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
@@ -3333,12 +3376,53 @@ 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 "PORTABILITY REQUIREMENTS"
+.IX Header "PORTABILITY REQUIREMENTS"
+In addition to a working ISO-C implementation, libev relies on a few
+additional extensions:
+.ie n .IP """sig_atomic_t volatile"" must be thread-atomic as well" 4
+.el .IP "\f(CWsig_atomic_t volatile\fR must be thread-atomic as well" 4
+.IX Item "sig_atomic_t volatile must be thread-atomic as well"
+The type \f(CW\*(C`sig_atomic_t volatile\*(C'\fR (or whatever is defined as
+\&\f(CW\*(C`EV_ATOMIC_T\*(C'\fR) must be atomic w.r.t. accesses from different
+threads. This is not part of the specification for \f(CW\*(C`sig_atomic_t\*(C'\fR, but is
+believed to be sufficiently portable.
+.ie n .IP """sigprocmask"" must work in a threaded environment" 4
+.el .IP "\f(CWsigprocmask\fR must work in a threaded environment" 4
+.IX Item "sigprocmask must work in a threaded environment"
+Libev uses \f(CW\*(C`sigprocmask\*(C'\fR to temporarily block signals. This is not
+allowed in a threaded program (\f(CW\*(C`pthread_sigmask\*(C'\fR has to be used). Typical
+pthread implementations will either allow \f(CW\*(C`sigprocmask\*(C'\fR in the \*(L"main
+thread\*(R" or will block signals process-wide, both behaviours would
+be compatible with libev. Interaction between \f(CW\*(C`sigprocmask\*(C'\fR and
+\&\f(CW\*(C`pthread_sigmask\*(C'\fR could complicate things, however.
+.Sp
+The most portable way to handle signals is to block signals in all threads
+except the initial one, and run the default loop in the initial thread as
+well.
+.ie n .IP """long"" must be large enough for common memory allocation sizes" 4
+.el .IP "\f(CWlong\fR must be large enough for common memory allocation sizes" 4
+.IX Item "long must be large enough for common memory allocation sizes"
+To improve portability and simplify using libev, libev uses \f(CW\*(C`long\*(C'\fR
+internally instead of \f(CW\*(C`size_t\*(C'\fR 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.
+.ie n .IP """double"" must hold a time value in seconds with enough accuracy" 4
+.el .IP "\f(CWdouble\fR must hold a time value in seconds with enough accuracy" 4
+.IX Item "double must hold a time value in seconds with enough accuracy"
+The type \f(CW\*(C`double\*(C'\fR 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 \s-1IEEE\s0 754 (basically all existing ones).
+.PP
+If you know of other additional requirements drop me a note.
.SH "AUTHOR"
.IX Header "AUTHOR"
Marc Lehmann <libev@schmorp.de>.
.SH "POD ERRORS"
.IX Header "POD ERRORS"
Hey! \fBThe above document had some coding errors, which are explained below:\fR
-.IP "Around line 3015:" 4
-.IX Item "Around line 3015:"
+.IP "Around line 3052:" 4
+.IX Item "Around line 3052:"
You forgot a '=back' before '=head2'
diff --git a/ev.pod b/ev.pod
index 0c09ceb..5cc3be2 100644
--- a/ev.pod
+++ b/ev.pod
@@ -66,7 +66,7 @@ libev - a high performance full-featured event loop written in C
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<http://cvs.schmorp.de/libev/ev.html>.
+time: L<http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod>.
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