summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ev.pod165
1 files changed, 83 insertions, 82 deletions
diff --git a/ev.pod b/ev.pod
index 39ac2a2..284c645 100644
--- a/ev.pod
+++ b/ev.pod
@@ -2386,8 +2386,8 @@ queue:
=item queueing from a signal handler context
To implement race-free queueing, you simply add to the queue in the signal
-handler but you block the signal handler in the watcher callback. Here is an example that does that for
-some fictitious SIGUSR1 handler:
+handler but you block the signal handler in the watcher callback. Here is
+an example that does that for some fictitious SIGUSR1 handler:
static ev_async mysig;
@@ -3315,11 +3315,11 @@ And a F<ev_cpp.C> implementation file that contains libev proper and is compiled
=head3 THREADS
All libev functions are reentrant and thread-safe unless explicitly
-documented otherwise, but it uses no locking itself. This means that you
-can use as many loops as you want in parallel, as long as there are no
-concurrent calls into any libev function with the same loop parameter
-(C<ev_default_*> calls have an implicit default loop parameter, of
-course): libev guarantees that different event loops share no data
+documented otherwise, but libev implements no locking itself. This means
+that you can use as many loops as you want in parallel, as long as there
+are no concurrent calls into any libev function with the same loop
+parameter (C<ev_default_*> calls have an implicit default loop parameter,
+of course): libev guarantees that different event loops share no data
structures that need any locking.
Or to put it differently: calls with different loop parameters can be done
@@ -3371,15 +3371,16 @@ watcher callback into the event loop interested in the signal.
=head3 COROUTINES
-Libev is much more accommodating to coroutines ("cooperative threads"):
-libev fully supports nesting calls to it's functions from different
+Libev is very accommodating to coroutines ("cooperative threads"):
+libev fully supports nesting calls to its functions from different
coroutines (e.g. you can call C<ev_loop> on the same loop from two
-different coroutines and switch freely between both coroutines running the
+different coroutines, and switch freely between both coroutines running the
loop, as long as you don't confuse yourself). The only exception is that
you must not do this from C<ev_periodic> reschedule callbacks.
Care has been taken to ensure that libev does not keep local state inside
-C<ev_loop>, and other calls do not usually allow coroutine switches.
+C<ev_loop>, and other calls do not usually allow for coroutine switches as
+they do not clal any callbacks.
=head2 COMPILER WARNINGS
@@ -3443,77 +3444,6 @@ If you need, for some reason, empty reports from valgrind for your project
I suggest using suppression lists.
-
-=head1 COMPLEXITIES
-
-In this section the complexities of (many of) the algorithms used inside
-libev will be explained. For complexity discussions about backends see the
-documentation for C<ev_default_init>.
-
-All of the following are about amortised time: If an array needs to be
-extended, libev needs to realloc and move the whole array, but this
-happens asymptotically never with higher number of elements, so O(1) might
-mean it might do a lengthy realloc operation in rare cases, but on average
-it is much faster and asymptotically approaches constant time.
-
-=over 4
-
-=item Starting and stopping timer/periodic watchers: O(log skipped_other_timers)
-
-This means that, when you have a watcher that triggers in one hour and
-there are 100 watchers that would trigger before that then inserting will
-have to skip roughly seven (C<ld 100>) of these watchers.
-
-=item Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers)
-
-That means that changing a timer costs less than removing/adding them
-as only the relative motion in the event queue has to be paid for.
-
-=item Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1)
-
-These just add the watcher into an array or at the head of a list.
-
-=item Stopping check/prepare/idle/fork/async watchers: O(1)
-
-=item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE))
-
-These watchers are stored in lists then need to be walked to find the
-correct watcher to remove. The lists are usually short (you don't usually
-have many watchers waiting for the same fd or signal).
-
-=item Finding the next timer in each loop iteration: O(1)
-
-By virtue of using a binary or 4-heap, the next timer is always found at a
-fixed position in the storage array.
-
-=item Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)
-
-A change means an I/O watcher gets started or stopped, which requires
-libev to recalculate its status (and possibly tell the kernel, depending
-on backend and whether C<ev_io_set> was used).
-
-=item Activating one watcher (putting it into the pending state): O(1)
-
-=item Priority handling: O(number_of_priorities)
-
-Priorities are implemented by allocating some space for each
-priority. When doing priority-based operations, libev usually has to
-linearly search all the priorities, but starting/stopping and activating
-watchers becomes O(1) with respect to priority handling.
-
-=item Sending an ev_async: O(1)
-
-=item Processing ev_async_send: O(number_of_async_watchers)
-
-=item Processing signals: O(max_signal_number)
-
-Sending involves a system call I<iff> there were no other C<ev_async_send>
-calls in the current loop iteration. Checking for async and signal events
-involves iterating over all running async watchers or all signal numbers.
-
-=back
-
-
=head1 PORTABILITY NOTES
=head2 WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS
@@ -3669,6 +3599,77 @@ implementations implementing IEEE 754 (basically all existing ones).
If you know of other additional requirements drop me a note.
+=head1 ALGORITHMIC COMPLEXITIES
+
+In this section the complexities of (many of) the algorithms used inside
+libev will be documented. For complexity discussions about backends see
+the documentation for C<ev_default_init>.
+
+All of the following are about amortised time: If an array needs to be
+extended, libev needs to realloc and move the whole array, but this
+happens asymptotically rarer with higher number of elements, so O(1) might
+mean that libev does a lengthy realloc operation in rare cases, but on
+average it is much faster and asymptotically approaches constant time.
+
+=over 4
+
+=item Starting and stopping timer/periodic watchers: O(log skipped_other_timers)
+
+This means that, when you have a watcher that triggers in one hour and
+there are 100 watchers that would trigger before that, then inserting will
+have to skip roughly seven (C<ld 100>) of these watchers.
+
+=item Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers)
+
+That means that changing a timer costs less than removing/adding them,
+as only the relative motion in the event queue has to be paid for.
+
+=item Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1)
+
+These just add the watcher into an array or at the head of a list.
+
+=item Stopping check/prepare/idle/fork/async watchers: O(1)
+
+=item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE))
+
+These watchers are stored in lists, so they need to be walked to find the
+correct watcher to remove. The lists are usually short (you don't usually
+have many watchers waiting for the same fd or signal: one is typical, two
+is rare).
+
+=item Finding the next timer in each loop iteration: O(1)
+
+By virtue of using a binary or 4-heap, the next timer is always found at a
+fixed position in the storage array.
+
+=item Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)
+
+A change means an I/O watcher gets started or stopped, which requires
+libev to recalculate its status (and possibly tell the kernel, depending
+on backend and whether C<ev_io_set> was used).
+
+=item Activating one watcher (putting it into the pending state): O(1)
+
+=item Priority handling: O(number_of_priorities)
+
+Priorities are implemented by allocating some space for each
+priority. When doing priority-based operations, libev usually has to
+linearly search all the priorities, but starting/stopping and activating
+watchers becomes O(1) with respect to priority handling.
+
+=item Sending an ev_async: O(1)
+
+=item Processing ev_async_send: O(number_of_async_watchers)
+
+=item Processing signals: O(max_signal_number)
+
+Sending involves a system call I<iff> there were no other C<ev_async_send>
+calls in the current loop iteration. Checking for async and signal events
+involves iterating over all running async watchers or all signal numbers.
+
+=back
+
+
=head1 AUTHOR
Marc Lehmann <libev@schmorp.de>.