mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Upgrade libev to 3.7
This commit is contained in:
25
deps/libev/Changes
vendored
25
deps/libev/Changes
vendored
@@ -1,5 +1,30 @@
|
||||
Revision history for libev, a high-performance and full-featured event loop.
|
||||
|
||||
3.7 Fri Jul 17 16:36:32 CEST 2009
|
||||
- ev_unloop and ev_loop wrongly used a global variable to exit loops,
|
||||
instead of using a per-loop variable (bug caught by accident...).
|
||||
- the ev_set_io_collect_interval interpretation has changed.
|
||||
- add new functionality: ev_set_userdata, ev_userdata,
|
||||
ev_set_invoke_pending_cb, ev_set_loop_release_cb,
|
||||
ev_invoke_pending, together with a long example about thread
|
||||
locking.
|
||||
- add ev_timer_remaining (as requested by Denis F. Latypoff).
|
||||
- add ev_loop_depth.
|
||||
- calling ev_unloop in fork/prepare watchers will no longer poll
|
||||
for new events.
|
||||
- Denis F. Latypoff corrected many typos in example code snippets.
|
||||
- honor autoconf detection of EV_USE_CLOCK_SYSCALL, also double-
|
||||
check that the syscall number is available before trying to
|
||||
use it (reported by ry@tinyclouds).
|
||||
- use GetSystemTimeAsFileTime instead of _timeb on windows, for
|
||||
slightly higher accuracy.
|
||||
- properly declare ev_loop_verify and ev_now_update even when
|
||||
!EV_MULTIPLICITY.
|
||||
- do not compile in any priority code when EV_MAXPRI == EV_MINPRI.
|
||||
- support EV_MINIMAL==2 for a reduced API.
|
||||
- actually 0-initialise struct sigaction when installing signals.
|
||||
- add section on hibernate and stopped processes to ev_timer docs.
|
||||
|
||||
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.
|
||||
|
||||
51
deps/libev/configure
vendored
51
deps/libev/configure
vendored
@@ -2207,7 +2207,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=libev
|
||||
VERSION=3.6
|
||||
VERSION=3.7
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@@ -2348,8 +2348,7 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
|
||||
# some platforms.
|
||||
|
||||
|
||||
|
||||
ac_config_headers="$ac_config_headers config.h"
|
||||
ac_config_headers="$ac_config_headers config.h"
|
||||
|
||||
{ echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
|
||||
echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6; }
|
||||
@@ -4350,7 +4349,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 4353 "configure"' > conftest.$ac_ext
|
||||
echo '#line 4352 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -7396,11 +7395,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7399: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7398: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7403: \$? = $ac_status" >&5
|
||||
echo "$as_me:7402: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7686,11 +7685,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7689: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7688: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7693: \$? = $ac_status" >&5
|
||||
echo "$as_me:7692: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7790,11 +7789,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7793: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7792: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7797: \$? = $ac_status" >&5
|
||||
echo "$as_me:7796: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -10167,7 +10166,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 10170 "configure"
|
||||
#line 10169 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -10267,7 +10266,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 10270 "configure"
|
||||
#line 10269 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -12668,11 +12667,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:12671: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:12670: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:12675: \$? = $ac_status" >&5
|
||||
echo "$as_me:12674: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -12772,11 +12771,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:12775: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:12774: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:12779: \$? = $ac_status" >&5
|
||||
echo "$as_me:12778: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -14370,11 +14369,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:14373: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:14372: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:14377: \$? = $ac_status" >&5
|
||||
echo "$as_me:14376: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -14474,11 +14473,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:14477: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:14476: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:14481: \$? = $ac_status" >&5
|
||||
echo "$as_me:14480: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -16694,11 +16693,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:16697: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:16696: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:16701: \$? = $ac_status" >&5
|
||||
echo "$as_me:16700: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -16984,11 +16983,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:16987: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:16986: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:16991: \$? = $ac_status" >&5
|
||||
echo "$as_me:16990: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -17088,11 +17087,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:17091: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:17090: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:17095: \$? = $ac_status" >&5
|
||||
echo "$as_me:17094: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
|
||||
2
deps/libev/configure.ac
vendored
2
deps/libev/configure.ac
vendored
@@ -1,7 +1,7 @@
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([ev_epoll.c])
|
||||
|
||||
AM_INIT_AUTOMAKE(libev,3.6)
|
||||
AM_INIT_AUTOMAKE(libev,3.7) dnl also update ev.h!
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
|
||||
17
deps/libev/ev++.h
vendored
17
deps/libev/ev++.h
vendored
@@ -207,11 +207,6 @@ namespace ev {
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int count () const throw ()
|
||||
{
|
||||
return ev_loop_count (EV_AX);
|
||||
}
|
||||
|
||||
unsigned int backend () const throw ()
|
||||
{
|
||||
return ev_backend (EV_AX);
|
||||
@@ -232,6 +227,17 @@ namespace ev {
|
||||
ev_unref (EV_AX);
|
||||
}
|
||||
|
||||
#if EV_MINIMAL < 2
|
||||
unsigned int count () const throw ()
|
||||
{
|
||||
return ev_loop_count (EV_AX);
|
||||
}
|
||||
|
||||
unsigned int depth () const throw ()
|
||||
{
|
||||
return ev_loop_depth (EV_AX);
|
||||
}
|
||||
|
||||
void set_io_collect_interval (tstamp interval) throw ()
|
||||
{
|
||||
ev_set_io_collect_interval (EV_AX_ interval);
|
||||
@@ -241,6 +247,7 @@ namespace ev {
|
||||
{
|
||||
ev_set_timeout_collect_interval (EV_AX_ interval);
|
||||
}
|
||||
#endif
|
||||
|
||||
// function callback
|
||||
void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw ()
|
||||
|
||||
448
deps/libev/ev.3
vendored
448
deps/libev/ev.3
vendored
@@ -1,15 +1,7 @@
|
||||
.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05)
|
||||
.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07)
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
.de Sh \" Subsection heading
|
||||
.br
|
||||
.if t .Sp
|
||||
.ne 5
|
||||
.PP
|
||||
\fB\\$1\fR
|
||||
.PP
|
||||
..
|
||||
.de Sp \" Vertical space (when we can't use .PP)
|
||||
.if t .sp .5v
|
||||
.if n .sp
|
||||
@@ -53,7 +45,7 @@
|
||||
.el .ds Aq '
|
||||
.\"
|
||||
.\" If the F register is turned on, we'll generate index entries on stderr for
|
||||
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
|
||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||
.\" output yourself in some meaningful fashion.
|
||||
.ie \nF \{\
|
||||
@@ -132,7 +124,7 @@
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "LIBEV 3"
|
||||
.TH LIBEV 3 "2009-04-25" "libev-3.6" "libev - high performance full featured event loop"
|
||||
.TH LIBEV 3 "2009-07-15" "libev-3.7" "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
|
||||
@@ -144,7 +136,7 @@ libev \- a high performance full\-featured event loop written in C
|
||||
.Vb 1
|
||||
\& #include <ev.h>
|
||||
.Ve
|
||||
.Sh "\s-1EXAMPLE\s0 \s-1PROGRAM\s0"
|
||||
.SS "\s-1EXAMPLE\s0 \s-1PROGRAM\s0"
|
||||
.IX Subsection "EXAMPLE PROGRAM"
|
||||
.Vb 2
|
||||
\& // a single header file is required
|
||||
@@ -232,7 +224,7 @@ You register interest in certain events by registering so-called \fIevent
|
||||
watchers\fR, which are relatively small C structures you initialise with the
|
||||
details of the event, and then hand it over to libev by \fIstarting\fR the
|
||||
watcher.
|
||||
.Sh "\s-1FEATURES\s0"
|
||||
.SS "\s-1FEATURES\s0"
|
||||
.IX Subsection "FEATURES"
|
||||
Libev supports \f(CW\*(C`select\*(C'\fR, \f(CW\*(C`poll\*(C'\fR, the Linux-specific \f(CW\*(C`epoll\*(C'\fR, the
|
||||
BSD-specific \f(CW\*(C`kqueue\*(C'\fR and the Solaris-specific event port mechanisms
|
||||
@@ -246,9 +238,9 @@ file watchers (\f(CW\*(C`ev_stat\*(C'\fR) and even limited support for fork even
|
||||
(\f(CW\*(C`ev_fork\*(C'\fR).
|
||||
.PP
|
||||
It also is quite fast (see this
|
||||
benchmark comparing it to libevent
|
||||
<benchmark> comparing it to libevent
|
||||
for example).
|
||||
.Sh "\s-1CONVENTIONS\s0"
|
||||
.SS "\s-1CONVENTIONS\s0"
|
||||
.IX Subsection "CONVENTIONS"
|
||||
Libev is very configurable. In this manual the default (and most common)
|
||||
configuration will be described, which supports multiple event loops. For
|
||||
@@ -257,7 +249,7 @@ more info about various configuration options please have a look at
|
||||
for multiple event loops, then all functions taking an initial argument of
|
||||
name \f(CW\*(C`loop\*(C'\fR (which is always of type \f(CW\*(C`ev_loop *\*(C'\fR) will not have
|
||||
this argument.
|
||||
.Sh "\s-1TIME\s0 \s-1REPRESENTATION\s0"
|
||||
.SS "\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
|
||||
@@ -751,6 +743,17 @@ happily wraps around with enough iterations.
|
||||
This value can sometimes be useful as a generation counter of sorts (it
|
||||
\&\*(L"ticks\*(R" the number of loop iterations), as it roughly corresponds with
|
||||
\&\f(CW\*(C`ev_prepare\*(C'\fR and \f(CW\*(C`ev_check\*(C'\fR calls.
|
||||
.IP "unsigned int ev_loop_depth (loop)" 4
|
||||
.IX Item "unsigned int ev_loop_depth (loop)"
|
||||
Returns the number of times \f(CW\*(C`ev_loop\*(C'\fR was entered minus the number of
|
||||
times \f(CW\*(C`ev_loop\*(C'\fR was exited, in other words, the recursion depth.
|
||||
.Sp
|
||||
Outside \f(CW\*(C`ev_loop\*(C'\fR, this number is zero. In a callback, this number is
|
||||
\&\f(CW1\fR, unless \f(CW\*(C`ev_loop\*(C'\fR was invoked recursively (or from another thread),
|
||||
in which case it is higher.
|
||||
.Sp
|
||||
Leaving \f(CW\*(C`ev_loop\*(C'\fR abnormally (setjmp/longjmp, cancelling the thread
|
||||
etc.), doesn't count as exit.
|
||||
.IP "unsigned int ev_backend (loop)" 4
|
||||
.IX Item "unsigned int ev_backend (loop)"
|
||||
Returns one of the \f(CW\*(C`EVBACKEND_*\*(C'\fR flags indicating the event backend in
|
||||
@@ -948,7 +951,9 @@ By setting a higher \fIio collect interval\fR you allow libev to spend more
|
||||
time collecting I/O events, so you can handle more events per iteration,
|
||||
at the cost of increasing latency. Timeouts (both \f(CW\*(C`ev_periodic\*(C'\fR and
|
||||
\&\f(CW\*(C`ev_timer\*(C'\fR) will be not affected. Setting this to a non-null value will
|
||||
introduce an additional \f(CW\*(C`ev_sleep ()\*(C'\fR call into most loop iterations.
|
||||
introduce an additional \f(CW\*(C`ev_sleep ()\*(C'\fR call into most loop iterations. The
|
||||
sleep time ensures that libev will not poll for I/O events more often then
|
||||
once per this interval, on average.
|
||||
.Sp
|
||||
Likewise, by setting a higher \fItimeout collect interval\fR you allow libev
|
||||
to spend more time collecting timeouts, at the expense of increased
|
||||
@@ -960,7 +965,11 @@ Many (busy) programs can usually benefit by setting the I/O collect
|
||||
interval to a value near \f(CW0.1\fR or so, which is often enough for
|
||||
interactive servers (of course not for games), likewise for timeouts. It
|
||||
usually doesn't make much sense to set it to a lower value than \f(CW0.01\fR,
|
||||
as this approaches the timing granularity of most systems.
|
||||
as this approaches the timing granularity of most systems. Note that if
|
||||
you do transactions with the outside world and you can't increase the
|
||||
parallelity, then this setting will limit your transaction rate (if you
|
||||
need to poll once per transaction and the I/O collect interval is 0.01,
|
||||
then you can't do more than 100 transations per second).
|
||||
.Sp
|
||||
Setting the \fItimeout collect interval\fR can improve the opportunity for
|
||||
saving power, as the program will \*(L"bundle\*(R" timer callback invocations that
|
||||
@@ -968,6 +977,76 @@ are \*(L"near\*(R" in time together, by delaying some, thus reducing the number
|
||||
times the process sleeps and wakes up again. Another useful technique to
|
||||
reduce iterations/wake\-ups is to use \f(CW\*(C`ev_periodic\*(C'\fR watchers and make sure
|
||||
they fire on, say, one-second boundaries only.
|
||||
.Sp
|
||||
Example: we only need 0.1s timeout granularity, and we wish not to poll
|
||||
more often than 100 times per second:
|
||||
.Sp
|
||||
.Vb 2
|
||||
\& ev_set_timeout_collect_interval (EV_DEFAULT_UC_ 0.1);
|
||||
\& ev_set_io_collect_interval (EV_DEFAULT_UC_ 0.01);
|
||||
.Ve
|
||||
.IP "ev_invoke_pending (loop)" 4
|
||||
.IX Item "ev_invoke_pending (loop)"
|
||||
This call will simply invoke all pending watchers while resetting their
|
||||
pending state. Normally, \f(CW\*(C`ev_loop\*(C'\fR does this automatically when required,
|
||||
but when overriding the invoke callback this call comes handy.
|
||||
.IP "int ev_pending_count (loop)" 4
|
||||
.IX Item "int ev_pending_count (loop)"
|
||||
Returns the number of pending watchers \- zero indicates that no watchers
|
||||
are pending.
|
||||
.IP "ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(\s-1EV_P\s0))" 4
|
||||
.IX Item "ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(EV_P))"
|
||||
This overrides the invoke pending functionality of the loop: Instead of
|
||||
invoking all pending watchers when there are any, \f(CW\*(C`ev_loop\*(C'\fR will call
|
||||
this callback instead. This is useful, for example, when you want to
|
||||
invoke the actual watchers inside another context (another thread etc.).
|
||||
.Sp
|
||||
If you want to reset the callback, use \f(CW\*(C`ev_invoke_pending\*(C'\fR as new
|
||||
callback.
|
||||
.IP "ev_set_loop_release_cb (loop, void (*release)(\s-1EV_P\s0), void (*acquire)(\s-1EV_P\s0))" 4
|
||||
.IX Item "ev_set_loop_release_cb (loop, void (*release)(EV_P), void (*acquire)(EV_P))"
|
||||
Sometimes you want to share the same loop between multiple threads. This
|
||||
can be done relatively simply by putting mutex_lock/unlock calls around
|
||||
each call to a libev function.
|
||||
.Sp
|
||||
However, \f(CW\*(C`ev_loop\*(C'\fR can run an indefinite time, so it is not feasible to
|
||||
wait for it to return. One way around this is to wake up the loop via
|
||||
\&\f(CW\*(C`ev_unloop\*(C'\fR and \f(CW\*(C`av_async_send\*(C'\fR, another way is to set these \fIrelease\fR
|
||||
and \fIacquire\fR callbacks on the loop.
|
||||
.Sp
|
||||
When set, then \f(CW\*(C`release\*(C'\fR will be called just before the thread is
|
||||
suspended waiting for new events, and \f(CW\*(C`acquire\*(C'\fR is called just
|
||||
afterwards.
|
||||
.Sp
|
||||
Ideally, \f(CW\*(C`release\*(C'\fR will just call your mutex_unlock function, and
|
||||
\&\f(CW\*(C`acquire\*(C'\fR will just call the mutex_lock function again.
|
||||
.Sp
|
||||
While event loop modifications are allowed between invocations of
|
||||
\&\f(CW\*(C`release\*(C'\fR and \f(CW\*(C`acquire\*(C'\fR (that's their only purpose after all), no
|
||||
modifications done will affect the event loop, i.e. adding watchers will
|
||||
have no effect on the set of file descriptors being watched, or the time
|
||||
waited. USe an \f(CW\*(C`ev_async\*(C'\fR watcher to wake up \f(CW\*(C`ev_loop\*(C'\fR when you want it
|
||||
to take note of any changes you made.
|
||||
.Sp
|
||||
In theory, threads executing \f(CW\*(C`ev_loop\*(C'\fR will be async-cancel safe between
|
||||
invocations of \f(CW\*(C`release\*(C'\fR and \f(CW\*(C`acquire\*(C'\fR.
|
||||
.Sp
|
||||
See also the locking example in the \f(CW\*(C`THREADS\*(C'\fR section later in this
|
||||
document.
|
||||
.IP "ev_set_userdata (loop, void *data)" 4
|
||||
.IX Item "ev_set_userdata (loop, void *data)"
|
||||
.PD 0
|
||||
.IP "ev_userdata (loop)" 4
|
||||
.IX Item "ev_userdata (loop)"
|
||||
.PD
|
||||
Set and retrieve a single \f(CW\*(C`void *\*(C'\fR associated with a loop. When
|
||||
\&\f(CW\*(C`ev_set_userdata\*(C'\fR has never been called, then \f(CW\*(C`ev_userdata\*(C'\fR returns
|
||||
\&\f(CW0.\fR
|
||||
.Sp
|
||||
These two functions can be used to associate arbitrary data with a loop,
|
||||
and are intended solely for the \f(CW\*(C`invoke_pending_cb\*(C'\fR, \f(CW\*(C`release\*(C'\fR and
|
||||
\&\f(CW\*(C`acquire\*(C'\fR callbacks described above, but of course can be (ab\-)used for
|
||||
any other purpose as well.
|
||||
.IP "ev_loop_verify (loop)" 4
|
||||
.IX Item "ev_loop_verify (loop)"
|
||||
This function only does something when \f(CW\*(C`EV_VERIFY\*(C'\fR support has been
|
||||
@@ -1126,7 +1205,7 @@ callbacks is well-written it can just attempt the operation and cope with
|
||||
the error from \fIread()\fR or \fIwrite()\fR. This will not work in multi-threaded
|
||||
programs, though, as the fd could already be closed and reused for another
|
||||
thing, so beware.
|
||||
.Sh "\s-1GENERIC\s0 \s-1WATCHER\s0 \s-1FUNCTIONS\s0"
|
||||
.SS "\s-1GENERIC\s0 \s-1WATCHER\s0 \s-1FUNCTIONS\s0"
|
||||
.IX Subsection "GENERIC WATCHER FUNCTIONS"
|
||||
.ie n .IP """ev_init"" (ev_TYPE *watcher, callback)" 4
|
||||
.el .IP "\f(CWev_init\fR (ev_TYPE *watcher, callback)" 4
|
||||
@@ -1260,7 +1339,7 @@ watcher isn't pending it does nothing and returns \f(CW0\fR.
|
||||
.Sp
|
||||
Sometimes it can be useful to \*(L"poll\*(R" a watcher instead of waiting for its
|
||||
callback to be invoked, which can be accomplished with this function.
|
||||
.Sh "\s-1ASSOCIATING\s0 \s-1CUSTOM\s0 \s-1DATA\s0 \s-1WITH\s0 A \s-1WATCHER\s0"
|
||||
.SS "\s-1ASSOCIATING\s0 \s-1CUSTOM\s0 \s-1DATA\s0 \s-1WITH\s0 A \s-1WATCHER\s0"
|
||||
.IX Subsection "ASSOCIATING CUSTOM DATA WITH A WATCHER"
|
||||
Each watcher has, by default, a member \f(CW\*(C`void *data\*(C'\fR that you can change
|
||||
and read at any time: libev will completely ignore it. This can be used
|
||||
@@ -1321,18 +1400,18 @@ programmers):
|
||||
\& static void
|
||||
\& t1_cb (EV_P_ ev_timer *w, int revents)
|
||||
\& {
|
||||
\& struct my_biggy big = (struct my_biggy *
|
||||
\& struct my_biggy big = (struct my_biggy *)
|
||||
\& (((char *)w) \- offsetof (struct my_biggy, t1));
|
||||
\& }
|
||||
\&
|
||||
\& static void
|
||||
\& t2_cb (EV_P_ ev_timer *w, int revents)
|
||||
\& {
|
||||
\& struct my_biggy big = (struct my_biggy *
|
||||
\& struct my_biggy big = (struct my_biggy *)
|
||||
\& (((char *)w) \- offsetof (struct my_biggy, t2));
|
||||
\& }
|
||||
.Ve
|
||||
.Sh "\s-1WATCHER\s0 \s-1PRIORITY\s0 \s-1MODELS\s0"
|
||||
.SS "\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
|
||||
@@ -1415,7 +1494,7 @@ other events are pending:
|
||||
\& }
|
||||
\&
|
||||
\& static void
|
||||
\& idle\-cb (EV_P_ ev_idle *w, int revents)
|
||||
\& idle_cb (EV_P_ ev_idle *w, int revents)
|
||||
\& {
|
||||
\& // actual processing
|
||||
\& read (STDIN_FILENO, ...);
|
||||
@@ -1450,8 +1529,8 @@ 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
|
||||
sensible or take immediate effect (or do anything at all), but libev will
|
||||
not crash or malfunction in any way.
|
||||
.ie n .Sh """ev_io"" \- is this file descriptor readable or writable?"
|
||||
.el .Sh "\f(CWev_io\fP \- is this file descriptor readable or writable?"
|
||||
.ie n .SS """ev_io"" \- is this file descriptor readable or writable?"
|
||||
.el .SS "\f(CWev_io\fP \- is this file descriptor readable or writable?"
|
||||
.IX Subsection "ev_io - is this file descriptor readable or writable?"
|
||||
I/O watchers check whether a file descriptor is readable or writable
|
||||
in each iteration of the event loop, or, more precisely, when reading
|
||||
@@ -1589,8 +1668,8 @@ attempt to read a whole line in the callback.
|
||||
\& ev_io_start (loop, &stdin_readable);
|
||||
\& ev_loop (loop, 0);
|
||||
.Ve
|
||||
.ie n .Sh """ev_timer"" \- relative and optionally repeating timeouts"
|
||||
.el .Sh "\f(CWev_timer\fP \- relative and optionally repeating timeouts"
|
||||
.ie n .SS """ev_timer"" \- relative and optionally repeating timeouts"
|
||||
.el .SS "\f(CWev_timer\fP \- relative and optionally repeating timeouts"
|
||||
.IX Subsection "ev_timer - relative and optionally repeating timeouts"
|
||||
Timer watchers are simple relative timers that generate an event after a
|
||||
given time, and optionally repeating in regular intervals after that.
|
||||
@@ -1605,8 +1684,8 @@ The callback is guaranteed to be invoked only \fIafter\fR its timeout has
|
||||
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).
|
||||
before ones of the same priority 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"
|
||||
@@ -1663,7 +1742,7 @@ member and \f(CW\*(C`ev_timer_again\*(C'\fR.
|
||||
At start:
|
||||
.Sp
|
||||
.Vb 3
|
||||
\& ev_timer_init (timer, callback);
|
||||
\& ev_init (timer, callback);
|
||||
\& timer\->repeat = 60.;
|
||||
\& ev_timer_again (loop, timer);
|
||||
.Ve
|
||||
@@ -1742,7 +1821,7 @@ to the current time (meaning we just have some activity :), then call the
|
||||
callback, which will \*(L"do the right thing\*(R" and start the timer:
|
||||
.Sp
|
||||
.Vb 3
|
||||
\& ev_timer_init (timer, callback);
|
||||
\& ev_init (timer, callback);
|
||||
\& last_activity = ev_now (loop);
|
||||
\& callback (loop, timer, EV_TIMEOUT);
|
||||
.Ve
|
||||
@@ -1816,6 +1895,37 @@ If the event loop is suspended for a long time, you can also force an
|
||||
update of the time returned by \f(CW\*(C`ev_now ()\*(C'\fR by calling \f(CW\*(C`ev_now_update
|
||||
()\*(C'\fR.
|
||||
.PP
|
||||
\fIThe special problems of suspended animation\fR
|
||||
.IX Subsection "The special problems of suspended animation"
|
||||
.PP
|
||||
When you leave the server world it is quite customary to hit machines that
|
||||
can suspend/hibernate \- what happens to the clocks during such a suspend?
|
||||
.PP
|
||||
Some quick tests made with a Linux 2.6.28 indicate that a suspend freezes
|
||||
all processes, while the clocks (\f(CW\*(C`times\*(C'\fR, \f(CW\*(C`CLOCK_MONOTONIC\*(C'\fR) continue
|
||||
to run until the system is suspended, but they will not advance while the
|
||||
system is suspended. That means, on resume, it will be as if the program
|
||||
was frozen for a few seconds, but the suspend time will not be counted
|
||||
towards \f(CW\*(C`ev_timer\*(C'\fR when a monotonic clock source is used. The real time
|
||||
clock advanced as expected, but if it is used as sole clocksource, then a
|
||||
long suspend would be detected as a time jump by libev, and timers would
|
||||
be adjusted accordingly.
|
||||
.PP
|
||||
I would not be surprised to see different behaviour in different between
|
||||
operating systems, \s-1OS\s0 versions or even different hardware.
|
||||
.PP
|
||||
The other form of suspend (job control, or sending a \s-1SIGSTOP\s0) will see a
|
||||
time jump in the monotonic clocks and the realtime clock. If the program
|
||||
is suspended for a very long time, and monotonic clock sources are in use,
|
||||
then you can expect \f(CW\*(C`ev_timer\*(C'\fRs to expire as the full suspension time
|
||||
will be counted towards the timers. When no monotonic clock source is in
|
||||
use, then libev will again assume a timejump and adjust accordingly.
|
||||
.PP
|
||||
It might be beneficial for this latter case to call \f(CW\*(C`ev_suspend\*(C'\fR
|
||||
and \f(CW\*(C`ev_resume\*(C'\fR in code that handles \f(CW\*(C`SIGTSTP\*(C'\fR, to at least get
|
||||
deterministic behaviour in this case (you can do nothing against
|
||||
\&\f(CW\*(C`SIGSTOP\*(C'\fR).
|
||||
.PP
|
||||
\fIWatcher-Specific Functions and Data Members\fR
|
||||
.IX Subsection "Watcher-Specific Functions and Data Members"
|
||||
.IP "ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)" 4
|
||||
@@ -1849,6 +1959,17 @@ If the timer is repeating, either start it if necessary (with the
|
||||
.Sp
|
||||
This sounds a bit complicated, see \*(L"Be smart about timeouts\*(R", above, for a
|
||||
usage example.
|
||||
.IP "ev_timer_remaining (loop, ev_timer *)" 4
|
||||
.IX Item "ev_timer_remaining (loop, ev_timer *)"
|
||||
Returns the remaining time until a timer fires. If the timer is active,
|
||||
then this time is relative to the current event loop time, otherwise it's
|
||||
the timeout value currently configured.
|
||||
.Sp
|
||||
That is, after an \f(CW\*(C`ev_timer_set (w, 5, 7)\*(C'\fR, \f(CW\*(C`ev_timer_remaining\*(C'\fR returns
|
||||
\&\f(CW5\fR. When the timer is started and one second passes, \f(CW\*(C`ev_timer_remain\*(C'\fR
|
||||
will return \f(CW4\fR. When the timer expires and is restarted, it will return
|
||||
roughly \f(CW7\fR (likely slightly less as callback invocation takes some time,
|
||||
too), and so on.
|
||||
.IP "ev_tstamp repeat [read\-write]" 4
|
||||
.IX Item "ev_tstamp repeat [read-write]"
|
||||
The current \f(CW\*(C`repeat\*(C'\fR value. Will be used each time the watcher times out
|
||||
@@ -1891,8 +2012,8 @@ inactivity.
|
||||
\& // reset the timeout to start ticking again at 10 seconds
|
||||
\& ev_timer_again (&mytimer);
|
||||
.Ve
|
||||
.ie n .Sh """ev_periodic"" \- to cron or not to cron?"
|
||||
.el .Sh "\f(CWev_periodic\fP \- to cron or not to cron?"
|
||||
.ie n .SS """ev_periodic"" \- to cron or not to cron?"
|
||||
.el .SS "\f(CWev_periodic\fP \- to cron or not to cron?"
|
||||
.IX Subsection "ev_periodic - to cron or not to cron?"
|
||||
Periodic watchers are also timers of a kind, but they are very versatile
|
||||
(and unfortunately a bit complex).
|
||||
@@ -2090,8 +2211,8 @@ Example: Call a callback every hour, starting now:
|
||||
\& fmod (ev_now (loop), 3600.), 3600., 0);
|
||||
\& ev_periodic_start (loop, &hourly_tick);
|
||||
.Ve
|
||||
.ie n .Sh """ev_signal"" \- signal me when a signal gets signalled!"
|
||||
.el .Sh "\f(CWev_signal\fP \- signal me when a signal gets signalled!"
|
||||
.ie n .SS """ev_signal"" \- signal me when a signal gets signalled!"
|
||||
.el .SS "\f(CWev_signal\fP \- signal me when a signal gets signalled!"
|
||||
.IX Subsection "ev_signal - signal me when a signal gets signalled!"
|
||||
Signal watchers will trigger an event when the process receives a specific
|
||||
signal one or more times. Even though signals are very asynchronous, libev
|
||||
@@ -2145,8 +2266,8 @@ Example: Try to exit cleanly on \s-1SIGINT\s0.
|
||||
\& ev_signal_init (&signal_watcher, sigint_cb, SIGINT);
|
||||
\& ev_signal_start (loop, &signal_watcher);
|
||||
.Ve
|
||||
.ie n .Sh """ev_child"" \- watch out for process status changes"
|
||||
.el .Sh "\f(CWev_child\fP \- watch out for process status changes"
|
||||
.ie n .SS """ev_child"" \- watch out for process status changes"
|
||||
.el .SS "\f(CWev_child\fP \- watch out for process status changes"
|
||||
.IX Subsection "ev_child - watch out for process status changes"
|
||||
Child watchers trigger when your process receives a \s-1SIGCHLD\s0 in response to
|
||||
some child status changes (most typically when a child of yours dies or
|
||||
@@ -2154,12 +2275,16 @@ exits). It is permissible to install a child watcher \fIafter\fR the child
|
||||
has been forked (which implies it might have already exited), as long
|
||||
as the event loop isn't entered (or is continued from a watcher), i.e.,
|
||||
forking and then immediately registering a watcher for the child is fine,
|
||||
but forking and registering a watcher a few event loop iterations later is
|
||||
not.
|
||||
but forking and registering a watcher a few event loop iterations later or
|
||||
in the next callback invocation is not.
|
||||
.PP
|
||||
Only the default event loop is capable of handling signals, and therefore
|
||||
you can only register child watchers in the default event loop.
|
||||
.PP
|
||||
Due to some design glitches inside libev, child watchers will always be
|
||||
handled at maximum priority (their priority is set to \f(CW\*(C`EV_MAXPRI\*(C'\fR by
|
||||
libev)
|
||||
.PP
|
||||
\fIProcess Interaction\fR
|
||||
.IX Subsection "Process Interaction"
|
||||
.PP
|
||||
@@ -2247,8 +2372,8 @@ its completion.
|
||||
\& ev_child_start (EV_DEFAULT_ &cw);
|
||||
\& }
|
||||
.Ve
|
||||
.ie n .Sh """ev_stat"" \- did the file attributes just change?"
|
||||
.el .Sh "\f(CWev_stat\fP \- did the file attributes just change?"
|
||||
.ie n .SS """ev_stat"" \- did the file attributes just change?"
|
||||
.el .SS "\f(CWev_stat\fP \- did the file attributes just change?"
|
||||
.IX Subsection "ev_stat - did the file attributes just change?"
|
||||
This watches a file system path for attribute changes. That is, it calls
|
||||
\&\f(CW\*(C`stat\*(C'\fR on that path in regular intervals (or when the \s-1OS\s0 says it changed)
|
||||
@@ -2472,8 +2597,8 @@ one might do the work both on \f(CW\*(C`ev_stat\*(C'\fR callback invocation \fIa
|
||||
\& ev_stat_start (loop, &passwd);
|
||||
\& 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..."
|
||||
.ie n .SS """ev_idle"" \- when you've got nothing better to do..."
|
||||
.el .SS "\f(CWev_idle\fP \- when you've got nothing better to do..."
|
||||
.IX Subsection "ev_idle - when you've got nothing better to do..."
|
||||
Idle watchers trigger events when no other events of the same or higher
|
||||
priority are pending (prepare, check and other idle watchers do not count
|
||||
@@ -2519,10 +2644,10 @@ callback, free it. Also, use no error checking, as usual.
|
||||
\&
|
||||
\& ev_idle *idle_watcher = malloc (sizeof (ev_idle));
|
||||
\& ev_idle_init (idle_watcher, idle_cb);
|
||||
\& ev_idle_start (loop, idle_cb);
|
||||
\& ev_idle_start (loop, idle_watcher);
|
||||
.Ve
|
||||
.ie n .Sh """ev_prepare""\fP and \f(CW""ev_check"" \- customise your event loop!"
|
||||
.el .Sh "\f(CWev_prepare\fP and \f(CWev_check\fP \- customise your event loop!"
|
||||
.ie n .SS """ev_prepare"" and ""ev_check"" \- customise your event loop!"
|
||||
.el .SS "\f(CWev_prepare\fP and \f(CWev_check\fP \- customise your event loop!"
|
||||
.IX Subsection "ev_prepare and ev_check - customise your event loop!"
|
||||
Prepare and check watchers are usually (but not always) used in pairs:
|
||||
prepare watchers get invoked before the process blocks and check watchers
|
||||
@@ -2622,7 +2747,7 @@ the callbacks for the IO/timeout watchers might not have been called yet.
|
||||
\& adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ()));
|
||||
\&
|
||||
\& /* the callback is illegal, but won\*(Aqt be called as we stop during check */
|
||||
\& ev_timer_init (&tw, 0, timeout * 1e\-3);
|
||||
\& ev_timer_init (&tw, 0, timeout * 1e\-3, 0.);
|
||||
\& ev_timer_start (loop, &tw);
|
||||
\&
|
||||
\& // create one ev_io per pollfd
|
||||
@@ -2723,8 +2848,8 @@ libglib event loop.
|
||||
\& return got_events;
|
||||
\& }
|
||||
.Ve
|
||||
.ie n .Sh """ev_embed"" \- when one backend isn't enough..."
|
||||
.el .Sh "\f(CWev_embed\fP \- when one backend isn't enough..."
|
||||
.ie n .SS """ev_embed"" \- when one backend isn't enough..."
|
||||
.el .SS "\f(CWev_embed\fP \- when one backend isn't enough..."
|
||||
.IX Subsection "ev_embed - when one backend isn't enough..."
|
||||
This is a rather advanced watcher type that lets you embed one event loop
|
||||
into another (currently only \f(CW\*(C`ev_io\*(C'\fR events are supported in the embedded
|
||||
@@ -2856,8 +2981,8 @@ kqueue implementation). Store the kqueue/socket\-only event loop in
|
||||
\&
|
||||
\& // now use loop_socket for all sockets, and loop for everything else
|
||||
.Ve
|
||||
.ie n .Sh """ev_fork"" \- the audacity to resume the event loop after a fork"
|
||||
.el .Sh "\f(CWev_fork\fP \- the audacity to resume the event loop after a fork"
|
||||
.ie n .SS """ev_fork"" \- the audacity to resume the event loop after a fork"
|
||||
.el .SS "\f(CWev_fork\fP \- the audacity to resume the event loop after a fork"
|
||||
.IX Subsection "ev_fork - the audacity to resume the event loop after a fork"
|
||||
Fork watchers are called when a \f(CW\*(C`fork ()\*(C'\fR was detected (usually because
|
||||
whoever is a good citizen cared to tell libev about it by calling
|
||||
@@ -2908,8 +3033,8 @@ also that in that case, you have to re-register any signal watchers.
|
||||
Initialises and configures the fork watcher \- it has no parameters of any
|
||||
kind. There is a \f(CW\*(C`ev_fork_set\*(C'\fR macro, but using it is utterly pointless,
|
||||
believe me.
|
||||
.ie n .Sh """ev_async"" \- how to wake up another event loop"
|
||||
.el .Sh "\f(CWev_async\fP \- how to wake up another event loop"
|
||||
.ie n .SS """ev_async"" \- how to wake up another event loop"
|
||||
.el .SS "\f(CWev_async\fP \- how to wake up another event loop"
|
||||
.IX Subsection "ev_async - how to wake up another event loop"
|
||||
In general, you cannot use an \f(CW\*(C`ev_loop\*(C'\fR from multiple threads or other
|
||||
asynchronous sources such as signal handlers (as opposed to multiple event
|
||||
@@ -3157,16 +3282,16 @@ types of functors please contact the author (preferably after implementing
|
||||
it).
|
||||
.PP
|
||||
Here is a list of things available in the \f(CW\*(C`ev\*(C'\fR namespace:
|
||||
.ie n .IP """ev::READ""\fR, \f(CW""ev::WRITE"" etc." 4
|
||||
.ie n .IP """ev::READ"", ""ev::WRITE"" etc." 4
|
||||
.el .IP "\f(CWev::READ\fR, \f(CWev::WRITE\fR etc." 4
|
||||
.IX Item "ev::READ, ev::WRITE etc."
|
||||
These are just enum values with the same values as the \f(CW\*(C`EV_READ\*(C'\fR etc.
|
||||
macros from \fIev.h\fR.
|
||||
.ie n .IP """ev::tstamp""\fR, \f(CW""ev::now""" 4
|
||||
.ie n .IP """ev::tstamp"", ""ev::now""" 4
|
||||
.el .IP "\f(CWev::tstamp\fR, \f(CWev::now\fR" 4
|
||||
.IX Item "ev::tstamp, ev::now"
|
||||
Aliases to the same types/functions as with the \f(CW\*(C`ev_\*(C'\fR prefix.
|
||||
.ie n .IP """ev::io""\fR, \f(CW""ev::timer""\fR, \f(CW""ev::periodic""\fR, \f(CW""ev::idle""\fR, \f(CW""ev::sig"" etc." 4
|
||||
.ie n .IP """ev::io"", ""ev::timer"", ""ev::periodic"", ""ev::idle"", ""ev::sig"" etc." 4
|
||||
.el .IP "\f(CWev::io\fR, \f(CWev::timer\fR, \f(CWev::periodic\fR, \f(CWev::idle\fR, \f(CWev::sig\fR etc." 4
|
||||
.IX Item "ev::io, ev::timer, ev::periodic, ev::idle, ev::sig etc."
|
||||
For each \f(CW\*(C`ev_TYPE\*(C'\fR watcher in \fIev.h\fR there is a corresponding class of
|
||||
@@ -3286,7 +3411,7 @@ constructor already stores the event loop.
|
||||
.IP "w\->stop ()" 4
|
||||
.IX Item "w->stop ()"
|
||||
Stops the watcher if it is active. Again, no \f(CW\*(C`loop\*(C'\fR argument.
|
||||
.ie n .IP "w\->again () (""ev::timer""\fR, \f(CW""ev::periodic"" only)" 4
|
||||
.ie n .IP "w\->again () (""ev::timer"", ""ev::periodic"" only)" 4
|
||||
.el .IP "w\->again () (\f(CWev::timer\fR, \f(CWev::periodic\fR only)" 4
|
||||
.IX Item "w->again () (ev::timer, ev::periodic only)"
|
||||
For \f(CW\*(C`ev::timer\*(C'\fR and \f(CW\*(C`ev::periodic\*(C'\fR, this invokes the corresponding
|
||||
@@ -3371,7 +3496,7 @@ functions and callbacks have an initial \f(CW\*(C`struct ev_loop *\*(C'\fR argum
|
||||
.PP
|
||||
To make it easier to write programs that cope with either variant, the
|
||||
following macros are defined:
|
||||
.ie n .IP """EV_A""\fR, \f(CW""EV_A_""" 4
|
||||
.ie n .IP """EV_A"", ""EV_A_""" 4
|
||||
.el .IP "\f(CWEV_A\fR, \f(CWEV_A_\fR" 4
|
||||
.IX Item "EV_A, EV_A_"
|
||||
This provides the loop \fIargument\fR for functions, if one is required (\*(L"ev
|
||||
@@ -3386,7 +3511,7 @@ loop argument\*(R"). The \f(CW\*(C`EV_A\*(C'\fR form is used when this is the so
|
||||
.Sp
|
||||
It assumes the variable \f(CW\*(C`loop\*(C'\fR of type \f(CW\*(C`struct ev_loop *\*(C'\fR is in scope,
|
||||
which is often provided by the following macro.
|
||||
.ie n .IP """EV_P""\fR, \f(CW""EV_P_""" 4
|
||||
.ie n .IP """EV_P"", ""EV_P_""" 4
|
||||
.el .IP "\f(CWEV_P\fR, \f(CWEV_P_\fR" 4
|
||||
.IX Item "EV_P, EV_P_"
|
||||
This provides the loop \fIparameter\fR for functions, if one is required (\*(L"ev
|
||||
@@ -3403,12 +3528,12 @@ loop parameter\*(R"). The \f(CW\*(C`EV_P\*(C'\fR form is used when this is the s
|
||||
.Sp
|
||||
It declares a parameter \f(CW\*(C`loop\*(C'\fR of type \f(CW\*(C`struct ev_loop *\*(C'\fR, quite
|
||||
suitable for use with \f(CW\*(C`EV_A\*(C'\fR.
|
||||
.ie n .IP """EV_DEFAULT""\fR, \f(CW""EV_DEFAULT_""" 4
|
||||
.ie n .IP """EV_DEFAULT"", ""EV_DEFAULT_""" 4
|
||||
.el .IP "\f(CWEV_DEFAULT\fR, \f(CWEV_DEFAULT_\fR" 4
|
||||
.IX Item "EV_DEFAULT, EV_DEFAULT_"
|
||||
Similar to the other two macros, this gives you the value of the default
|
||||
loop, if multiple loops are supported (\*(L"ev loop default\*(R").
|
||||
.ie n .IP """EV_DEFAULT_UC""\fR, \f(CW""EV_DEFAULT_UC_""" 4
|
||||
.ie n .IP """EV_DEFAULT_UC"", ""EV_DEFAULT_UC_""" 4
|
||||
.el .IP "\f(CWEV_DEFAULT_UC\fR, \f(CWEV_DEFAULT_UC_\fR" 4
|
||||
.IX Item "EV_DEFAULT_UC, EV_DEFAULT_UC_"
|
||||
Usage identical to \f(CW\*(C`EV_DEFAULT\*(C'\fR and \f(CW\*(C`EV_DEFAULT_\*(C'\fR, but requires that the
|
||||
@@ -3446,7 +3571,7 @@ The goal is to enable you to just copy the necessary files into your
|
||||
source directory without having to change even a single line in them, so
|
||||
you can easily upgrade by simply copying (or having a checked-out copy of
|
||||
libev somewhere in your source tree).
|
||||
.Sh "\s-1FILESETS\s0"
|
||||
.SS "\s-1FILESETS\s0"
|
||||
.IX Subsection "FILESETS"
|
||||
Depending on what features you need you need to include one or more sets of files
|
||||
in your application.
|
||||
@@ -3535,7 +3660,7 @@ For this of course you need the m4 file:
|
||||
.Vb 1
|
||||
\& libev.m4
|
||||
.Ve
|
||||
.Sh "\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0"
|
||||
.SS "\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0"
|
||||
.IX Subsection "PREPROCESSOR SYMBOLS/MACROS"
|
||||
Libev can be configured via a variety of preprocessor symbols you have to
|
||||
define before including any of its files. The default in the absence of
|
||||
@@ -3744,9 +3869,19 @@ 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 this is used to override some
|
||||
inlining decisions, saves roughly 30% code size on amd64. It also selects a
|
||||
much smaller 2\-heap for timer management over the default 4\-heap.
|
||||
speed (but with the full \s-1API\s0), define this symbol to \f(CW1\fR. Currently this
|
||||
is used to override some inlining decisions, saves roughly 30% code size
|
||||
on amd64. It also selects a much smaller 2\-heap for timer management over
|
||||
the default 4\-heap.
|
||||
.Sp
|
||||
You can save even more by disabling watcher types you do not need
|
||||
and setting \f(CW\*(C`EV_MAXPRI\*(C'\fR == \f(CW\*(C`EV_MINPRI\*(C'\fR. Also, disabling \f(CW\*(C`assert\*(C'\fR
|
||||
(\f(CW\*(C`\-DNDEBUG\*(C'\fR) will usually reduce code size a lot.
|
||||
.Sp
|
||||
Defining \f(CW\*(C`EV_MINIMAL\*(C'\fR to \f(CW2\fR will additionally reduce the core \s-1API\s0 to
|
||||
provide a bare-bones event library. See \f(CW\*(C`ev.h\*(C'\fR for details on what parts
|
||||
of the \s-1API\s0 are still available, and do not complain if this subset changes
|
||||
over time.
|
||||
.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
|
||||
@@ -3820,7 +3955,7 @@ definition and a statement, respectively. See the \fIev.h\fR header file for
|
||||
their default definitions. One possible use for overriding these is to
|
||||
avoid the \f(CW\*(C`struct ev_loop *\*(C'\fR as first argument in all cases, or to use
|
||||
method calls instead of plain function calls in \*(C+.
|
||||
.Sh "\s-1EXPORTED\s0 \s-1API\s0 \s-1SYMBOLS\s0"
|
||||
.SS "\s-1EXPORTED\s0 \s-1API\s0 \s-1SYMBOLS\s0"
|
||||
.IX Subsection "EXPORTED API SYMBOLS"
|
||||
If you need to re-export the \s-1API\s0 (e.g. via a \s-1DLL\s0) and you need a list of
|
||||
exported symbols, you can use the provided \fISymbol.*\fR files which list
|
||||
@@ -3850,7 +3985,7 @@ This would create a file \fIwrap.h\fR which essentially looks like this:
|
||||
\& #define ev_check_stop myprefix_ev_check_stop
|
||||
\& ...
|
||||
.Ve
|
||||
.Sh "\s-1EXAMPLES\s0"
|
||||
.SS "\s-1EXAMPLES\s0"
|
||||
.IX Subsection "EXAMPLES"
|
||||
For a real-world example of a program the includes libev
|
||||
verbatim, you can have a look at the \s-1EV\s0 perl module
|
||||
@@ -3885,7 +4020,7 @@ And a \fIev_cpp.C\fR implementation file that contains libev proper and is compi
|
||||
.Ve
|
||||
.SH "INTERACTION WITH OTHER PROGRAMS OR LIBRARIES"
|
||||
.IX Header "INTERACTION WITH OTHER PROGRAMS OR LIBRARIES"
|
||||
.Sh "\s-1THREADS\s0 \s-1AND\s0 \s-1COROUTINES\s0"
|
||||
.SS "\s-1THREADS\s0 \s-1AND\s0 \s-1COROUTINES\s0"
|
||||
.IX Subsection "THREADS AND COROUTINES"
|
||||
\fI\s-1THREADS\s0\fR
|
||||
.IX Subsection "THREADS"
|
||||
@@ -3941,20 +4076,173 @@ work in the default loop by registering the signal watcher with the
|
||||
default loop and triggering an \f(CW\*(C`ev_async\*(C'\fR watcher from the default loop
|
||||
watcher callback into the event loop interested in the signal.
|
||||
.PP
|
||||
\s-1THREAD\s0 \s-1LOCKING\s0 \s-1EXAMPLE\s0
|
||||
.IX Subsection "THREAD LOCKING EXAMPLE"
|
||||
.PP
|
||||
Here is a fictitious example of how to run an event loop in a different
|
||||
thread than where callbacks are being invoked and watchers are
|
||||
created/added/removed.
|
||||
.PP
|
||||
For a real-world example, see the \f(CW\*(C`EV::Loop::Async\*(C'\fR perl module,
|
||||
which uses exactly this technique (which is suited for many high-level
|
||||
languages).
|
||||
.PP
|
||||
The example uses a pthread mutex to protect the loop data, a condition
|
||||
variable to wait for callback invocations, an async watcher to notify the
|
||||
event loop thread and an unspecified mechanism to wake up the main thread.
|
||||
.PP
|
||||
First, you need to associate some data with the event loop:
|
||||
.PP
|
||||
.Vb 6
|
||||
\& typedef struct {
|
||||
\& mutex_t lock; /* global loop lock */
|
||||
\& ev_async async_w;
|
||||
\& thread_t tid;
|
||||
\& cond_t invoke_cv;
|
||||
\& } userdata;
|
||||
\&
|
||||
\& void prepare_loop (EV_P)
|
||||
\& {
|
||||
\& // 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);
|
||||
\&
|
||||
\& 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_invoke_pending_cb (EV_A_ l_invoke);
|
||||
\& ev_set_loop_release_cb (EV_A_ l_release, l_acquire);
|
||||
\&
|
||||
\& // then create the thread running ev_loop
|
||||
\& pthread_create (&u\->tid, 0, l_run, EV_A);
|
||||
\& }
|
||||
.Ve
|
||||
.PP
|
||||
The callback for the \f(CW\*(C`ev_async\*(C'\fR watcher does nothing: the watcher is used
|
||||
solely to wake up the event loop so it takes notice of any new watchers
|
||||
that might have been added:
|
||||
.PP
|
||||
.Vb 5
|
||||
\& static void
|
||||
\& async_cb (EV_P_ ev_async *w, int revents)
|
||||
\& {
|
||||
\& // just used for the side effects
|
||||
\& }
|
||||
.Ve
|
||||
.PP
|
||||
The \f(CW\*(C`l_release\*(C'\fR and \f(CW\*(C`l_acquire\*(C'\fR callbacks simply unlock/lock the mutex
|
||||
protecting the loop data, respectively.
|
||||
.PP
|
||||
.Vb 6
|
||||
\& static void
|
||||
\& l_release (EV_P)
|
||||
\& {
|
||||
\& userdata *u = ev_userdata (EV_A);
|
||||
\& pthread_mutex_unlock (&u\->lock);
|
||||
\& }
|
||||
\&
|
||||
\& static void
|
||||
\& l_acquire (EV_P)
|
||||
\& {
|
||||
\& userdata *u = ev_userdata (EV_A);
|
||||
\& pthread_mutex_lock (&u\->lock);
|
||||
\& }
|
||||
.Ve
|
||||
.PP
|
||||
The event loop thread first acquires the mutex, and then jumps straight
|
||||
into \f(CW\*(C`ev_loop\*(C'\fR:
|
||||
.PP
|
||||
.Vb 4
|
||||
\& void *
|
||||
\& l_run (void *thr_arg)
|
||||
\& {
|
||||
\& struct ev_loop *loop = (struct ev_loop *)thr_arg;
|
||||
\&
|
||||
\& l_acquire (EV_A);
|
||||
\& pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
\& ev_loop (EV_A_ 0);
|
||||
\& l_release (EV_A);
|
||||
\&
|
||||
\& return 0;
|
||||
\& }
|
||||
.Ve
|
||||
.PP
|
||||
Instead of invoking all pending watchers, the \f(CW\*(C`l_invoke\*(C'\fR callback will
|
||||
signal the main thread via some unspecified mechanism (signals? pipe
|
||||
writes? \f(CW\*(C`Async::Interrupt\*(C'\fR?) and then waits until all pending watchers
|
||||
have been called (in a while loop because a) spurious wakeups are possible
|
||||
and b) skipping inter-thread-communication when there are no pending
|
||||
watchers is very beneficial):
|
||||
.PP
|
||||
.Vb 4
|
||||
\& static void
|
||||
\& l_invoke (EV_P)
|
||||
\& {
|
||||
\& userdata *u = ev_userdata (EV_A);
|
||||
\&
|
||||
\& while (ev_pending_count (EV_A))
|
||||
\& {
|
||||
\& wake_up_other_thread_in_some_magic_or_not_so_magic_way ();
|
||||
\& pthread_cond_wait (&u\->invoke_cv, &u\->lock);
|
||||
\& }
|
||||
\& }
|
||||
.Ve
|
||||
.PP
|
||||
Now, whenever the main thread gets told to invoke pending watchers, it
|
||||
will grab the lock, call \f(CW\*(C`ev_invoke_pending\*(C'\fR and then signal the loop
|
||||
thread to continue:
|
||||
.PP
|
||||
.Vb 4
|
||||
\& static void
|
||||
\& real_invoke_pending (EV_P)
|
||||
\& {
|
||||
\& userdata *u = ev_userdata (EV_A);
|
||||
\&
|
||||
\& pthread_mutex_lock (&u\->lock);
|
||||
\& ev_invoke_pending (EV_A);
|
||||
\& pthread_cond_signal (&u\->invoke_cv);
|
||||
\& pthread_mutex_unlock (&u\->lock);
|
||||
\& }
|
||||
.Ve
|
||||
.PP
|
||||
Whenever you want to start/stop a watcher or do other modifications to an
|
||||
event loop, you will now have to lock:
|
||||
.PP
|
||||
.Vb 2
|
||||
\& ev_timer timeout_watcher;
|
||||
\& userdata *u = ev_userdata (EV_A);
|
||||
\&
|
||||
\& ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
|
||||
\&
|
||||
\& pthread_mutex_lock (&u\->lock);
|
||||
\& ev_timer_start (EV_A_ &timeout_watcher);
|
||||
\& ev_async_send (EV_A_ &u\->async_w);
|
||||
\& pthread_mutex_unlock (&u\->lock);
|
||||
.Ve
|
||||
.PP
|
||||
Note that sending the \f(CW\*(C`ev_async\*(C'\fR watcher is required because otherwise
|
||||
an event loop currently blocking in the kernel will have no knowledge
|
||||
about the newly added timer. By waking up the loop it will pick up any new
|
||||
watchers in the next event loop iteration.
|
||||
.PP
|
||||
\fI\s-1COROUTINES\s0\fR
|
||||
.IX Subsection "COROUTINES"
|
||||
.PP
|
||||
Libev is very accommodating to coroutines (\*(L"cooperative threads\*(R"):
|
||||
libev fully supports nesting calls to its functions from different
|
||||
coroutines (e.g. you can call \f(CW\*(C`ev_loop\*(C'\fR on the same loop from two
|
||||
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 \f(CW\*(C`ev_periodic\*(C'\fR reschedule callbacks.
|
||||
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 \f(CW\*(C`ev_periodic\*(C'\fR reschedule callbacks.
|
||||
.PP
|
||||
Care has been taken to ensure that libev does not keep local state inside
|
||||
\&\f(CW\*(C`ev_loop\*(C'\fR, and other calls do not usually allow for coroutine switches as
|
||||
they do not call any callbacks.
|
||||
.Sh "\s-1COMPILER\s0 \s-1WARNINGS\s0"
|
||||
.SS "\s-1COMPILER\s0 \s-1WARNINGS\s0"
|
||||
.IX Subsection "COMPILER WARNINGS"
|
||||
Depending on your compiler and compiler settings, you might get no or a
|
||||
lot of warnings when compiling libev code. Some people are apparently
|
||||
@@ -3981,7 +4269,7 @@ While libev is written to generate as few warnings as possible,
|
||||
with any compiler warnings enabled unless you are prepared to cope with
|
||||
them (e.g. by ignoring them). Remember that warnings are just that:
|
||||
warnings, not errors, or proof of bugs.
|
||||
.Sh "\s-1VALGRIND\s0"
|
||||
.SS "\s-1VALGRIND\s0"
|
||||
.IX Subsection "VALGRIND"
|
||||
Valgrind has a special section here because it is a popular tool that is
|
||||
highly useful. Unfortunately, valgrind reports are very hard to interpret.
|
||||
@@ -4016,7 +4304,7 @@ If you need, for some reason, empty reports from valgrind for your project
|
||||
I suggest using suppression lists.
|
||||
.SH "PORTABILITY NOTES"
|
||||
.IX Header "PORTABILITY NOTES"
|
||||
.Sh "\s-1WIN32\s0 \s-1PLATFORM\s0 \s-1LIMITATIONS\s0 \s-1AND\s0 \s-1WORKAROUNDS\s0"
|
||||
.SS "\s-1WIN32\s0 \s-1PLATFORM\s0 \s-1LIMITATIONS\s0 \s-1AND\s0 \s-1WORKAROUNDS\s0"
|
||||
.IX Subsection "WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS"
|
||||
Win32 doesn't support any of the standards (e.g. \s-1POSIX\s0) that libev
|
||||
requires, and its I/O model is fundamentally incompatible with the \s-1POSIX\s0
|
||||
@@ -4113,11 +4401,11 @@ runtime libraries. This might get you to about \f(CW512\fR or \f(CW2048\fR socke
|
||||
(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"
|
||||
.SS "\s-1PORTABILITY\s0 \s-1REQUIREMENTS\s0"
|
||||
.IX Subsection "PORTABILITY REQUIREMENTS"
|
||||
In addition to a working ISO-C implementation and of course the
|
||||
backend-specific APIs, libev relies on a few additional extensions:
|
||||
.ie n .IP """void (*)(ev_watcher_type *, int revents)""\fR must have compatible calling conventions regardless of \f(CW""ev_watcher_type *""." 4
|
||||
.ie n .IP """void (*)(ev_watcher_type *, int revents)"" must have compatible calling conventions regardless of ""ev_watcher_type *""." 4
|
||||
.el .IP "\f(CWvoid (*)(ev_watcher_type *, int revents)\fR must have compatible calling conventions regardless of \f(CWev_watcher_type *\fR." 4
|
||||
.IX Item "void (*)(ev_watcher_type *, int revents) must have compatible calling conventions regardless of ev_watcher_type *."
|
||||
Libev assumes not only that all watcher pointers have the same internal
|
||||
@@ -4159,7 +4447,9 @@ watchers.
|
||||
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).
|
||||
implementations implementing \s-1IEEE\s0 754, which is basically all existing
|
||||
ones. With \s-1IEEE\s0 754 doubles, you get microsecond accuracy until at least
|
||||
2200.
|
||||
.PP
|
||||
If you know of other additional requirements drop me a note.
|
||||
.SH "ALGORITHMIC COMPLEXITIES"
|
||||
|
||||
195
deps/libev/ev.c
vendored
195
deps/libev/ev.c
vendored
@@ -59,6 +59,8 @@ extern "C" {
|
||||
# define EV_USE_MONOTONIC 1
|
||||
# endif
|
||||
# endif
|
||||
# elif !defined(EV_USE_CLOCK_SYSCALL)
|
||||
# define EV_USE_CLOCK_SYSCALL 0
|
||||
# endif
|
||||
|
||||
# if HAVE_CLOCK_GETTIME
|
||||
@@ -284,6 +286,20 @@ extern "C" {
|
||||
# define EV_HEAP_CACHE_AT !EV_MINIMAL
|
||||
#endif
|
||||
|
||||
/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
|
||||
/* which makes programs even slower. might work on other unices, too. */
|
||||
#if EV_USE_CLOCK_SYSCALL
|
||||
# include <syscall.h>
|
||||
# ifdef SYS_clock_gettime
|
||||
# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
|
||||
# undef EV_USE_MONOTONIC
|
||||
# define EV_USE_MONOTONIC 1
|
||||
# else
|
||||
# undef EV_USE_CLOCK_SYSCALL
|
||||
# define EV_USE_CLOCK_SYSCALL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* this block fixes any misconfiguration where we know we run into trouble otherwise */
|
||||
|
||||
#ifndef CLOCK_MONOTONIC
|
||||
@@ -322,15 +338,6 @@ extern "C" {
|
||||
# include <winsock.h>
|
||||
#endif
|
||||
|
||||
/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
|
||||
/* which makes programs even slower. might work on other unices, too. */
|
||||
#if EV_USE_CLOCK_SYSCALL
|
||||
# include <syscall.h>
|
||||
# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
|
||||
# undef EV_USE_MONOTONIC
|
||||
# define EV_USE_MONOTONIC 1
|
||||
#endif
|
||||
|
||||
#if EV_USE_EVENTFD
|
||||
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
||||
# include <stdint.h>
|
||||
@@ -386,8 +393,13 @@ int eventfd (unsigned int initval, int flags);
|
||||
# define inline_speed static inline
|
||||
#endif
|
||||
|
||||
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
|
||||
#define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
|
||||
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
|
||||
|
||||
#if EV_MINPRI == EV_MAXPRI
|
||||
# define ABSPRI(w) (((W)w), 0)
|
||||
#else
|
||||
# define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
|
||||
#endif
|
||||
|
||||
#define EMPTY /* required for microsofts broken pseudo-c compiler */
|
||||
#define EMPTY2(a,b) /* used to suppress some warnings */
|
||||
@@ -480,12 +492,15 @@ ev_realloc (void *ptr, long size)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* set in reify when reification needed */
|
||||
#define EV_ANFD_REIFY 1
|
||||
|
||||
/* file descriptor info structure */
|
||||
typedef struct
|
||||
{
|
||||
WL head;
|
||||
unsigned char events; /* the events watched for */
|
||||
unsigned char reify; /* flag set when this ANFD needs reification */
|
||||
unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
|
||||
unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
|
||||
unsigned char unused;
|
||||
#if EV_USE_EPOLL
|
||||
@@ -557,8 +572,21 @@ typedef struct
|
||||
|
||||
#endif
|
||||
|
||||
#if EV_MINIMAL < 2
|
||||
# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)
|
||||
# define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A)
|
||||
# define EV_INVOKE_PENDING invoke_cb (EV_A)
|
||||
#else
|
||||
# define EV_RELEASE_CB (void)0
|
||||
# define EV_ACQUIRE_CB (void)0
|
||||
# define EV_INVOKE_PENDING ev_invoke_pending (EV_A)
|
||||
#endif
|
||||
|
||||
#define EVUNLOOP_RECURSE 0x80
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef EV_HAVE_EV_TIME
|
||||
ev_tstamp
|
||||
ev_time (void)
|
||||
{
|
||||
@@ -575,6 +603,7 @@ ev_time (void)
|
||||
gettimeofday (&tv, 0);
|
||||
return tv.tv_sec + tv.tv_usec * 1e-6;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline_size ev_tstamp
|
||||
get_clock (void)
|
||||
@@ -620,7 +649,7 @@ ev_sleep (ev_tstamp delay)
|
||||
tv.tv_usec = (long)((delay - (ev_tstamp)(tv.tv_sec)) * 1e6);
|
||||
|
||||
/* here we rely on sys/time.h + sys/types.h + unistd.h providing select */
|
||||
/* somehting nto guaranteed by newer posix versions, but guaranteed */
|
||||
/* something not guaranteed by newer posix versions, but guaranteed */
|
||||
/* by older ones */
|
||||
select (0, 0, 0, 0, &tv);
|
||||
#endif
|
||||
@@ -738,7 +767,7 @@ queue_events (EV_P_ W *events, int eventcnt, int type)
|
||||
/*****************************************************************************/
|
||||
|
||||
inline_speed void
|
||||
fd_event (EV_P_ int fd, int revents)
|
||||
fd_event_nc (EV_P_ int fd, int revents)
|
||||
{
|
||||
ANFD *anfd = anfds + fd;
|
||||
ev_io *w;
|
||||
@@ -752,11 +781,22 @@ fd_event (EV_P_ int fd, int revents)
|
||||
}
|
||||
}
|
||||
|
||||
/* do not submit kernel events for fds that have reify set */
|
||||
/* because that means they changed while we were polling for new events */
|
||||
inline_speed void
|
||||
fd_event (EV_P_ int fd, int revents)
|
||||
{
|
||||
ANFD *anfd = anfds + fd;
|
||||
|
||||
if (expect_true (!anfd->reify))
|
||||
fd_event_nc (EV_A_ fd, revents);
|
||||
}
|
||||
|
||||
void
|
||||
ev_feed_fd_event (EV_P_ int fd, int revents)
|
||||
{
|
||||
if (fd >= 0 && fd < anfdmax)
|
||||
fd_event (EV_A_ fd, revents);
|
||||
fd_event_nc (EV_A_ fd, revents);
|
||||
}
|
||||
|
||||
/* make sure the external fd watch events are in-sync */
|
||||
@@ -881,7 +921,7 @@ fd_rearm_all (EV_P)
|
||||
{
|
||||
anfds [fd].events = 0;
|
||||
anfds [fd].emask = 0;
|
||||
fd_change (EV_A_ fd, EV__IOFDSET | 1);
|
||||
fd_change (EV_A_ fd, EV__IOFDSET | EV_ANFD_REIFY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,12 +1385,19 @@ ev_backend (EV_P)
|
||||
return backend;
|
||||
}
|
||||
|
||||
#if EV_MINIMAL < 2
|
||||
unsigned int
|
||||
ev_loop_count (EV_P)
|
||||
{
|
||||
return loop_count;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
ev_loop_depth (EV_P)
|
||||
{
|
||||
return loop_depth;
|
||||
}
|
||||
|
||||
void
|
||||
ev_set_io_collect_interval (EV_P_ ev_tstamp interval)
|
||||
{
|
||||
@@ -1363,6 +1410,30 @@ ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval)
|
||||
timeout_blocktime = interval;
|
||||
}
|
||||
|
||||
void
|
||||
ev_set_userdata (EV_P_ void *data)
|
||||
{
|
||||
userdata = data;
|
||||
}
|
||||
|
||||
void *
|
||||
ev_userdata (EV_P)
|
||||
{
|
||||
return userdata;
|
||||
}
|
||||
|
||||
void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P))
|
||||
{
|
||||
invoke_cb = invoke_pending_cb;
|
||||
}
|
||||
|
||||
void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
|
||||
{
|
||||
release_cb = release;
|
||||
acquire_cb = acquire;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initialise a loop structure, must be zero-initialised */
|
||||
static void noinline
|
||||
loop_init (EV_P_ unsigned int flags)
|
||||
@@ -1393,6 +1464,9 @@ loop_init (EV_P_ unsigned int flags)
|
||||
mn_now = get_clock ();
|
||||
now_floor = mn_now;
|
||||
rtmn_diff = ev_rt_now - mn_now;
|
||||
#if EV_MINIMAL < 2
|
||||
invoke_cb = ev_invoke_pending;
|
||||
#endif
|
||||
|
||||
io_blocktime = 0.;
|
||||
timeout_blocktime = 0.;
|
||||
@@ -1596,6 +1670,7 @@ ev_loop_fork (EV_P)
|
||||
{
|
||||
postfork = 1; /* must be in line with ev_default_fork */
|
||||
}
|
||||
#endif /* multiplicity */
|
||||
|
||||
#if EV_VERIFY
|
||||
static void noinline
|
||||
@@ -1633,6 +1708,7 @@ array_verify (EV_P_ W *ws, int cnt)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EV_MINIMAL < 2
|
||||
void
|
||||
ev_loop_verify (EV_P)
|
||||
{
|
||||
@@ -1695,8 +1771,7 @@ ev_loop_verify (EV_P)
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* multiplicity */
|
||||
#endif
|
||||
|
||||
#if EV_MULTIPLICITY
|
||||
struct ev_loop *
|
||||
@@ -1767,8 +1842,20 @@ ev_invoke (EV_P_ void *w, int revents)
|
||||
EV_CB_INVOKE ((W)w, revents);
|
||||
}
|
||||
|
||||
inline_speed void
|
||||
call_pending (EV_P)
|
||||
unsigned int
|
||||
ev_pending_count (EV_P)
|
||||
{
|
||||
int pri;
|
||||
unsigned int count = 0;
|
||||
|
||||
for (pri = NUMPRI; pri--; )
|
||||
count += pendingcnt [pri];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void noinline
|
||||
ev_invoke_pending (EV_P)
|
||||
{
|
||||
int pri;
|
||||
|
||||
@@ -1950,11 +2037,10 @@ timers_reschedule (EV_P_ ev_tstamp adjust)
|
||||
inline_speed void
|
||||
time_update (EV_P_ ev_tstamp max_block)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if EV_USE_MONOTONIC
|
||||
if (expect_true (have_monotonic))
|
||||
{
|
||||
int i;
|
||||
ev_tstamp odiff = rtmn_diff;
|
||||
|
||||
mn_now = get_clock ();
|
||||
@@ -2014,14 +2100,18 @@ time_update (EV_P_ ev_tstamp max_block)
|
||||
}
|
||||
}
|
||||
|
||||
static int loop_done;
|
||||
|
||||
void
|
||||
ev_loop (EV_P_ int flags)
|
||||
{
|
||||
#if EV_MINIMAL < 2
|
||||
++loop_depth;
|
||||
#endif
|
||||
|
||||
assert (("libev: ev_loop recursion during release detected", loop_done != EVUNLOOP_RECURSE));
|
||||
|
||||
loop_done = EVUNLOOP_CANCEL;
|
||||
|
||||
call_pending (EV_A); /* in case we recurse, ensure ordering stays nice and clean */
|
||||
EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */
|
||||
|
||||
do
|
||||
{
|
||||
@@ -2044,7 +2134,7 @@ ev_loop (EV_P_ int flags)
|
||||
if (forkcnt)
|
||||
{
|
||||
queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
|
||||
call_pending (EV_A);
|
||||
EV_INVOKE_PENDING;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2052,9 +2142,12 @@ ev_loop (EV_P_ int flags)
|
||||
if (expect_false (preparecnt))
|
||||
{
|
||||
queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
|
||||
call_pending (EV_A);
|
||||
EV_INVOKE_PENDING;
|
||||
}
|
||||
|
||||
if (expect_false (loop_done))
|
||||
break;
|
||||
|
||||
/* we might have forked, so reify kernel state if necessary */
|
||||
if (expect_false (postfork))
|
||||
loop_fork (EV_A);
|
||||
@@ -2069,6 +2162,9 @@ ev_loop (EV_P_ int flags)
|
||||
|
||||
if (expect_true (!(flags & EVLOOP_NONBLOCK || idleall || !activecnt)))
|
||||
{
|
||||
/* remember old timestamp for io_blocktime calculation */
|
||||
ev_tstamp prev_mn_now = mn_now;
|
||||
|
||||
/* update time to cancel out callback processing overhead */
|
||||
time_update (EV_A_ 1e100);
|
||||
|
||||
@@ -2088,23 +2184,32 @@ ev_loop (EV_P_ int flags)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* don't let timeouts decrease the waittime below timeout_blocktime */
|
||||
if (expect_false (waittime < timeout_blocktime))
|
||||
waittime = timeout_blocktime;
|
||||
|
||||
sleeptime = waittime - backend_fudge;
|
||||
|
||||
if (expect_true (sleeptime > io_blocktime))
|
||||
sleeptime = io_blocktime;
|
||||
|
||||
if (sleeptime)
|
||||
/* extra check because io_blocktime is commonly 0 */
|
||||
if (expect_false (io_blocktime))
|
||||
{
|
||||
ev_sleep (sleeptime);
|
||||
waittime -= sleeptime;
|
||||
sleeptime = io_blocktime - (mn_now - prev_mn_now);
|
||||
|
||||
if (sleeptime > waittime - backend_fudge)
|
||||
sleeptime = waittime - backend_fudge;
|
||||
|
||||
if (expect_true (sleeptime > 0.))
|
||||
{
|
||||
ev_sleep (sleeptime);
|
||||
waittime -= sleeptime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if EV_MINIMAL < 2
|
||||
++loop_count;
|
||||
#endif
|
||||
assert ((loop_done = EVUNLOOP_RECURSE, 1)); /* assert for side effect */
|
||||
backend_poll (EV_A_ waittime);
|
||||
assert ((loop_done = EVUNLOOP_CANCEL, 1)); /* assert for side effect */
|
||||
|
||||
/* update ev_rt_now, do magic */
|
||||
time_update (EV_A_ waittime + sleeptime);
|
||||
@@ -2125,7 +2230,7 @@ ev_loop (EV_P_ int flags)
|
||||
if (expect_false (checkcnt))
|
||||
queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
|
||||
|
||||
call_pending (EV_A);
|
||||
EV_INVOKE_PENDING;
|
||||
}
|
||||
while (expect_true (
|
||||
activecnt
|
||||
@@ -2135,6 +2240,10 @@ ev_loop (EV_P_ int flags)
|
||||
|
||||
if (loop_done == EVUNLOOP_ONE)
|
||||
loop_done = EVUNLOOP_CANCEL;
|
||||
|
||||
#if EV_MINIMAL < 2
|
||||
--loop_depth;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2236,10 +2345,10 @@ ev_clear_pending (EV_P_ void *w)
|
||||
inline_size void
|
||||
pri_adjust (EV_P_ W w)
|
||||
{
|
||||
int pri = w->priority;
|
||||
int pri = ev_priority (w);
|
||||
pri = pri < EV_MINPRI ? EV_MINPRI : pri;
|
||||
pri = pri > EV_MAXPRI ? EV_MAXPRI : pri;
|
||||
w->priority = pri;
|
||||
ev_set_priority (w, pri);
|
||||
}
|
||||
|
||||
inline_speed void
|
||||
@@ -2276,7 +2385,7 @@ ev_io_start (EV_P_ ev_io *w)
|
||||
array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
|
||||
wlist_add (&anfds[fd].head, (WL)w);
|
||||
|
||||
fd_change (EV_A_ fd, w->events & EV__IOFDSET | 1);
|
||||
fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY);
|
||||
w->events &= ~EV__IOFDSET;
|
||||
|
||||
EV_FREQUENT_CHECK;
|
||||
@@ -2380,6 +2489,12 @@ ev_timer_again (EV_P_ ev_timer *w)
|
||||
EV_FREQUENT_CHECK;
|
||||
}
|
||||
|
||||
ev_tstamp
|
||||
ev_timer_remaining (EV_P_ ev_timer *w)
|
||||
{
|
||||
return ev_at (w) - (ev_is_active (w) ? mn_now : 0.);
|
||||
}
|
||||
|
||||
#if EV_PERIODIC_ENABLE
|
||||
void noinline
|
||||
ev_periodic_start (EV_P_ ev_periodic *w)
|
||||
@@ -2490,7 +2605,7 @@ ev_signal_start (EV_P_ ev_signal *w)
|
||||
#if _WIN32
|
||||
signal (w->signum, ev_sighandler);
|
||||
#else
|
||||
struct sigaction sa;
|
||||
struct sigaction sa = { };
|
||||
sa.sa_handler = ev_sighandler;
|
||||
sigfillset (&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
|
||||
|
||||
72
deps/libev/ev.h
vendored
72
deps/libev/ev.h
vendored
@@ -163,7 +163,7 @@ struct ev_loop;
|
||||
#endif
|
||||
|
||||
#define EV_VERSION_MAJOR 3
|
||||
#define EV_VERSION_MINOR 0
|
||||
#define EV_VERSION_MINOR 7
|
||||
|
||||
#ifndef EV_CB_DECLARE
|
||||
# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents);
|
||||
@@ -189,11 +189,17 @@ struct ev_loop;
|
||||
* or the array index + 1 in the pendings array.
|
||||
*/
|
||||
|
||||
#if EV_MINPRI == EV_MAXPRI
|
||||
# define EV_DECL_PRIORITY
|
||||
#else
|
||||
# define EV_DECL_PRIORITY int priority;
|
||||
#endif
|
||||
|
||||
/* shared by all watchers */
|
||||
#define EV_WATCHER(type) \
|
||||
int active; /* private */ \
|
||||
int pending; /* private */ \
|
||||
int priority; /* private */ \
|
||||
EV_DECL_PRIORITY /* private */ \
|
||||
EV_COMMON /* rw */ \
|
||||
EV_CB_DECLARE (type) /* private */
|
||||
|
||||
@@ -461,10 +467,8 @@ ev_default_loop (unsigned int flags)
|
||||
struct ev_loop *ev_loop_new (unsigned int flags);
|
||||
void ev_loop_destroy (EV_P);
|
||||
void ev_loop_fork (EV_P);
|
||||
void ev_loop_verify (EV_P);
|
||||
|
||||
ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */
|
||||
void ev_now_update (EV_P);
|
||||
|
||||
#else
|
||||
|
||||
@@ -498,6 +502,10 @@ void ev_default_destroy (void); /* destroy the default loop */
|
||||
/* you can actually call it at any time, anywhere :) */
|
||||
void ev_default_fork (void);
|
||||
|
||||
unsigned int ev_backend (EV_P); /* backend in use by loop */
|
||||
|
||||
void ev_now_update (EV_P); /* update event loop time */
|
||||
|
||||
#if EV_WALK_ENABLE
|
||||
/* walk (almost) all watchers in the loop of a given type, invoking the */
|
||||
/* callback on every such watcher. The callback might stop the watcher, */
|
||||
@@ -505,8 +513,6 @@ void ev_default_fork (void);
|
||||
void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w));
|
||||
#endif
|
||||
|
||||
unsigned int ev_backend (EV_P); /* backend in use by loop */
|
||||
unsigned int ev_loop_count (EV_P); /* number of loop iterations */
|
||||
#endif /* prototypes */
|
||||
|
||||
#define EVLOOP_NONBLOCK 1 /* do not block/wait */
|
||||
@@ -519,36 +525,52 @@ unsigned int ev_loop_count (EV_P); /* number of loop iterations */
|
||||
void ev_loop (EV_P_ int flags);
|
||||
void ev_unloop (EV_P_ int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */
|
||||
|
||||
void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
|
||||
void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
|
||||
|
||||
/*
|
||||
* ref/unref can be used to add or remove a refcount on the mainloop. every watcher
|
||||
* keeps one reference. if you have a long-runing watcher you never unregister that
|
||||
* keeps one reference. if you have a long-running watcher you never unregister that
|
||||
* should not keep ev_loop from running, unref() after starting, and ref() before stopping.
|
||||
*/
|
||||
void ev_ref (EV_P);
|
||||
void ev_unref (EV_P);
|
||||
|
||||
/*
|
||||
* stop/start the timer handling.
|
||||
*/
|
||||
void ev_suspend (EV_P);
|
||||
void ev_resume (EV_P);
|
||||
|
||||
/*
|
||||
* convenience function, wait for a single event, without registering an event watcher
|
||||
* if timeout is < 0, do wait indefinitely
|
||||
*/
|
||||
void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg);
|
||||
|
||||
# if EV_MINIMAL < 2
|
||||
unsigned int ev_loop_count (EV_P); /* number of loop iterations */
|
||||
unsigned int ev_loop_depth (EV_P); /* #ev_loop enters - #ev_loop leaves */
|
||||
void ev_loop_verify (EV_P); /* abort if loop data corrupted */
|
||||
|
||||
void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
|
||||
void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
|
||||
|
||||
/* advanced stuff for threading etc. support, see docs */
|
||||
void ev_set_userdata (EV_P_ void *data);
|
||||
void *ev_userdata (EV_P);
|
||||
void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P));
|
||||
void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P));
|
||||
|
||||
unsigned int ev_pending_count (EV_P); /* number of pending events, if any */
|
||||
void ev_invoke_pending (EV_P); /* invoke all pending watchers */
|
||||
|
||||
/*
|
||||
* stop/start the timer handling.
|
||||
*/
|
||||
void ev_suspend (EV_P);
|
||||
void ev_resume (EV_P);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* these may evaluate ev multiple times, and the other arguments at most once */
|
||||
/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */
|
||||
#define ev_init(ev,cb_) do { \
|
||||
((ev_watcher *)(void *)(ev))->active = \
|
||||
((ev_watcher *)(void *)(ev))->pending = \
|
||||
((ev_watcher *)(void *)(ev))->priority = 0; \
|
||||
((ev_watcher *)(void *)(ev))->active = \
|
||||
((ev_watcher *)(void *)(ev))->pending = 0; \
|
||||
ev_set_priority ((ev), 0); \
|
||||
ev_set_cb ((ev), cb_); \
|
||||
} while (0)
|
||||
|
||||
@@ -581,9 +603,15 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
|
||||
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
|
||||
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
|
||||
|
||||
#define ev_priority(ev) ((((ev_watcher *)(void *)(ev))->priority) + 0)
|
||||
#define ev_cb(ev) (ev)->cb /* rw */
|
||||
#define ev_set_priority(ev,pri) ((ev_watcher *)(void *)(ev))->priority = (pri)
|
||||
|
||||
#if EV_MINPRI == EV_MAXPRI
|
||||
# define ev_priority(ev) ((ev), EV_MINPRI)
|
||||
# define ev_set_priority(ev,pri) ((ev), (pri))
|
||||
#else
|
||||
# define ev_priority(ev) ((((ev_watcher *)(void *)(ev))->priority) + 0)
|
||||
# define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri)
|
||||
#endif
|
||||
|
||||
#define ev_periodic_at(ev) (((ev_watcher_time *)(ev))->at + 0.)
|
||||
|
||||
@@ -610,6 +638,8 @@ void ev_timer_start (EV_P_ ev_timer *w);
|
||||
void ev_timer_stop (EV_P_ ev_timer *w);
|
||||
/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */
|
||||
void ev_timer_again (EV_P_ ev_timer *w);
|
||||
/* return remaining time */
|
||||
ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w);
|
||||
|
||||
#if EV_PERIODIC_ENABLE
|
||||
void ev_periodic_start (EV_P_ ev_periodic *w);
|
||||
|
||||
325
deps/libev/ev.pod
vendored
325
deps/libev/ev.pod
vendored
@@ -623,6 +623,18 @@ This value can sometimes be useful as a generation counter of sorts (it
|
||||
"ticks" the number of loop iterations), as it roughly corresponds with
|
||||
C<ev_prepare> and C<ev_check> calls.
|
||||
|
||||
=item unsigned int ev_loop_depth (loop)
|
||||
|
||||
Returns the number of times C<ev_loop> was entered minus the number of
|
||||
times C<ev_loop> was exited, in other words, the recursion depth.
|
||||
|
||||
Outside C<ev_loop>, this number is zero. In a callback, this number is
|
||||
C<1>, unless C<ev_loop> was invoked recursively (or from another thread),
|
||||
in which case it is higher.
|
||||
|
||||
Leaving C<ev_loop> abnormally (setjmp/longjmp, cancelling the thread
|
||||
etc.), doesn't count as exit.
|
||||
|
||||
=item unsigned int ev_backend (loop)
|
||||
|
||||
Returns one of the C<EVBACKEND_*> flags indicating the event backend in
|
||||
@@ -813,7 +825,9 @@ By setting a higher I<io collect interval> you allow libev to spend more
|
||||
time collecting I/O events, so you can handle more events per iteration,
|
||||
at the cost of increasing latency. Timeouts (both C<ev_periodic> and
|
||||
C<ev_timer>) will be not affected. Setting this to a non-null value will
|
||||
introduce an additional C<ev_sleep ()> call into most loop iterations.
|
||||
introduce an additional C<ev_sleep ()> call into most loop iterations. The
|
||||
sleep time ensures that libev will not poll for I/O events more often then
|
||||
once per this interval, on average.
|
||||
|
||||
Likewise, by setting a higher I<timeout collect interval> you allow libev
|
||||
to spend more time collecting timeouts, at the expense of increased
|
||||
@@ -825,7 +839,11 @@ Many (busy) programs can usually benefit by setting the I/O collect
|
||||
interval to a value near C<0.1> or so, which is often enough for
|
||||
interactive servers (of course not for games), likewise for timeouts. It
|
||||
usually doesn't make much sense to set it to a lower value than C<0.01>,
|
||||
as this approaches the timing granularity of most systems.
|
||||
as this approaches the timing granularity of most systems. Note that if
|
||||
you do transactions with the outside world and you can't increase the
|
||||
parallelity, then this setting will limit your transaction rate (if you
|
||||
need to poll once per transaction and the I/O collect interval is 0.01,
|
||||
then you can't do more than 100 transations per second).
|
||||
|
||||
Setting the I<timeout collect interval> can improve the opportunity for
|
||||
saving power, as the program will "bundle" timer callback invocations that
|
||||
@@ -834,6 +852,77 @@ times the process sleeps and wakes up again. Another useful technique to
|
||||
reduce iterations/wake-ups is to use C<ev_periodic> watchers and make sure
|
||||
they fire on, say, one-second boundaries only.
|
||||
|
||||
Example: we only need 0.1s timeout granularity, and we wish not to poll
|
||||
more often than 100 times per second:
|
||||
|
||||
ev_set_timeout_collect_interval (EV_DEFAULT_UC_ 0.1);
|
||||
ev_set_io_collect_interval (EV_DEFAULT_UC_ 0.01);
|
||||
|
||||
=item ev_invoke_pending (loop)
|
||||
|
||||
This call will simply invoke all pending watchers while resetting their
|
||||
pending state. Normally, C<ev_loop> does this automatically when required,
|
||||
but when overriding the invoke callback this call comes handy.
|
||||
|
||||
=item int ev_pending_count (loop)
|
||||
|
||||
Returns the number of pending watchers - zero indicates that no watchers
|
||||
are pending.
|
||||
|
||||
=item ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(EV_P))
|
||||
|
||||
This overrides the invoke pending functionality of the loop: Instead of
|
||||
invoking all pending watchers when there are any, C<ev_loop> will call
|
||||
this callback instead. This is useful, for example, when you want to
|
||||
invoke the actual watchers inside another context (another thread etc.).
|
||||
|
||||
If you want to reset the callback, use C<ev_invoke_pending> as new
|
||||
callback.
|
||||
|
||||
=item ev_set_loop_release_cb (loop, void (*release)(EV_P), void (*acquire)(EV_P))
|
||||
|
||||
Sometimes you want to share the same loop between multiple threads. This
|
||||
can be done relatively simply by putting mutex_lock/unlock calls around
|
||||
each call to a libev function.
|
||||
|
||||
However, C<ev_loop> can run an indefinite time, so it is not feasible to
|
||||
wait for it to return. One way around this is to wake up the loop via
|
||||
C<ev_unloop> and C<av_async_send>, another way is to set these I<release>
|
||||
and I<acquire> callbacks on the loop.
|
||||
|
||||
When set, then C<release> will be called just before the thread is
|
||||
suspended waiting for new events, and C<acquire> is called just
|
||||
afterwards.
|
||||
|
||||
Ideally, C<release> will just call your mutex_unlock function, and
|
||||
C<acquire> will just call the mutex_lock function again.
|
||||
|
||||
While event loop modifications are allowed between invocations of
|
||||
C<release> and C<acquire> (that's their only purpose after all), no
|
||||
modifications done will affect the event loop, i.e. adding watchers will
|
||||
have no effect on the set of file descriptors being watched, or the time
|
||||
waited. USe an C<ev_async> watcher to wake up C<ev_loop> when you want it
|
||||
to take note of any changes you made.
|
||||
|
||||
In theory, threads executing C<ev_loop> will be async-cancel safe between
|
||||
invocations of C<release> and C<acquire>.
|
||||
|
||||
See also the locking example in the C<THREADS> section later in this
|
||||
document.
|
||||
|
||||
=item ev_set_userdata (loop, void *data)
|
||||
|
||||
=item ev_userdata (loop)
|
||||
|
||||
Set and retrieve a single C<void *> associated with a loop. When
|
||||
C<ev_set_userdata> has never been called, then C<ev_userdata> returns
|
||||
C<0.>
|
||||
|
||||
These two functions can be used to associate arbitrary data with a loop,
|
||||
and are intended solely for the C<invoke_pending_cb>, C<release> and
|
||||
C<acquire> callbacks described above, but of course can be (ab-)used for
|
||||
any other purpose as well.
|
||||
|
||||
=item ev_loop_verify (loop)
|
||||
|
||||
This function only does something when C<EV_VERIFY> support has been
|
||||
@@ -1186,14 +1275,14 @@ programmers):
|
||||
static void
|
||||
t1_cb (EV_P_ ev_timer *w, int revents)
|
||||
{
|
||||
struct my_biggy big = (struct my_biggy *
|
||||
struct my_biggy big = (struct my_biggy *)
|
||||
(((char *)w) - offsetof (struct my_biggy, t1));
|
||||
}
|
||||
|
||||
static void
|
||||
t2_cb (EV_P_ ev_timer *w, int revents)
|
||||
{
|
||||
struct my_biggy big = (struct my_biggy *
|
||||
struct my_biggy big = (struct my_biggy *)
|
||||
(((char *)w) - offsetof (struct my_biggy, t2));
|
||||
}
|
||||
|
||||
@@ -1279,7 +1368,7 @@ other events are pending:
|
||||
}
|
||||
|
||||
static void
|
||||
idle-cb (EV_P_ ev_idle *w, int revents)
|
||||
idle_cb (EV_P_ ev_idle *w, int revents)
|
||||
{
|
||||
// actual processing
|
||||
read (STDIN_FILENO, ...);
|
||||
@@ -1470,8 +1559,8 @@ The callback is guaranteed to be invoked only I<after> its timeout has
|
||||
passed (not I<at>, 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 C<ev_loop> recursively).
|
||||
before ones of the same priority with later time-out values (but this is
|
||||
no longer true when a callback calls C<ev_loop> recursively).
|
||||
|
||||
=head3 Be smart about timeouts
|
||||
|
||||
@@ -1525,7 +1614,7 @@ member and C<ev_timer_again>.
|
||||
|
||||
At start:
|
||||
|
||||
ev_timer_init (timer, callback);
|
||||
ev_init (timer, callback);
|
||||
timer->repeat = 60.;
|
||||
ev_timer_again (loop, timer);
|
||||
|
||||
@@ -1597,7 +1686,7 @@ To start the timer, simply initialise the watcher and set C<last_activity>
|
||||
to the current time (meaning we just have some activity :), then call the
|
||||
callback, which will "do the right thing" and start the timer:
|
||||
|
||||
ev_timer_init (timer, callback);
|
||||
ev_init (timer, callback);
|
||||
last_activity = ev_now (loop);
|
||||
callback (loop, timer, EV_TIMEOUT);
|
||||
|
||||
@@ -1668,6 +1757,36 @@ If the event loop is suspended for a long time, you can also force an
|
||||
update of the time returned by C<ev_now ()> by calling C<ev_now_update
|
||||
()>.
|
||||
|
||||
=head3 The special problems of suspended animation
|
||||
|
||||
When you leave the server world it is quite customary to hit machines that
|
||||
can suspend/hibernate - what happens to the clocks during such a suspend?
|
||||
|
||||
Some quick tests made with a Linux 2.6.28 indicate that a suspend freezes
|
||||
all processes, while the clocks (C<times>, C<CLOCK_MONOTONIC>) continue
|
||||
to run until the system is suspended, but they will not advance while the
|
||||
system is suspended. That means, on resume, it will be as if the program
|
||||
was frozen for a few seconds, but the suspend time will not be counted
|
||||
towards C<ev_timer> when a monotonic clock source is used. The real time
|
||||
clock advanced as expected, but if it is used as sole clocksource, then a
|
||||
long suspend would be detected as a time jump by libev, and timers would
|
||||
be adjusted accordingly.
|
||||
|
||||
I would not be surprised to see different behaviour in different between
|
||||
operating systems, OS versions or even different hardware.
|
||||
|
||||
The other form of suspend (job control, or sending a SIGSTOP) will see a
|
||||
time jump in the monotonic clocks and the realtime clock. If the program
|
||||
is suspended for a very long time, and monotonic clock sources are in use,
|
||||
then you can expect C<ev_timer>s to expire as the full suspension time
|
||||
will be counted towards the timers. When no monotonic clock source is in
|
||||
use, then libev will again assume a timejump and adjust accordingly.
|
||||
|
||||
It might be beneficial for this latter case to call C<ev_suspend>
|
||||
and C<ev_resume> in code that handles C<SIGTSTP>, to at least get
|
||||
deterministic behaviour in this case (you can do nothing against
|
||||
C<SIGSTOP>).
|
||||
|
||||
=head3 Watcher-Specific Functions and Data Members
|
||||
|
||||
=over 4
|
||||
@@ -1703,6 +1822,18 @@ C<repeat> value), or reset the running timer to the C<repeat> value.
|
||||
This sounds a bit complicated, see L<Be smart about timeouts>, above, for a
|
||||
usage example.
|
||||
|
||||
=item ev_timer_remaining (loop, ev_timer *)
|
||||
|
||||
Returns the remaining time until a timer fires. If the timer is active,
|
||||
then this time is relative to the current event loop time, otherwise it's
|
||||
the timeout value currently configured.
|
||||
|
||||
That is, after an C<ev_timer_set (w, 5, 7)>, C<ev_timer_remaining> returns
|
||||
C<5>. When the timer is started and one second passes, C<ev_timer_remain>
|
||||
will return C<4>. When the timer expires and is restarted, it will return
|
||||
roughly C<7> (likely slightly less as callback invocation takes some time,
|
||||
too), and so on.
|
||||
|
||||
=item ev_tstamp repeat [read-write]
|
||||
|
||||
The current C<repeat> value. Will be used each time the watcher times out
|
||||
@@ -2004,12 +2135,16 @@ exits). It is permissible to install a child watcher I<after> the child
|
||||
has been forked (which implies it might have already exited), as long
|
||||
as the event loop isn't entered (or is continued from a watcher), i.e.,
|
||||
forking and then immediately registering a watcher for the child is fine,
|
||||
but forking and registering a watcher a few event loop iterations later is
|
||||
not.
|
||||
but forking and registering a watcher a few event loop iterations later or
|
||||
in the next callback invocation is not.
|
||||
|
||||
Only the default event loop is capable of handling signals, and therefore
|
||||
you can only register child watchers in the default event loop.
|
||||
|
||||
Due to some design glitches inside libev, child watchers will always be
|
||||
handled at maximum priority (their priority is set to C<EV_MAXPRI> by
|
||||
libev)
|
||||
|
||||
=head3 Process Interaction
|
||||
|
||||
Libev grabs C<SIGCHLD> as soon as the default event loop is
|
||||
@@ -2370,7 +2505,7 @@ callback, free it. Also, use no error checking, as usual.
|
||||
|
||||
ev_idle *idle_watcher = malloc (sizeof (ev_idle));
|
||||
ev_idle_init (idle_watcher, idle_cb);
|
||||
ev_idle_start (loop, idle_cb);
|
||||
ev_idle_start (loop, idle_watcher);
|
||||
|
||||
|
||||
=head2 C<ev_prepare> and C<ev_check> - customise your event loop!
|
||||
@@ -2473,7 +2608,7 @@ the callbacks for the IO/timeout watchers might not have been called yet.
|
||||
adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ()));
|
||||
|
||||
/* the callback is illegal, but won't be called as we stop during check */
|
||||
ev_timer_init (&tw, 0, timeout * 1e-3);
|
||||
ev_timer_init (&tw, 0, timeout * 1e-3, 0.);
|
||||
ev_timer_start (loop, &tw);
|
||||
|
||||
// create one ev_io per pollfd
|
||||
@@ -3645,9 +3780,19 @@ defined to be C<0>, then they are not.
|
||||
=item EV_MINIMAL
|
||||
|
||||
If you need to shave off some kilobytes of code at the expense of some
|
||||
speed, define this symbol to C<1>. Currently this is used to override some
|
||||
inlining decisions, saves roughly 30% code size on amd64. It also selects a
|
||||
much smaller 2-heap for timer management over the default 4-heap.
|
||||
speed (but with the full API), define this symbol to C<1>. Currently this
|
||||
is used to override some inlining decisions, saves roughly 30% code size
|
||||
on amd64. It also selects a much smaller 2-heap for timer management over
|
||||
the default 4-heap.
|
||||
|
||||
You can save even more by disabling watcher types you do not need
|
||||
and setting C<EV_MAXPRI> == C<EV_MINPRI>. Also, disabling C<assert>
|
||||
(C<-DNDEBUG>) will usually reduce code size a lot.
|
||||
|
||||
Defining C<EV_MINIMAL> to C<2> will additionally reduce the core API to
|
||||
provide a bare-bones event library. See C<ev.h> for details on what parts
|
||||
of the API are still available, and do not complain if this subset changes
|
||||
over time.
|
||||
|
||||
=item EV_PID_HASHSIZE
|
||||
|
||||
@@ -3843,14 +3988,152 @@ watcher callback into the event loop interested in the signal.
|
||||
|
||||
=back
|
||||
|
||||
=head4 THREAD LOCKING EXAMPLE
|
||||
|
||||
Here is a fictitious example of how to run an event loop in a different
|
||||
thread than where callbacks are being invoked and watchers are
|
||||
created/added/removed.
|
||||
|
||||
For a real-world example, see the C<EV::Loop::Async> perl module,
|
||||
which uses exactly this technique (which is suited for many high-level
|
||||
languages).
|
||||
|
||||
The example uses a pthread mutex to protect the loop data, a condition
|
||||
variable to wait for callback invocations, an async watcher to notify the
|
||||
event loop thread and an unspecified mechanism to wake up the main thread.
|
||||
|
||||
First, you need to associate some data with the event loop:
|
||||
|
||||
typedef struct {
|
||||
mutex_t lock; /* global loop lock */
|
||||
ev_async async_w;
|
||||
thread_t tid;
|
||||
cond_t invoke_cv;
|
||||
} userdata;
|
||||
|
||||
void prepare_loop (EV_P)
|
||||
{
|
||||
// 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);
|
||||
|
||||
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_invoke_pending_cb (EV_A_ l_invoke);
|
||||
ev_set_loop_release_cb (EV_A_ l_release, l_acquire);
|
||||
|
||||
// then create the thread running ev_loop
|
||||
pthread_create (&u->tid, 0, l_run, EV_A);
|
||||
}
|
||||
|
||||
The callback for the C<ev_async> watcher does nothing: the watcher is used
|
||||
solely to wake up the event loop so it takes notice of any new watchers
|
||||
that might have been added:
|
||||
|
||||
static void
|
||||
async_cb (EV_P_ ev_async *w, int revents)
|
||||
{
|
||||
// just used for the side effects
|
||||
}
|
||||
|
||||
The C<l_release> and C<l_acquire> callbacks simply unlock/lock the mutex
|
||||
protecting the loop data, respectively.
|
||||
|
||||
static void
|
||||
l_release (EV_P)
|
||||
{
|
||||
userdata *u = ev_userdata (EV_A);
|
||||
pthread_mutex_unlock (&u->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
l_acquire (EV_P)
|
||||
{
|
||||
userdata *u = ev_userdata (EV_A);
|
||||
pthread_mutex_lock (&u->lock);
|
||||
}
|
||||
|
||||
The event loop thread first acquires the mutex, and then jumps straight
|
||||
into C<ev_loop>:
|
||||
|
||||
void *
|
||||
l_run (void *thr_arg)
|
||||
{
|
||||
struct ev_loop *loop = (struct ev_loop *)thr_arg;
|
||||
|
||||
l_acquire (EV_A);
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
ev_loop (EV_A_ 0);
|
||||
l_release (EV_A);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instead of invoking all pending watchers, the C<l_invoke> callback will
|
||||
signal the main thread via some unspecified mechanism (signals? pipe
|
||||
writes? C<Async::Interrupt>?) and then waits until all pending watchers
|
||||
have been called (in a while loop because a) spurious wakeups are possible
|
||||
and b) skipping inter-thread-communication when there are no pending
|
||||
watchers is very beneficial):
|
||||
|
||||
static void
|
||||
l_invoke (EV_P)
|
||||
{
|
||||
userdata *u = ev_userdata (EV_A);
|
||||
|
||||
while (ev_pending_count (EV_A))
|
||||
{
|
||||
wake_up_other_thread_in_some_magic_or_not_so_magic_way ();
|
||||
pthread_cond_wait (&u->invoke_cv, &u->lock);
|
||||
}
|
||||
}
|
||||
|
||||
Now, whenever the main thread gets told to invoke pending watchers, it
|
||||
will grab the lock, call C<ev_invoke_pending> and then signal the loop
|
||||
thread to continue:
|
||||
|
||||
static void
|
||||
real_invoke_pending (EV_P)
|
||||
{
|
||||
userdata *u = ev_userdata (EV_A);
|
||||
|
||||
pthread_mutex_lock (&u->lock);
|
||||
ev_invoke_pending (EV_A);
|
||||
pthread_cond_signal (&u->invoke_cv);
|
||||
pthread_mutex_unlock (&u->lock);
|
||||
}
|
||||
|
||||
Whenever you want to start/stop a watcher or do other modifications to an
|
||||
event loop, you will now have to lock:
|
||||
|
||||
ev_timer timeout_watcher;
|
||||
userdata *u = ev_userdata (EV_A);
|
||||
|
||||
ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
|
||||
|
||||
pthread_mutex_lock (&u->lock);
|
||||
ev_timer_start (EV_A_ &timeout_watcher);
|
||||
ev_async_send (EV_A_ &u->async_w);
|
||||
pthread_mutex_unlock (&u->lock);
|
||||
|
||||
Note that sending the C<ev_async> watcher is required because otherwise
|
||||
an event loop currently blocking in the kernel will have no knowledge
|
||||
about the newly added timer. By waking up the loop it will pick up any new
|
||||
watchers in the next event loop iteration.
|
||||
|
||||
=head3 COROUTINES
|
||||
|
||||
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
|
||||
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.
|
||||
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 for coroutine switches as
|
||||
@@ -4067,7 +4350,9 @@ watchers.
|
||||
The type C<double> 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 IEEE 754 (basically all existing ones).
|
||||
implementations implementing IEEE 754, which is basically all existing
|
||||
ones. With IEEE 754 doubles, you get microsecond accuracy until at least
|
||||
2200.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
6
deps/libev/ev_epoll.c
vendored
6
deps/libev/ev_epoll.c
vendored
@@ -119,7 +119,11 @@ static void
|
||||
epoll_poll (EV_P_ ev_tstamp timeout)
|
||||
{
|
||||
int i;
|
||||
int eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.));
|
||||
int eventcnt;
|
||||
|
||||
EV_RELEASE_CB;
|
||||
eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.));
|
||||
EV_ACQUIRE_CB;
|
||||
|
||||
if (expect_false (eventcnt < 0))
|
||||
{
|
||||
|
||||
2
deps/libev/ev_kqueue.c
vendored
2
deps/libev/ev_kqueue.c
vendored
@@ -93,9 +93,11 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
|
||||
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
|
||||
}
|
||||
|
||||
EV_RELEASE_CB;
|
||||
ts.tv_sec = (time_t)timeout;
|
||||
ts.tv_nsec = (long)((timeout - (ev_tstamp)ts.tv_sec) * 1e9);
|
||||
res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts);
|
||||
EV_ACQUIRE_CB;
|
||||
kqueue_changecnt = 0;
|
||||
|
||||
if (expect_false (res < 0))
|
||||
|
||||
6
deps/libev/ev_poll.c
vendored
6
deps/libev/ev_poll.c
vendored
@@ -89,7 +89,11 @@ static void
|
||||
poll_poll (EV_P_ ev_tstamp timeout)
|
||||
{
|
||||
struct pollfd *p;
|
||||
int res = poll (polls, pollcnt, (int)ceil (timeout * 1000.));
|
||||
int res;
|
||||
|
||||
EV_RELEASE_CB;
|
||||
res = poll (polls, pollcnt, (int)ceil (timeout * 1000.));
|
||||
EV_ACQUIRE_CB;
|
||||
|
||||
if (expect_false (res < 0))
|
||||
{
|
||||
|
||||
2
deps/libev/ev_port.c
vendored
2
deps/libev/ev_port.c
vendored
@@ -85,9 +85,11 @@ port_poll (EV_P_ ev_tstamp timeout)
|
||||
struct timespec ts;
|
||||
uint_t nget = 1;
|
||||
|
||||
EV_RELEASE_CB;
|
||||
ts.tv_sec = (time_t)timeout;
|
||||
ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9;
|
||||
res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
|
||||
EV_ACQUIRE_CB;
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
|
||||
2
deps/libev/ev_select.c
vendored
2
deps/libev/ev_select.c
vendored
@@ -140,6 +140,7 @@ select_poll (EV_P_ ev_tstamp timeout)
|
||||
int res;
|
||||
int fd_setsize;
|
||||
|
||||
EV_RELEASE_CB;
|
||||
tv.tv_sec = (long)timeout;
|
||||
tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
|
||||
|
||||
@@ -166,6 +167,7 @@ select_poll (EV_P_ ev_tstamp timeout)
|
||||
#else
|
||||
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
|
||||
#endif
|
||||
EV_ACQUIRE_CB;
|
||||
|
||||
if (expect_false (res < 0))
|
||||
{
|
||||
|
||||
14
deps/libev/ev_vars.h
vendored
14
deps/libev/ev_vars.h
vendored
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* loop member variable declarations
|
||||
*
|
||||
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
||||
* Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
@@ -48,7 +48,7 @@ VARx(ev_tstamp, timeout_blocktime)
|
||||
|
||||
VARx(int, backend)
|
||||
VARx(int, activecnt) /* total number of active events ("refcount") */
|
||||
VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */
|
||||
VARx(unsigned char, loop_done) /* signal by ev_unloop */
|
||||
|
||||
VARx(int, backend_fd)
|
||||
VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */
|
||||
@@ -166,5 +166,15 @@ VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */
|
||||
VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
|
||||
#endif
|
||||
|
||||
#if EV_MINIMAL < 2 || EV_GENWRAP
|
||||
VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */
|
||||
VARx(unsigned int, loop_depth) /* #ev_loop enters - #ev_loop leaves */
|
||||
|
||||
VARx(void *, userdata)
|
||||
VAR (release_cb, void (*release_cb)(EV_P))
|
||||
VAR (acquire_cb, void (*acquire_cb)(EV_P))
|
||||
VAR (invoke_cb , void (*invoke_cb) (EV_P))
|
||||
#endif
|
||||
|
||||
#undef VARx
|
||||
|
||||
|
||||
23
deps/libev/ev_win32.c
vendored
23
deps/libev/ev_win32.c
vendored
@@ -133,22 +133,21 @@ fail:
|
||||
|
||||
#undef pipe
|
||||
#define pipe(filedes) ev_pipe (filedes)
|
||||
|
||||
static int
|
||||
ev_gettimeofday (struct timeval *tv, struct timezone *tz)
|
||||
|
||||
#define EV_HAVE_EV_TIME 1
|
||||
ev_tstamp
|
||||
ev_time (void)
|
||||
{
|
||||
struct _timeb tb;
|
||||
FILETIME ft;
|
||||
ULARGE_INTEGER ui;
|
||||
|
||||
_ftime (&tb);
|
||||
GetSystemTimeAsFileTime (&ft);
|
||||
ui.u.LowPart = ft.dwLowDateTime;
|
||||
ui.u.HighPart = ft.dwHighDateTime;
|
||||
|
||||
tv->tv_sec = (long)tb.time;
|
||||
tv->tv_usec = ((long)tb.millitm) * 1000;
|
||||
|
||||
return 0;
|
||||
/* msvc cannot convert ulonglong to double... yes, it is that sucky */
|
||||
return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7;
|
||||
}
|
||||
|
||||
#undef gettimeofday
|
||||
#define gettimeofday(tv,tz) ev_gettimeofday (tv, tz)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
16
deps/libev/ev_wrap.h
vendored
16
deps/libev/ev_wrap.h
vendored
@@ -8,7 +8,7 @@
|
||||
#define timeout_blocktime ((loop)->timeout_blocktime)
|
||||
#define backend ((loop)->backend)
|
||||
#define activecnt ((loop)->activecnt)
|
||||
#define loop_count ((loop)->loop_count)
|
||||
#define loop_done ((loop)->loop_done)
|
||||
#define backend_fd ((loop)->backend_fd)
|
||||
#define backend_fudge ((loop)->backend_fudge)
|
||||
#define backend_modify ((loop)->backend_modify)
|
||||
@@ -77,6 +77,12 @@
|
||||
#define fs_w ((loop)->fs_w)
|
||||
#define fs_2625 ((loop)->fs_2625)
|
||||
#define fs_hash ((loop)->fs_hash)
|
||||
#define loop_count ((loop)->loop_count)
|
||||
#define loop_depth ((loop)->loop_depth)
|
||||
#define userdata ((loop)->userdata)
|
||||
#define release_cb ((loop)->release_cb)
|
||||
#define acquire_cb ((loop)->acquire_cb)
|
||||
#define invoke_cb ((loop)->invoke_cb)
|
||||
#else
|
||||
#undef EV_WRAP_H
|
||||
#undef now_floor
|
||||
@@ -86,7 +92,7 @@
|
||||
#undef timeout_blocktime
|
||||
#undef backend
|
||||
#undef activecnt
|
||||
#undef loop_count
|
||||
#undef loop_done
|
||||
#undef backend_fd
|
||||
#undef backend_fudge
|
||||
#undef backend_modify
|
||||
@@ -155,4 +161,10 @@
|
||||
#undef fs_w
|
||||
#undef fs_2625
|
||||
#undef fs_hash
|
||||
#undef loop_count
|
||||
#undef loop_depth
|
||||
#undef userdata
|
||||
#undef release_cb
|
||||
#undef acquire_cb
|
||||
#undef invoke_cb
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user