--- libev/ev.pod 2012/04/28 12:10:07 1.404
+++ libev/ev.pod 2023/06/03 08:53:03 1.469
@@ -1,3 +1,5 @@
+=encoding utf-8
+
=head1 NAME
libev - a high performance full-featured event loop written in C
@@ -84,9 +86,9 @@
This manual tries to be very detailed, but unfortunately, this also makes
it very long. If you just want to know the basics of libev, I suggest
-reading L, then the L above and
-look up the missing functions in L and the C and
-C sections in L.
+reading L , then the L above and
+look up the missing functions in L and the C and
+C sections in L.
=head1 ABOUT LIBEV
@@ -105,10 +107,10 @@
=head2 FEATURES
-Libev supports C, C, the Linux-specific C, the
-BSD-specific C and the Solaris-specific event port mechanisms
-for file descriptor events (C), the Linux C interface
-(for C), Linux eventfd/signalfd (for faster and cleaner
+Libev supports C, C, the Linux-specific aio and C
+interfaces, the BSD-specific C and the Solaris-specific event port
+mechanisms for file descriptor events (C), the Linux C
+interface (for C), Linux eventfd/signalfd (for faster and cleaner
inter-thread wakeup (C)/signal handling (C)) relative
timers (C), absolute timers with customised rescheduling
(C), synchronous signals (C), process status
@@ -159,9 +161,13 @@
so C will disable this checking): these are programming errors in
the libev caller and need to be fixed there.
-Libev also has a few internal error-checking Cions, and also has
-extensive consistency checking code. These do not trigger under normal
-circumstances, as they indicate either a bug in libev or worse.
+Via the C macro you can compile in and/or enable extensive
+consistency checking code inside libev that can be used to check for
+internal inconsistencies, suually caused by application bugs.
+
+Libev also has a few internal error-checking Cions. These do not
+trigger under normal circumstances, as they indicate either a bug in libev
+or worse.
=head1 GLOBAL FUNCTIONS
@@ -265,12 +271,32 @@
free some memory if it cannot allocate memory, to use a special allocator,
or even to sleep a while and retry until some memory is available.
+Example: The following is the C function that libev itself uses
+which should work with C and C functions of all kinds and
+is probably a good basis for your own implementation.
+
+ static void *
+ ev_realloc_emul (void *ptr, long size) EV_NOEXCEPT
+ {
+ if (size)
+ return realloc (ptr, size);
+
+ free (ptr);
+ return 0;
+ }
+
Example: Replace the libev allocator with one that waits a bit and then
-retries (example requires a standards-compliant C).
+retries.
static void *
persistent_realloc (void *ptr, size_t size)
{
+ if (!size)
+ {
+ free (ptr);
+ return 0;
+ }
+
for (;;)
{
void *newptr = realloc (ptr, size);
@@ -398,8 +424,10 @@
or setgid) then libev will I look at the environment variable
C. Otherwise (the default), this environment variable will
override the flags completely if it is found in the environment. This is
-useful to try out specific backends to test their performance, or to work
-around bugs.
+useful to try out specific backends to test their performance, to work
+around bugs, or to make libev threadsafe (accessing environment variables
+cannot be done in a threadsafe way, but usually it works if no other
+thread modifies them).
=item C
@@ -409,13 +437,14 @@
This works by calling C on every iteration of the loop,
and thus this might slow down your event loop if you do a lot of loop
iterations and little real work, but is usually not noticeable (on my
-GNU/Linux system for example, C is actually a simple 5-insn sequence
-without a system call and thus I fast, but my GNU/Linux system also has
-C which is even faster).
+GNU/Linux system for example, C is actually a simple 5-insn
+sequence without a system call and thus I fast, but my GNU/Linux
+system also has C which is even faster). (Update: glibc
+versions 2.25 apparently removed the C optimisation again).
The big advantage of this flag is that you can forget about fork (and
-forget about forgetting to tell libev about forking) when you use this
-flag.
+forget about forgetting to tell libev about forking, although you still
+have to ignore C) when you use this flag.
This flag setting cannot be overridden or specified in the C
environment variable.
@@ -453,7 +482,16 @@
It's also required by POSIX in a threaded program, as libev calls
C, whose behaviour is officially unspecified.
-This flag's behaviour will become the default in future versions of libev.
+=item C
+
+When this flag is specified, the libev will avoid using a C to
+detect time jumps. It will still be able to detect time jumps, but takes
+longer and has a lower accuracy in doing so, but saves a file descriptor
+per loop.
+
+The current implementation only tries to use a C when the first
+C watcher is started and falls back on other methods if it
+cannot be created, but this behaviour might change in the future.
=item C (value 1, portable select backend)
@@ -488,7 +526,7 @@
=item C (value 4, Linux)
-Use the linux-specific epoll(7) interface (for both pre- and post-2.6.9
+Use the Linux-specific epoll(7) interface (for both pre- and post-2.6.9
kernels).
For few fds, this backend is a bit little slower than poll and select, but
@@ -544,22 +582,66 @@
the usage. So sad.
While nominally embeddable in other event loops, this feature is broken in
-all kernel versions tested so far.
+a lot of kernel revisions, but probably(!) works in current versions.
+
+This backend maps C and C in the same way as
+C.
+
+=item C (value 64, Linux)
+
+Use the Linux-specific Linux AIO (I C<< aio(7) >> but C<<
+io_submit(2) >>) event interface available in post-4.18 kernels (but libev
+only tries to use it in 4.19+).
+
+This is another Linux train wreck of an event interface.
+
+If this backend works for you (as of this writing, it was very
+experimental), it is the best event interface available on Linux and might
+be well worth enabling it - if it isn't available in your kernel this will
+be detected and this backend will be skipped.
+
+This backend can batch oneshot requests and supports a user-space ring
+buffer to receive events. It also doesn't suffer from most of the design
+problems of epoll (such as not being able to remove event sources from
+the epoll set), and generally sounds too good to be true. Because, this
+being the Linux kernel, of course it suffers from a whole new set of
+limitations, forcing you to fall back to epoll, inheriting all its design
+issues.
+
+For one, it is not easily embeddable (but probably could be done using
+an event fd at some extra overhead). It also is subject to a system wide
+limit that can be configured in F. If no AIO
+requests are left, this backend will be skipped during initialisation, and
+will switch to epoll when the loop is active.
+
+Most problematic in practice, however, is that not all file descriptors
+work with it. For example, in Linux 5.1, TCP sockets, pipes, event fds,
+files, F and many others are supported, but ttys do not work
+properly (a known bug that the kernel developers don't care about, see
+L ), so this is not
+(yet?) a generic event polling interface.
+
+Overall, it seems the Linux developers just don't want it to have a
+generic event handling mechanism other than C or C.
+
+To work around all these problem, the current version of libev uses its
+epoll backend as a fallback for file descriptor types that do not work. Or
+falls back completely to epoll if the kernel acts up.
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). 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.
+Kqueue deserves special mention, as at the time this backend was
+implemented, 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). Unlike epoll, however, whose
+brokenness is by design, these kqueue bugs can be (and mostly have been)
+fixed without API changes to existing programs. For this reason it's not
+being "auto-detected" on all platforms 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.
You still can embed kqueue into a normal poll or select backend and use it
only for sockets (after having made sure that sockets work with kqueue on
@@ -570,8 +652,8 @@
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 (you
-might have to leak fd's on fork, but it's more sane than epoll) and it
-drops fds silently in similarly hard-to-detect cases
+might have to leak fds on fork, but it's more sane than epoll) and it
+drops fds silently in similarly hard-to-detect cases.
This backend usually performs well under most conditions.
@@ -595,8 +677,8 @@
=item C (value 32, Solaris 10)
-This uses the Solaris 10 event port mechanism. As with everything on Solaris,
-it's really slow, but it still scales very well (O(active_fds)).
+This uses the Solaris 10 event port mechanism. As with everything on
+Solaris, it's really slow, but it still scales very well (O(active_fds)).
While this backend scales well, it requires one system call per active
file descriptor per loop iteration. For small and medium numbers of file
@@ -655,6 +737,12 @@
struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_KQUEUE);
+Example: Similarly, on linux, you mgiht want to take advantage of the
+linux aio backend if possible, but fall back to something else if that
+isn't available.
+
+ struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_LINUXAIO);
+
=item ev_loop_destroy (loop)
Destroys an event loop object (frees all memory and kernel state
@@ -680,13 +768,17 @@
=item ev_loop_fork (loop)
-This function sets a flag that causes subsequent C iterations to
-reinitialise the kernel state for backends that have one. Despite the
-name, you can call it anytime, but it makes most sense after forking, in
-the child process. You I call it (or use C) in the
-child before resuming or calling C.
+This function sets a flag that causes subsequent C iterations
+to reinitialise the kernel state for backends that have one. Despite
+the name, you can call it anytime you are allowed to start or stop
+watchers (except inside an C callback), but it makes most
+sense after forking, in the child process. You I call it (or use
+C) in the child before resuming or calling C.
+
+In addition, if you want to reuse a loop (via this function or
+C), you I have to ignore C.
-Again, you I to call it on I loop that you want to re-use after
+Again, you I to call it on I loop that you want to re-use after
a fork, I. This is
because some kernel interfaces *cough* I *cough* do funny things
during fork.
@@ -766,7 +858,7 @@
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.
+See also L in the C section.
=item ev_suspend (loop)
@@ -869,8 +961,8 @@
- Queue all idle watchers with priority higher than that of pending events.
- 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
- be handled here by queueing them when their watcher gets executed.
+ Signals, async and child watchers are implemented as I/O watchers, and
+ will be handled here by queueing them when their watcher gets executed.
- If ev_break has been called, or EVRUN_ONCE or EVRUN_NOWAIT
were used, or there are no active watchers, goto FINISH, otherwise
continue with step LOOP.
@@ -1128,8 +1220,9 @@
corresponding stop function (C<< ev_TYPE_stop (loop, watcher *) >>.
As long as your watcher is active (has been started but not stopped) you
-must not touch the values stored in it. Most specifically you must never
-reinitialise it or call its C macro.
+must not touch the values stored in it except when explicitly documented
+otherwise. Most specifically you must never reinitialise it or call its
+C macro.
Each and every callback receives the event loop pointer as first, the
registered watcher structure as second, and a bitset of received events as
@@ -1176,13 +1269,18 @@
=item C
-All C watchers are invoked just I C starts
-to gather new events, and all C watchers are invoked just after
-C has gathered them, but before it invokes any callbacks for any
-received events. Callbacks of both watcher types can start and stop as
-many watchers as they want, and all of them will be taken into account
-(for example, a C watcher might start an idle watcher to keep
-C from blocking).
+All C watchers are invoked just I C starts to
+gather new events, and all C watchers are queued (not invoked)
+just after C has gathered them, but before it queues any callbacks
+for any received events. That means C watchers are the last
+watchers invoked before the event loop sleeps or polls for new events, and
+C watchers will be invoked before any other watchers of the same
+or lower priority within an event loop iteration.
+
+Callbacks of both watcher types can start and stop as many watchers as
+they want, and all of them will be taken into account (for example, a
+C watcher might start an idle watcher to keep C from
+blocking).
=item C
@@ -1300,7 +1398,10 @@
Returns a true value iff the watcher is active (i.e. it has been started
and not yet been stopped). As long as a watcher is active you must not modify
-it.
+it unless documented otherwise.
+
+Obviously, it is safe to call this on an active watcher, or actually any
+watcher that is initialised.
=item bool ev_is_pending (ev_TYPE *watcher)
@@ -1311,11 +1412,14 @@
make sure the watcher is available to libev (e.g. you cannot C
it).
+It is safe to call this on any watcher in any state as long as it is
+initialised.
+
=item callback ev_cb (ev_TYPE *watcher)
Returns the callback currently set on the watcher.
-=item ev_cb_set (ev_TYPE *watcher, callback)
+=item ev_set_cb (ev_TYPE *watcher, callback)
Change the callback. You can change the callback at virtually any time
(modulo threads).
@@ -1333,8 +1437,8 @@
If you need to suppress invocation when higher priority events are pending
you need to look at C watchers, which provide this functionality.
-You I change the priority of a watcher as long as it is active or
-pending.
+You I change the priority of a watcher as long as it is active
+or pending. Reading the priority with C is fine in any state.
Setting a priority outside the range of C to C is
fine, as long as you do not mind that the priority value you query might
@@ -1343,7 +1447,7 @@
The default priority used by watchers when no priority has been set is
always C<0>, which is supposed to not be too high and not be too low :).
-See L, below, for a more thorough treatment of
+See L , below, for a more thorough treatment of
priorities.
=item ev_invoke (loop, ev_TYPE *watcher, int revents)
@@ -1366,8 +1470,9 @@
Feeds the given event set into the event loop, as if the specified event
had happened for the specified watcher (which must be a pointer to an
-initialised but not necessarily started event watcher). Obviously you must
-not free the watcher as long as it has pending events.
+initialised but not necessarily started event watcher, though it can be
+active). Obviously you must not free the watcher as long as it has pending
+events.
Stopping the watcher, letting libev invoke it, or calling
C will clear the pending event, even if the watcher was
@@ -1378,7 +1483,7 @@
=back
-See also the L and L and L idioms.
=head2 WATCHER STATES
@@ -1390,7 +1495,7 @@
=over 4
-=item initialiased
+=item initialised
Before a watcher can be registered with the event loop it has to be
initialised. This can be done with a call to C, or calls to
@@ -1405,24 +1510,33 @@
Once a watcher has been started with a call to C it becomes
property of the event loop, and is actively waiting for events. While in
-this state it cannot be accessed (except in a few documented ways), moved,
-freed or anything else - the only legal thing is to keep a pointer to it,
-and call libev functions on it that are documented to work on active watchers.
+this state it cannot be accessed (except in a few documented ways, such as
+stoping it), moved, freed or anything else - the only legal thing is to
+keep a pointer to it, and call libev functions on it that are documented
+to work on active watchers.
+
+As a rule of thumb, before accessing a member or calling any function on
+a watcher, it should be stopped (or freshly initialised). If that is not
+convenient, you can check the documentation for that function or member to
+see if it is safe to use on an active watcher.
=item pending
If a watcher is active and libev determines that an event it is interested
-in has occurred (such as a timer expiring), it will become pending. It will
-stay in this pending state until either it is stopped or its callback is
-about to be invoked, so it is not normally pending inside the watcher
-callback.
+in has occurred (such as a timer expiring), it will become pending. It
+will stay in this pending state until either it is explicitly stopped or
+its callback is about to be invoked, so it is not normally pending inside
+the watcher callback.
+
+Generally, the watcher might or might not be active while it is pending
+(for example, an expired non-repeating timer can be pending but no longer
+active). If it is pending but not active, it can be freely accessed (e.g.
+by calling C), but it is still property of the event loop at
+this time, so cannot be moved, freed or reused. And if it is active the
+rules described in the previous item still apply.
-The watcher might or might not be active while it is pending (for example,
-an expired non-repeating timer can be pending but no longer active). If it
-is stopped, it can be freely accessed (e.g. by calling C),
-but it is still property of the event loop at this time, so cannot be
-moved, freed or reused. And if it is active the rules described in the
-previous item still apply.
+Explicitly stopping a watcher will also clear the pending state
+unconditionally, so it is safe to stop a watcher and then free it.
It is also possible to feed an event on a watcher that is not active (e.g.
via C), in which case it becomes pending without being
@@ -1449,7 +1563,7 @@
integers that influence the ordering of event callback invocation
between watchers in some way, all else being equal.
-In libev, Watcher priorities can be set using C. See its
+In libev, watcher priorities can be set using C. See its
description for the more technical details such as the actual priority
range.
@@ -1553,15 +1667,18 @@
information given in the last section. Any initialisation/set macros,
functions and members specific to the watcher type are explained.
-Members are additionally marked with either I<[read-only]>, meaning that,
-while the watcher is active, you can look at the member and expect some
-sensible content, but you must not modify it (you can modify it while the
-watcher is stopped to your hearts content), or I<[read-write]>, which
-means you can expect it to have some sensible content while the watcher
-is active, but you can also modify it. Modifying it may not do something
+Most members are additionally marked with either I<[read-only]>, meaning
+that, while the watcher is active, you can look at the member and expect
+some sensible content, but you must not modify it (you can modify it while
+the watcher is stopped to your hearts content), or I<[read-write]>, which
+means you can expect it to have some sensible content while the watcher is
+active, but you can also modify it (within the same thread as the event
+loop, i.e. without creating data races). Modifying it may not do something
sensible or take immediate effect (or do anything at all), but libev will
not crash or malfunction in any way.
+In any case, the documentation for each member will explain what the
+effects are, and if there are any additional access restrictions.
=head2 C - is this file descriptor readable or writable?
@@ -1598,13 +1715,13 @@
=head3 The special problem of disappearing file descriptors
-Some backends (e.g. kqueue, epoll) need to be told about closing a file
-descriptor (either due to calling C explicitly or any other means,
-such as C). The reason is that you register interest in some file
-descriptor, but when it goes away, the operating system will silently drop
-this interest. If another file descriptor with the same number then is
-registered with libev, there is no efficient way to see that this is, in
-fact, a different file descriptor.
+Some backends (e.g. kqueue, epoll, linuxaio) need to be told about closing
+a file descriptor (either due to calling C explicitly or any other
+means, such as C). The reason is that you register interest in some
+file descriptor, but when it goes away, the operating system will silently
+drop this interest. If another file descriptor with the same number then
+is registered with libev, there is no efficient way to see that this is,
+in fact, a different file descriptor.
To avoid having to explicitly tell libev about such cases, libev follows
the following policy: Each time C is being called, libev
@@ -1663,9 +1780,10 @@
=head3 The special problem of fork
-Some backends (epoll, kqueue) do not support C at all or exhibit
-useless behaviour. Libev fully supports fork, but needs to be told about
-it in the child if you want to continue to use it in the child.
+Some backends (epoll, kqueue, linuxaio, iouring) do not support C
+at all or exhibit useless behaviour. Libev fully supports fork, but needs
+to be told about it in the child if you want to continue to use it in the
+child.
To support fork in your child processes, you have to call C after a fork in the child, enable C, or resort to
@@ -1730,16 +1848,36 @@
=item ev_io_set (ev_io *, int fd, int events)
Configures an C watcher. The C is the file descriptor to
-receive events for and C is either C, C or
-C, to express the desire to receive the given events.
+receive events for and C is either C, C, both
+C or C<0>, to express the desire to receive the given
+events.
+
+Note that setting the C to C<0> and starting the watcher is
+supported, but not specially optimized - if your program sometimes happens
+to generate this combination this is fine, but if it is easy to avoid
+starting an io watcher watching for no events you should do so.
+
+=item ev_io_modify (ev_io *, int events)
-=item int fd [read-only]
+Similar to C, but only changes the requested events. Using this
+might be faster with some backends, as libev can assume that the C
+still refers to the same underlying file description, something it cannot
+do when using C.
-The file descriptor being watched.
+=item int fd [no-modify]
-=item int events [read-only]
+The file descriptor being watched. While it can be read at any time, you
+must not modify this member even when the watcher is stopped - always use
+C for that.
-The events being watched.
+=item int events [no-modify]
+
+The set of events the fd is being watched for, among other flags. Remember
+that this is a bit set - to test for C, use C<< w->events &
+EV_READ >>, and similarly for C.
+
+As with C, you must not modify this member even when the watcher is
+stopped, always use C or C for that.
=back
@@ -2021,13 +2159,15 @@
time. This is usually the right thing as this timestamp refers to the time
of the event triggering whatever timeout you are modifying/starting. If
you suspect event processing to be delayed and you I to base the
-timeout on the current time, use something like this to adjust for this:
+timeout on the current time, use something like the following to adjust
+for it:
- ev_timer_set (&timer, after + ev_now () - ev_time (), 0.);
+ ev_timer_set (&timer, after + (ev_time () - ev_now ()), 0.);
If the event loop is suspended for a long time, you can also force an
update of the time returned by C by calling C.
+()>, although that will push the event time of all outstanding events
+further into the future.
=head3 The special problem of unsynchronised clocks
@@ -2100,11 +2240,11 @@
=item ev_timer_set (ev_timer *, ev_tstamp after, ev_tstamp repeat)
-Configure the timer to trigger after C seconds. If C
-is C<0.>, then it will automatically be stopped once the timeout is
-reached. If it is positive, then the timer will automatically be
-configured to trigger again C seconds later, again, and again,
-until stopped manually.
+Configure the timer to trigger after C seconds (fractional and
+negative values are supported). If C is C<0.>, then it will
+automatically be stopped once the timeout is reached. If it is positive,
+then the timer will automatically be configured to trigger again C
+seconds later, again, and again, until stopped manually.
The timer itself will do a best-effort at avoiding drift, that is, if
you configure a timer to trigger every 10 seconds, then it will normally
@@ -2133,7 +2273,7 @@
=back
-This sounds a bit complicated, see L, above, for a
+This sounds a bit complicated, see L , above, for a
usage example.
=item ev_tstamp ev_timer_remaining (loop, ev_timer *)
@@ -2196,7 +2336,7 @@
Unlike C, 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
+(absolute time, the thing you can read on your calendar 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).
@@ -2211,8 +2351,8 @@
C watchers can also be used to implement vastly more complex
timers, such as triggering an event on each "midnight, local time", or
-other complicated rules. This cannot be done with C watchers, as
-those cannot react to time jumps.
+other complicated rules. This cannot easily be done with C
+watchers, as those cannot react to time jumps.
As with timers, the callback is guaranteed to be invoked only when the
point in time where it is supposed to trigger has passed. If multiple
@@ -2308,10 +2448,28 @@
equal to the passed C value >>.
This can be used to create very complex timers, such as a timer that
-triggers on "next midnight, local time". To do this, you would calculate the
-next midnight after C and return the timestamp value for this. How
-you do this is, again, up to you (but it is not trivial, which is the main
-reason I omitted it as an example).
+triggers on "next midnight, local time". To do this, you would calculate
+the next midnight after C and return the timestamp value for
+this. Here is a (completely untested, no error checking) example on how to
+do this:
+
+ #include
+
+ static ev_tstamp
+ my_rescheduler (ev_periodic *w, ev_tstamp now)
+ {
+ time_t tnow = (time_t)now;
+ struct tm tm;
+ localtime_r (&tnow, &tm);
+
+ tm.tm_sec = tm.tm_min = tm.tm_hour = 0; // midnight current day
+ ++tm.tm_mday; // midnight next day
+
+ return mktime (&tm);
+ }
+
+Note: this code might run into trouble on days that have more then two
+midnights (beginning and end).
=back
@@ -2386,7 +2544,7 @@
ev_periodic_init (&hourly_tick, clock_cb,
fmod (ev_now (loop), 3600.), 3600., 0);
ev_periodic_start (loop, &hourly_tick);
-
+
=head2 C - signal me when a signal gets signalled!
@@ -2406,9 +2564,9 @@
C in both the default loop and another loop at the same time. At
the moment, C is permanently tied to the default loop.
-When the 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).
+Only after the first watcher for a signal is started will libev actually
+register something with the kernel. It thus coexists with your own signal
+handlers as long as you don't register any with libev for the same signal.
If possible and supported, libev will install its handlers with
C (or equivalent) behaviour enabled, so system calls should
@@ -2603,8 +2761,9 @@
This watches a file system path for attribute changes. That is, it calls
C on that path in regular intervals (or when the OS says it changed)
-and sees if it changed compared to the last time, invoking the callback if
-it did.
+and sees if it changed compared to the last time, invoking the callback
+if it did. Starting the watcher C's the file, so only changes that
+happen after the watcher has been started will be reported.
The path does not need to exist: changing from "path exists" to "path does
not exist" is a status change like any other. The condition "path does not
@@ -2844,6 +3003,20 @@
"pseudo-background processing", or delay processing stuff to after the
event loop has handled all outstanding events.
+=head3 Abusing an C watcher for its side-effect
+
+As long as there is at least one active idle watcher, libev will never
+sleep unnecessarily. Or in other words, it will loop as fast as possible.
+For this to work, the idle watcher doesn't need to be invoked at all - the
+lowest priority will do.
+
+This mode of operation can be useful together with an C watcher,
+to do something on each event loop iteration - for example to balance load
+between different connections.
+
+See L for a longer
+example.
+
=head3 Watcher-Specific Functions and Data Members
=over 4
@@ -2864,7 +3037,12 @@
static void
idle_cb (struct ev_loop *loop, ev_idle *w, int revents)
{
+ // stop the watcher
+ ev_idle_stop (loop, w);
+
+ // now we can free it
free (w);
+
// now do something you wanted to do when the program has
// no longer anything immediate to do.
}
@@ -2876,17 +3054,17 @@
=head2 C and C - customise your event loop!
-Prepare and check watchers are usually (but not always) used in pairs:
+Prepare and check watchers are often (but not always) used in pairs:
prepare watchers get invoked before the process blocks and check watchers
afterwards.
-You I call C or similar functions that enter
-the current event loop from either C or C
-watchers. Other loops than the current one are fine, however. The
-rationale behind this is that you do not need to check for recursion in
-those watchers, i.e. the sequence will always be C, blocking,
-C so if you have one watcher of each kind they will always be
-called in pairs bracketing the blocking call.
+You I call C (or similar functions that enter the
+current event loop) or C from either C or
+C watchers. Other loops than the current one are fine,
+however. The rationale behind this is that you do not need to check
+for recursion in those watchers, i.e. the sequence will always be
+C, blocking, C so if you have one watcher of each
+kind they will always be called in pairs bracketing the blocking call.
Their main purpose is to integrate other event mechanisms into libev and
their use is somewhat advanced. They could be used, for example, to track
@@ -2914,9 +3092,10 @@
loop from blocking if lower-priority coroutines are active, thus mapping
low-priority coroutines to idle/background tasks).
-It is recommended to give C watchers highest (C)
-priority, to ensure that they are being run before any other watchers
-after the poll (this doesn't matter for C watchers).
+When used for this purpose, it is recommended to give C watchers
+highest (C) priority, to ensure that they are being run before
+any other watchers after the poll (this doesn't matter for C
+watchers).
Also, C watchers (and C watchers, too) should not
activate ("feed") events into libev. While libev fully supports this, they
@@ -2926,6 +3105,25 @@
C watcher ran (always remind yourself to coexist peacefully with
others).
+=head3 Abusing an C watcher for its side-effect
+
+C (and less often also C) watchers can also be
+useful because they are called once per event loop iteration. For
+example, if you want to handle a large number of connections fairly, you
+normally only do a bit of work for each active connection, and if there
+is more work to do, you wait for the next event loop iteration, so other
+connections have a chance of making progress.
+
+Using an C watcher is almost enough: it will be called on the
+next event loop iteration. However, that isn't as soon as possible -
+without external events, your C watcher will not be invoked.
+
+This is where C watchers come in handy - all you need is a
+single global idle watcher that is active as long as you have one active
+C watcher. The C watcher makes sure the event loop
+will not sleep, and the C watcher makes sure a callback gets
+invoked. Neither watcher alone can do that.
+
=head3 Watcher-Specific Functions and Data Members
=over 4
@@ -3135,7 +3333,7 @@
=item ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)
-=item ev_embed_set (ev_embed *, callback, struct ev_loop *embedded_loop)
+=item ev_embed_set (ev_embed *, struct ev_loop *embedded_loop)
Configures the watcher to embed the given loop, which must be
embeddable. If the callback is C<0>, then C will be
@@ -3166,7 +3364,7 @@
struct ev_loop *loop_hi = ev_default_init (0);
struct ev_loop *loop_lo = 0;
ev_embed embed;
-
+
// see if there is a chance of getting one that works
// (remember that a flags value of 0 means autodetection)
loop_lo = ev_embeddable_backends () & ev_recommended_backends ()
@@ -3190,7 +3388,7 @@
struct ev_loop *loop = ev_default_init (0);
struct ev_loop *loop_socket = 0;
ev_embed embed;
-
+
if (ev_supported_backends () & ~ev_recommended_backends () & EVBACKEND_KQUEUE)
if ((loop_socket = ev_loop_new (EVBACKEND_KQUEUE))
{
@@ -3208,15 +3406,15 @@
Fork watchers are called when a C was detected (usually because
whoever is a good citizen cared to tell libev about it by calling
-C or C). The invocation is done before the
-event loop blocks next and before C watchers are being called,
-and only in the child after the fork. If whoever good citizen calling
-C cheats and calls it in the wrong process, the fork
-handlers will be invoked, too, of course.
+C). The invocation is done before the event loop blocks next
+and before C watchers are being called, and only in the child
+after the fork. If whoever good citizen calling C cheats
+and calls it in the wrong process, the fork handlers will be invoked, too,
+of course.
=head3 The special problem of life after fork - how is it possible?
-Most uses of C consist of forking, then some simple calls to set
+Most uses of C consist of forking, then some simple calls to set
up/change the process environment, followed by a call to C. This
sequence should be handled by libev without any problems.
@@ -3464,7 +3662,7 @@
=over 4
-=item ev_once (loop, int fd, int events, ev_tstamp timeout, callback)
+=item ev_once (loop, int fd, int events, ev_tstamp timeout, callback, arg)
This function combines a simple timer and an I/O watcher, calls your
callback on whichever event happens first and automatically stops both
@@ -3616,9 +3814,9 @@
A common way around all these issues is to make sure that
C I returns before the callback is invoked. If
C immediately knows the result, it can artificially
-delay invoking the callback by e.g. using a C or C watcher
-for example, or more sneakily, by reusing an existing (stopped) watcher
-and pushing it into the pending queue:
+delay invoking the callback by using a C or C watcher for
+example, or more sneakily, by reusing an existing (stopped) watcher and
+pushing it into the pending queue:
ev_set_cb (watcher, callback);
ev_feed_event (EV_A_ watcher, 0);
@@ -3636,7 +3834,7 @@
main C call, but not the nested one (e.g. user clicked "Quit", but
a modal "Are you sure?" dialog is still waiting), or just the nested one
and not the main one (e.g. user clocked "Ok" in a modal dialog), or some
-other combination: In these cases, C will not work alone.
+other combination: In these cases, a simple C will not work.
The solution is to maintain "break this loop" variable for each C
invocation, and use a loop around C until the condition is
@@ -3682,10 +3880,10 @@
First, you need to associate some data with the event loop:
typedef struct {
- mutex_t lock; /* global loop lock */
+ pthread_mutex_t lock; /* global loop lock */
+ pthread_t tid;
+ pthread_cond_t invoke_cv;
ev_async async_w;
- thread_t tid;
- cond_t invoke_cv;
} userdata;
void prepare_loop (EV_P)
@@ -3693,19 +3891,19 @@
// 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);
+ 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);
+ 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_userdata (EV_A_ &u);
ev_set_invoke_pending_cb (EV_A_ l_invoke);
ev_set_loop_release_cb (EV_A_ l_release, l_acquire);
// then create the thread running ev_run
- pthread_create (&u->tid, 0, l_run, EV_A);
+ pthread_create (&u.tid, 0, l_run, EV_A);
}
The callback for the C watcher does nothing: the watcher is used
@@ -3832,7 +4030,7 @@
void
wait_for_event (ev_watcher *w)
{
- ev_cb_set (w) = current_coro;
+ ev_set_cb (w, current_coro);
switch_to (libev_coro);
}
@@ -3845,12 +4043,12 @@
switching to a coroutine, you push the watcher onto the queue and notify
any waiters.
-To embed libev, see L, but in short, it's easiest to create two
+To embed libev, see L , but in short, it's easiest to create two
files, F and F that include the respective libev files:
// my_ev.h
#define EV_CB_DECLARE(type) struct my_coro *cb;
- #define EV_CB_INVOKE(watcher) switch_to ((watcher)->cb);
+ #define EV_CB_INVOKE(watcher) switch_to ((watcher)->cb)
#include "../libev/ev.h"
// my_ev.c
@@ -3906,14 +4104,14 @@
will work fine.
Proper exception specifications might have to be added to callbacks passed
-to libev: exceptions may be thrown only from watcher callbacks, all
-other callbacks (allocator, syserr, loop acquire/release and periodioc
-reschedule callbacks) must not throw exceptions, and might need a C specification. If you have code that needs to be compiled as both C
-and C++ you can use the C macro for this:
+to libev: exceptions may be thrown only from watcher callbacks, all other
+callbacks (allocator, syserr, loop acquire/release and periodic reschedule
+callbacks) must not throw exceptions, and might need a C
+specification. If you have code that needs to be compiled as both C and
+C++ you can use the C macro for this:
static void
- fatal_error (const char *msg) EV_THROW
+ fatal_error (const char *msg) EV_NOEXCEPT
{
perror (msg);
abort ();
@@ -3937,7 +4135,7 @@
the callback model to a model using method callbacks on objects.
To use it,
-
+
#include
This automatically includes F and puts all of its definitions (many
@@ -4050,7 +4248,7 @@
...
}
}
-
+
myfunctor f;
ev::io w;
@@ -4078,10 +4276,17 @@
=item w->set ([arguments])
-Basically the same as C, with the same arguments. Either this
-method or a suitable start method must be called at least once. Unlike the
-C counterpart, an active watcher gets automatically stopped and restarted
-when reconfiguring it with this method.
+Basically the same as C (except for C watchers>),
+with the same arguments. Either this method or a suitable start method
+must be called at least once. Unlike the C counterpart, an active watcher
+gets automatically stopped and restarted when reconfiguring it with this
+method.
+
+For C watchers this method is called C, to avoid
+clashing with the C method.
+
+For C watchers there is an additional C method that acepts a
+new event mask only, and internally calls C.
=item w->start ()
@@ -4195,6 +4400,14 @@
time of this writing, only C and C), to be found at
L.
+=item Javascript
+
+Node.js (L) uses libev as the underlying event library.
+
+=item Others
+
+There are others, and I stopped counting.
+
=back
@@ -4321,11 +4534,13 @@
ev_win32.c required on win32 platforms only
- ev_select.c only when select backend is enabled (which is enabled by default)
- ev_poll.c only when poll backend is enabled (disabled by default)
- ev_epoll.c only when the epoll backend is enabled (disabled by default)
- ev_kqueue.c only when the kqueue backend is enabled (disabled by default)
- ev_port.c only when the solaris port backend is enabled (disabled by default)
+ ev_select.c only when select backend is enabled
+ ev_poll.c only when poll backend is enabled
+ ev_epoll.c only when the epoll backend is enabled
+ ev_linuxaio.c only when the linux aio backend is enabled
+ ev_iouring.c only when the linux io_uring backend is enabled
+ ev_kqueue.c only when the kqueue backend is enabled
+ ev_port.c only when the solaris port backend is enabled
F