Browse Source

Upgrade libev to 3.7

v0.7.4-release
Ryan 16 years ago
parent
commit
f4dfbe37a3
  1. 25
      deps/libev/Changes
  2. 49
      deps/libev/configure
  3. 2
      deps/libev/configure.ac
  4. 17
      deps/libev/ev++.h
  5. 448
      deps/libev/ev.3
  6. 183
      deps/libev/ev.c
  7. 66
      deps/libev/ev.h
  8. 325
      deps/libev/ev.pod
  9. 6
      deps/libev/ev_epoll.c
  10. 2
      deps/libev/ev_kqueue.c
  11. 6
      deps/libev/ev_poll.c
  12. 2
      deps/libev/ev_port.c
  13. 2
      deps/libev/ev_select.c
  14. 14
      deps/libev/ev_vars.h
  15. 21
      deps/libev/ev_win32.c
  16. 16
      deps/libev/ev_wrap.h

25
deps/libev/Changes

@ -1,5 +1,30 @@
Revision history for libev, a high-performance and full-featured event loop. 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 3.6 Tue Apr 28 02:49:30 CEST 2009
- multiple timers becoming ready within an event loop iteration - multiple timers becoming ready within an event loop iteration
will be invoked in the "correct" order now. will be invoked in the "correct" order now.

49
deps/libev/configure

@ -2207,7 +2207,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE=libev PACKAGE=libev
VERSION=3.6 VERSION=3.7
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -2348,7 +2348,6 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
# some platforms. # 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 "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
@ -4350,7 +4349,7 @@ ia64-*-hpux*)
;; ;;
*-*-irix6*) *-*-irix6*)
# Find out which ABI we are using. # 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 if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5 (eval $ac_compile) 2>&5
ac_status=$? ac_status=$?
@ -7396,11 +7395,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 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 if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # 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_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 10170 "configure" #line 10169 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@ -10267,7 +10266,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 10270 "configure" #line 10269 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@ -12668,11 +12667,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 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 if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 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 if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 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 if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized

2
deps/libev/configure.ac

@ -1,7 +1,7 @@
AC_INIT AC_INIT
AC_CONFIG_SRCDIR([ev_epoll.c]) 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]) AC_CONFIG_HEADERS([config.h])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE

17
deps/libev/ev++.h

@ -207,11 +207,6 @@ namespace ev {
#endif #endif
} }
unsigned int count () const throw ()
{
return ev_loop_count (EV_AX);
}
unsigned int backend () const throw () unsigned int backend () const throw ()
{ {
return ev_backend (EV_AX); return ev_backend (EV_AX);
@ -232,6 +227,17 @@ namespace ev {
ev_unref (EV_AX); 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 () void set_io_collect_interval (tstamp interval) throw ()
{ {
ev_set_io_collect_interval (EV_AX_ interval); ev_set_io_collect_interval (EV_AX_ interval);
@ -241,6 +247,7 @@ namespace ev {
{ {
ev_set_timeout_collect_interval (EV_AX_ interval); ev_set_timeout_collect_interval (EV_AX_ interval);
} }
#endif
// function callback // function callback
void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw () void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw ()

448
deps/libev/ev.3

@ -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: .\" 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) .de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v .if t .sp .5v
.if n .sp .if n .sp
@ -53,7 +45,7 @@
.el .ds Aq ' .el .ds Aq '
.\" .\"
.\" If the F register is turned on, we'll generate index entries on stderr for .\" 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 .\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion. .\" output yourself in some meaningful fashion.
.ie \nF \{\ .ie \nF \{\
@ -132,7 +124,7 @@
.\" ======================================================================== .\" ========================================================================
.\" .\"
.IX Title "LIBEV 3" .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 .\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents. .\" way too many mistakes in technical documents.
.if n .ad l .if n .ad l
@ -144,7 +136,7 @@ libev \- a high performance full\-featured event loop written in C
.Vb 1 .Vb 1
\& #include <ev.h> \& #include <ev.h>
.Ve .Ve
.Sh "\s-1EXAMPLE\s0 \s-1PROGRAM\s0" .SS "\s-1EXAMPLE\s0 \s-1PROGRAM\s0"
.IX Subsection "EXAMPLE PROGRAM" .IX Subsection "EXAMPLE PROGRAM"
.Vb 2 .Vb 2
\& // a single header file is required \& // 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 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 details of the event, and then hand it over to libev by \fIstarting\fR the
watcher. watcher.
.Sh "\s-1FEATURES\s0" .SS "\s-1FEATURES\s0"
.IX Subsection "FEATURES" .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 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 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). (\f(CW\*(C`ev_fork\*(C'\fR).
.PP .PP
It also is quite fast (see this It also is quite fast (see this
benchmark comparing it to libevent <benchmark> comparing it to libevent
for example). for example).
.Sh "\s-1CONVENTIONS\s0" .SS "\s-1CONVENTIONS\s0"
.IX Subsection "CONVENTIONS" .IX Subsection "CONVENTIONS"
Libev is very configurable. In this manual the default (and most common) Libev is very configurable. In this manual the default (and most common)
configuration will be described, which supports multiple event loops. For 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 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 name \f(CW\*(C`loop\*(C'\fR (which is always of type \f(CW\*(C`ev_loop *\*(C'\fR) will not have
this argument. this argument.
.Sh "\s-1TIME\s0 \s-1REPRESENTATION\s0" .SS "\s-1TIME\s0 \s-1REPRESENTATION\s0"
.IX Subsection "TIME REPRESENTATION" .IX Subsection "TIME REPRESENTATION"
Libev represents time as a single floating point number, representing Libev represents time as a single floating point number, representing
the (fractional) number of seconds since the (\s-1POSIX\s0) epoch (somewhere 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 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 \&\*(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. \&\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 .IP "unsigned int ev_backend (loop)" 4
.IX Item "unsigned int ev_backend (loop)" .IX Item "unsigned int ev_backend (loop)"
Returns one of the \f(CW\*(C`EVBACKEND_*\*(C'\fR flags indicating the event backend in 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, 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 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 \&\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 .Sp
Likewise, by setting a higher \fItimeout collect interval\fR you allow libev Likewise, by setting a higher \fItimeout collect interval\fR you allow libev
to spend more time collecting timeouts, at the expense of increased 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 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 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, 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 .Sp
Setting the \fItimeout collect interval\fR can improve the opportunity for Setting the \fItimeout collect interval\fR can improve the opportunity for
saving power, as the program will \*(L"bundle\*(R" timer callback invocations that 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 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 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. 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 .IP "ev_loop_verify (loop)" 4
.IX Item "ev_loop_verify (loop)" .IX Item "ev_loop_verify (loop)"
This function only does something when \f(CW\*(C`EV_VERIFY\*(C'\fR support has been 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 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 programs, though, as the fd could already be closed and reused for another
thing, so beware. 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" .IX Subsection "GENERIC WATCHER FUNCTIONS"
.ie n .IP """ev_init"" (ev_TYPE *watcher, callback)" 4 .ie n .IP """ev_init"" (ev_TYPE *watcher, callback)" 4
.el .IP "\f(CWev_init\fR (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 .Sp
Sometimes it can be useful to \*(L"poll\*(R" a watcher instead of waiting for its 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. 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" .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 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 and read at any time: libev will completely ignore it. This can be used
@ -1321,18 +1400,18 @@ programmers):
\& static void \& static void
\& t1_cb (EV_P_ ev_timer *w, int revents) \& 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)); \& (((char *)w) \- offsetof (struct my_biggy, t1));
\& } \& }
\& \&
\& static void \& static void
\& t2_cb (EV_P_ ev_timer *w, int revents) \& 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)); \& (((char *)w) \- offsetof (struct my_biggy, t2));
\& } \& }
.Ve .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" .IX Subsection "WATCHER PRIORITY MODELS"
Many event loops support \fIwatcher priorities\fR, which are usually small Many event loops support \fIwatcher priorities\fR, which are usually small
integers that influence the ordering of event callback invocation integers that influence the ordering of event callback invocation
@ -1415,7 +1494,7 @@ other events are pending:
\& } \& }
\& \&
\& static void \& static void
\& idle\-cb (EV_P_ ev_idle *w, int revents) \& idle_cb (EV_P_ ev_idle *w, int revents)
\& { \& {
\& // actual processing \& // actual processing
\& read (STDIN_FILENO, ...); \& 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 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 sensible or take immediate effect (or do anything at all), but libev will
not crash or malfunction in any way. not crash or malfunction in any way.
.ie n .Sh """ev_io"" \- is this file descriptor readable or writable?" .ie n .SS """ev_io"" \- is this file descriptor readable or writable?"
.el .Sh "\f(CWev_io\fP \- 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?" .IX Subsection "ev_io - is this file descriptor readable or writable?"
I/O watchers check whether a file descriptor is 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 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_io_start (loop, &stdin_readable);
\& ev_loop (loop, 0); \& ev_loop (loop, 0);
.Ve .Ve
.ie n .Sh """ev_timer"" \- relative and optionally repeating timeouts" .ie n .SS """ev_timer"" \- relative and optionally repeating timeouts"
.el .Sh "\f(CWev_timer\fP \- 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" .IX Subsection "ev_timer - relative and optionally repeating timeouts"
Timer watchers are simple relative timers that generate an event after a Timer watchers are simple relative timers that generate an event after a
given time, and optionally repeating in regular intervals after that. 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 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 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 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 before ones of the same priority with later time-out values (but this is
callback calls \f(CW\*(C`ev_loop\*(C'\fR recursively). no longer true when a callback calls \f(CW\*(C`ev_loop\*(C'\fR recursively).
.PP .PP
\fIBe smart about timeouts\fR \fIBe smart about timeouts\fR
.IX Subsection "Be smart about timeouts" .IX Subsection "Be smart about timeouts"
@ -1663,7 +1742,7 @@ member and \f(CW\*(C`ev_timer_again\*(C'\fR.
At start: At start:
.Sp .Sp
.Vb 3 .Vb 3
\& ev_timer_init (timer, callback); \& ev_init (timer, callback);
\& timer\->repeat = 60.; \& timer\->repeat = 60.;
\& ev_timer_again (loop, timer); \& ev_timer_again (loop, timer);
.Ve .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: callback, which will \*(L"do the right thing\*(R" and start the timer:
.Sp .Sp
.Vb 3 .Vb 3
\& ev_timer_init (timer, callback); \& ev_init (timer, callback);
\& last_activity = ev_now (loop); \& last_activity = ev_now (loop);
\& callback (loop, timer, EV_TIMEOUT); \& callback (loop, timer, EV_TIMEOUT);
.Ve .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 update of the time returned by \f(CW\*(C`ev_now ()\*(C'\fR by calling \f(CW\*(C`ev_now_update
()\*(C'\fR. ()\*(C'\fR.
.PP .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 \fIWatcher-Specific Functions and Data Members\fR
.IX Subsection "Watcher-Specific Functions and Data Members" .IX Subsection "Watcher-Specific Functions and Data Members"
.IP "ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)" 4 .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 .Sp
This sounds a bit complicated, see \*(L"Be smart about timeouts\*(R", above, for a This sounds a bit complicated, see \*(L"Be smart about timeouts\*(R", above, for a
usage example. 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 .IP "ev_tstamp repeat [read\-write]" 4
.IX Item "ev_tstamp repeat [read-write]" .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 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 \& // reset the timeout to start ticking again at 10 seconds
\& ev_timer_again (&mytimer); \& ev_timer_again (&mytimer);
.Ve .Ve
.ie n .Sh """ev_periodic"" \- to cron or not to cron?" .ie n .SS """ev_periodic"" \- to cron or not to cron?"
.el .Sh "\f(CWev_periodic\fP \- 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?" .IX Subsection "ev_periodic - to cron or not to cron?"
Periodic watchers are also timers of a kind, but they are very versatile Periodic watchers are also timers of a kind, but they are very versatile
(and unfortunately a bit complex). (and unfortunately a bit complex).
@ -2090,8 +2211,8 @@ Example: Call a callback every hour, starting now:
\& fmod (ev_now (loop), 3600.), 3600., 0); \& fmod (ev_now (loop), 3600.), 3600., 0);
\& ev_periodic_start (loop, &hourly_tick); \& ev_periodic_start (loop, &hourly_tick);
.Ve .Ve
.ie n .Sh """ev_signal"" \- signal me when a signal gets signalled!" .ie n .SS """ev_signal"" \- signal me when a signal gets signalled!"
.el .Sh "\f(CWev_signal\fP \- 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!" .IX Subsection "ev_signal - signal me when a signal gets signalled!"
Signal watchers will trigger an event when the process receives a specific Signal watchers will trigger an event when the process receives a specific
signal one or more times. Even though signals are very asynchronous, libev 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_init (&signal_watcher, sigint_cb, SIGINT);
\& ev_signal_start (loop, &signal_watcher); \& ev_signal_start (loop, &signal_watcher);
.Ve .Ve
.ie n .Sh """ev_child"" \- watch out for process status changes" .ie n .SS """ev_child"" \- watch out for process status changes"
.el .Sh "\f(CWev_child\fP \- 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" .IX Subsection "ev_child - watch out for process status changes"
Child watchers trigger when your process receives a \s-1SIGCHLD\s0 in response to 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 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 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., 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, 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 but forking and registering a watcher a few event loop iterations later or
not. in the next callback invocation is not.
.PP .PP
Only the default event loop is capable of handling signals, and therefore Only the default event loop is capable of handling signals, and therefore
you can only register child watchers in the default event loop. you can only register child watchers in the default event loop.
.PP .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 \fIProcess Interaction\fR
.IX Subsection "Process Interaction" .IX Subsection "Process Interaction"
.PP .PP
@ -2247,8 +2372,8 @@ its completion.
\& ev_child_start (EV_DEFAULT_ &cw); \& ev_child_start (EV_DEFAULT_ &cw);
\& } \& }
.Ve .Ve
.ie n .Sh """ev_stat"" \- did the file attributes just change?" .ie n .SS """ev_stat"" \- did the file attributes just change?"
.el .Sh "\f(CWev_stat\fP \- 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?" .IX Subsection "ev_stat - did the file attributes just change?"
This watches a file system path for attribute changes. That is, it calls 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) \&\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_stat_start (loop, &passwd);
\& ev_timer_init (&timer, timer_cb, 0., 1.02); \& ev_timer_init (&timer, timer_cb, 0., 1.02);
.Ve .Ve
.ie n .Sh """ev_idle"" \- when you've got nothing better to do..." .ie n .SS """ev_idle"" \- when you've got nothing better to do..."
.el .Sh "\f(CWev_idle\fP \- 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..." .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 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 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 *idle_watcher = malloc (sizeof (ev_idle));
\& ev_idle_init (idle_watcher, idle_cb); \& ev_idle_init (idle_watcher, idle_cb);
\& ev_idle_start (loop, idle_cb); \& ev_idle_start (loop, idle_watcher);
.Ve .Ve
.ie n .Sh """ev_prepare""\fP and \f(CW""ev_check"" \- customise your event loop!" .ie n .SS """ev_prepare"" and ""ev_check"" \- customise your event loop!"
.el .Sh "\f(CWev_prepare\fP and \f(CWev_check\fP \- 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!" .IX Subsection "ev_prepare and ev_check - customise your event loop!"
Prepare and check watchers are usually (but not always) used in pairs: Prepare and check watchers are usually (but not always) used in pairs:
prepare watchers get invoked before the process blocks and check watchers 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 ())); \& adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ()));
\& \&
\& /* the callback is illegal, but won\*(Aqt be called as we stop during check */ \& /* 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); \& ev_timer_start (loop, &tw);
\& \&
\& // create one ev_io per pollfd \& // create one ev_io per pollfd
@ -2723,8 +2848,8 @@ libglib event loop.
\& return got_events; \& return got_events;
\& } \& }
.Ve .Ve
.ie n .Sh """ev_embed"" \- when one backend isn't enough..." .ie n .SS """ev_embed"" \- when one backend isn't enough..."
.el .Sh "\f(CWev_embed\fP \- 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..." .IX Subsection "ev_embed - when one backend isn't enough..."
This is a rather advanced watcher type that lets you embed one event loop 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 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 \& // now use loop_socket for all sockets, and loop for everything else
.Ve .Ve
.ie n .Sh """ev_fork"" \- 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 .Sh "\f(CWev_fork\fP \- 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" .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 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 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 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, kind. There is a \f(CW\*(C`ev_fork_set\*(C'\fR macro, but using it is utterly pointless,
believe me. believe me.
.ie n .Sh """ev_async"" \- how to wake up another event loop" .ie n .SS """ev_async"" \- how to wake up another event loop"
.el .Sh "\f(CWev_async\fP \- 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" .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 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 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). it).
.PP .PP
Here is a list of things available in the \f(CW\*(C`ev\*(C'\fR namespace: 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 .el .IP "\f(CWev::READ\fR, \f(CWev::WRITE\fR etc." 4
.IX Item "ev::READ, ev::WRITE etc." .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. These are just enum values with the same values as the \f(CW\*(C`EV_READ\*(C'\fR etc.
macros from \fIev.h\fR. 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 .el .IP "\f(CWev::tstamp\fR, \f(CWev::now\fR" 4
.IX Item "ev::tstamp, ev::now" .IX Item "ev::tstamp, ev::now"
Aliases to the same types/functions as with the \f(CW\*(C`ev_\*(C'\fR prefix. 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 .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." .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 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 .IP "w\->stop ()" 4
.IX Item "w->stop ()" .IX Item "w->stop ()"
Stops the watcher if it is active. Again, no \f(CW\*(C`loop\*(C'\fR argument. 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 .el .IP "w\->again () (\f(CWev::timer\fR, \f(CWev::periodic\fR only)" 4
.IX Item "w->again () (ev::timer, ev::periodic only)" .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 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 .PP
To make it easier to write programs that cope with either variant, the To make it easier to write programs that cope with either variant, the
following macros are defined: 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 .el .IP "\f(CWEV_A\fR, \f(CWEV_A_\fR" 4
.IX Item "EV_A, EV_A_" .IX Item "EV_A, EV_A_"
This provides the loop \fIargument\fR for functions, if one is required (\*(L"ev 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 .Sp
It assumes the variable \f(CW\*(C`loop\*(C'\fR of type \f(CW\*(C`struct ev_loop *\*(C'\fR is in scope, 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. 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 .el .IP "\f(CWEV_P\fR, \f(CWEV_P_\fR" 4
.IX Item "EV_P, EV_P_" .IX Item "EV_P, EV_P_"
This provides the loop \fIparameter\fR for functions, if one is required (\*(L"ev 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 .Sp
It declares a parameter \f(CW\*(C`loop\*(C'\fR of type \f(CW\*(C`struct ev_loop *\*(C'\fR, quite 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. 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 .el .IP "\f(CWEV_DEFAULT\fR, \f(CWEV_DEFAULT_\fR" 4
.IX Item "EV_DEFAULT, EV_DEFAULT_" .IX Item "EV_DEFAULT, EV_DEFAULT_"
Similar to the other two macros, this gives you the value of the 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"). 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 .el .IP "\f(CWEV_DEFAULT_UC\fR, \f(CWEV_DEFAULT_UC_\fR" 4
.IX Item "EV_DEFAULT_UC, EV_DEFAULT_UC_" .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 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 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 you can easily upgrade by simply copying (or having a checked-out copy of
libev somewhere in your source tree). libev somewhere in your source tree).
.Sh "\s-1FILESETS\s0" .SS "\s-1FILESETS\s0"
.IX Subsection "FILESETS" .IX Subsection "FILESETS"
Depending on what features you need you need to include one or more sets of files Depending on what features you need you need to include one or more sets of files
in your application. in your application.
@ -3535,7 +3660,7 @@ For this of course you need the m4 file:
.Vb 1 .Vb 1
\& libev.m4 \& libev.m4
.Ve .Ve
.Sh "\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0" .SS "\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0"
.IX Subsection "PREPROCESSOR SYMBOLS/MACROS" .IX Subsection "PREPROCESSOR SYMBOLS/MACROS"
Libev can be configured via a variety of preprocessor symbols you have to 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 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 .IP "\s-1EV_MINIMAL\s0" 4
.IX Item "EV_MINIMAL" .IX Item "EV_MINIMAL"
If you need to shave off some kilobytes of code at the expense of some 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 speed (but with the full \s-1API\s0), define this symbol to \f(CW1\fR. Currently this
inlining decisions, saves roughly 30% code size on amd64. It also selects a is used to override some inlining decisions, saves roughly 30% code size
much smaller 2\-heap for timer management over the default 4\-heap. 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 .IP "\s-1EV_PID_HASHSIZE\s0" 4
.IX Item "EV_PID_HASHSIZE" .IX Item "EV_PID_HASHSIZE"
\&\f(CW\*(C`ev_child\*(C'\fR watchers use a small hash table to distribute workload by \&\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 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 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+. 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" .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 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 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 \& #define ev_check_stop myprefix_ev_check_stop
\& ... \& ...
.Ve .Ve
.Sh "\s-1EXAMPLES\s0" .SS "\s-1EXAMPLES\s0"
.IX Subsection "EXAMPLES" .IX Subsection "EXAMPLES"
For a real-world example of a program the includes libev For a real-world example of a program the includes libev
verbatim, you can have a look at the \s-1EV\s0 perl module 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 .Ve
.SH "INTERACTION WITH OTHER PROGRAMS OR LIBRARIES" .SH "INTERACTION WITH OTHER PROGRAMS OR LIBRARIES"
.IX Header "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" .IX Subsection "THREADS AND COROUTINES"
\fI\s-1THREADS\s0\fR \fI\s-1THREADS\s0\fR
.IX Subsection "THREADS" .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 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. watcher callback into the event loop interested in the signal.
.PP .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 \fI\s-1COROUTINES\s0\fR
.IX Subsection "COROUTINES" .IX Subsection "COROUTINES"
.PP .PP
Libev is very accommodating to coroutines (\*(L"cooperative threads\*(R"): Libev is very accommodating to coroutines (\*(L"cooperative threads\*(R"):
libev fully supports nesting calls to its functions from different 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 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 different coroutines, and switch freely between both coroutines running
loop, as long as you don't confuse yourself). The only exception is that the loop, as long as you don't confuse yourself). The only exception is
you must not do this from \f(CW\*(C`ev_periodic\*(C'\fR reschedule callbacks. that you must not do this from \f(CW\*(C`ev_periodic\*(C'\fR reschedule callbacks.
.PP .PP
Care has been taken to ensure that libev does not keep local state inside 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 \&\f(CW\*(C`ev_loop\*(C'\fR, and other calls do not usually allow for coroutine switches as
they do not call any callbacks. they do not call any callbacks.
.Sh "\s-1COMPILER\s0 \s-1WARNINGS\s0" .SS "\s-1COMPILER\s0 \s-1WARNINGS\s0"
.IX Subsection "COMPILER WARNINGS" .IX Subsection "COMPILER WARNINGS"
Depending on your compiler and compiler settings, you might get no or a Depending on your compiler and compiler settings, you might get no or a
lot of warnings when compiling libev code. Some people are apparently 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 with any compiler warnings enabled unless you are prepared to cope with
them (e.g. by ignoring them). Remember that warnings are just that: them (e.g. by ignoring them). Remember that warnings are just that:
warnings, not errors, or proof of bugs. warnings, not errors, or proof of bugs.
.Sh "\s-1VALGRIND\s0" .SS "\s-1VALGRIND\s0"
.IX Subsection "VALGRIND" .IX Subsection "VALGRIND"
Valgrind has a special section here because it is a popular tool that is Valgrind has a special section here because it is a popular tool that is
highly useful. Unfortunately, valgrind reports are very hard to interpret. 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. I suggest using suppression lists.
.SH "PORTABILITY NOTES" .SH "PORTABILITY NOTES"
.IX Header "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" .IX Subsection "WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS"
Win32 doesn't support any of the standards (e.g. \s-1POSIX\s0) that libev 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 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, (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 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. 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" .IX Subsection "PORTABILITY REQUIREMENTS"
In addition to a working ISO-C implementation and of course the In addition to a working ISO-C implementation and of course the
backend-specific APIs, libev relies on a few additional extensions: 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 .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 *." .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 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 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 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 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 .PP
If you know of other additional requirements drop me a note. If you know of other additional requirements drop me a note.
.SH "ALGORITHMIC COMPLEXITIES" .SH "ALGORITHMIC COMPLEXITIES"

183
deps/libev/ev.c

@ -59,6 +59,8 @@ extern "C" {
# define EV_USE_MONOTONIC 1 # define EV_USE_MONOTONIC 1
# endif # endif
# endif # endif
# elif !defined(EV_USE_CLOCK_SYSCALL)
# define EV_USE_CLOCK_SYSCALL 0
# endif # endif
# if HAVE_CLOCK_GETTIME # if HAVE_CLOCK_GETTIME
@ -284,6 +286,20 @@ extern "C" {
# define EV_HEAP_CACHE_AT !EV_MINIMAL # define EV_HEAP_CACHE_AT !EV_MINIMAL
#endif #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 */ /* this block fixes any misconfiguration where we know we run into trouble otherwise */
#ifndef CLOCK_MONOTONIC #ifndef CLOCK_MONOTONIC
@ -322,15 +338,6 @@ extern "C" {
# include <winsock.h> # include <winsock.h>
#endif #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 #if EV_USE_EVENTFD
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */ /* our minimum requirement is glibc 2.7 which has the stub, but not the header */
# include <stdint.h> # include <stdint.h>
@ -387,7 +394,12 @@ int eventfd (unsigned int initval, int flags);
#endif #endif
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1) #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) # define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
#endif
#define EMPTY /* required for microsofts broken pseudo-c compiler */ #define EMPTY /* required for microsofts broken pseudo-c compiler */
#define EMPTY2(a,b) /* used to suppress some warnings */ #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 */ /* file descriptor info structure */
typedef struct typedef struct
{ {
WL head; WL head;
unsigned char events; /* the events watched for */ 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 emask; /* the epoll backend stores the actual kernel mask in here */
unsigned char unused; unsigned char unused;
#if EV_USE_EPOLL #if EV_USE_EPOLL
@ -557,8 +572,21 @@ typedef struct
#endif #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_tstamp
ev_time (void) ev_time (void)
{ {
@ -575,6 +603,7 @@ ev_time (void)
gettimeofday (&tv, 0); gettimeofday (&tv, 0);
return tv.tv_sec + tv.tv_usec * 1e-6; return tv.tv_sec + tv.tv_usec * 1e-6;
} }
#endif
inline_size ev_tstamp inline_size ev_tstamp
get_clock (void) get_clock (void)
@ -620,7 +649,7 @@ ev_sleep (ev_tstamp delay)
tv.tv_usec = (long)((delay - (ev_tstamp)(tv.tv_sec)) * 1e6); 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 */ /* 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 */ /* by older ones */
select (0, 0, 0, 0, &tv); select (0, 0, 0, 0, &tv);
#endif #endif
@ -738,7 +767,7 @@ queue_events (EV_P_ W *events, int eventcnt, int type)
/*****************************************************************************/ /*****************************************************************************/
inline_speed void inline_speed void
fd_event (EV_P_ int fd, int revents) fd_event_nc (EV_P_ int fd, int revents)
{ {
ANFD *anfd = anfds + fd; ANFD *anfd = anfds + fd;
ev_io *w; 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 void
ev_feed_fd_event (EV_P_ int fd, int revents) ev_feed_fd_event (EV_P_ int fd, int revents)
{ {
if (fd >= 0 && fd < anfdmax) 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 */ /* 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].events = 0;
anfds [fd].emask = 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; return backend;
} }
#if EV_MINIMAL < 2
unsigned int unsigned int
ev_loop_count (EV_P) ev_loop_count (EV_P)
{ {
return loop_count; return loop_count;
} }
unsigned int
ev_loop_depth (EV_P)
{
return loop_depth;
}
void void
ev_set_io_collect_interval (EV_P_ ev_tstamp interval) 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; 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 */ /* initialise a loop structure, must be zero-initialised */
static void noinline static void noinline
loop_init (EV_P_ unsigned int flags) loop_init (EV_P_ unsigned int flags)
@ -1393,6 +1464,9 @@ loop_init (EV_P_ unsigned int flags)
mn_now = get_clock (); mn_now = get_clock ();
now_floor = mn_now; now_floor = mn_now;
rtmn_diff = ev_rt_now - mn_now; rtmn_diff = ev_rt_now - mn_now;
#if EV_MINIMAL < 2
invoke_cb = ev_invoke_pending;
#endif
io_blocktime = 0.; io_blocktime = 0.;
timeout_blocktime = 0.; timeout_blocktime = 0.;
@ -1596,6 +1670,7 @@ ev_loop_fork (EV_P)
{ {
postfork = 1; /* must be in line with ev_default_fork */ postfork = 1; /* must be in line with ev_default_fork */
} }
#endif /* multiplicity */
#if EV_VERIFY #if EV_VERIFY
static void noinline static void noinline
@ -1633,6 +1708,7 @@ array_verify (EV_P_ W *ws, int cnt)
} }
#endif #endif
#if EV_MINIMAL < 2
void void
ev_loop_verify (EV_P) ev_loop_verify (EV_P)
{ {
@ -1695,8 +1771,7 @@ ev_loop_verify (EV_P)
# endif # endif
#endif #endif
} }
#endif
#endif /* multiplicity */
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
struct ev_loop * struct ev_loop *
@ -1767,8 +1842,20 @@ ev_invoke (EV_P_ void *w, int revents)
EV_CB_INVOKE ((W)w, revents); EV_CB_INVOKE ((W)w, revents);
} }
inline_speed void unsigned int
call_pending (EV_P) 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; int pri;
@ -1950,11 +2037,10 @@ timers_reschedule (EV_P_ ev_tstamp adjust)
inline_speed void inline_speed void
time_update (EV_P_ ev_tstamp max_block) time_update (EV_P_ ev_tstamp max_block)
{ {
int i;
#if EV_USE_MONOTONIC #if EV_USE_MONOTONIC
if (expect_true (have_monotonic)) if (expect_true (have_monotonic))
{ {
int i;
ev_tstamp odiff = rtmn_diff; ev_tstamp odiff = rtmn_diff;
mn_now = get_clock (); mn_now = get_clock ();
@ -2014,14 +2100,18 @@ time_update (EV_P_ ev_tstamp max_block)
} }
} }
static int loop_done;
void void
ev_loop (EV_P_ int flags) 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; 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 do
{ {
@ -2044,7 +2134,7 @@ ev_loop (EV_P_ int flags)
if (forkcnt) if (forkcnt)
{ {
queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK); queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
call_pending (EV_A); EV_INVOKE_PENDING;
} }
#endif #endif
@ -2052,9 +2142,12 @@ ev_loop (EV_P_ int flags)
if (expect_false (preparecnt)) if (expect_false (preparecnt))
{ {
queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE); 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 */ /* we might have forked, so reify kernel state if necessary */
if (expect_false (postfork)) if (expect_false (postfork))
loop_fork (EV_A); loop_fork (EV_A);
@ -2069,6 +2162,9 @@ ev_loop (EV_P_ int flags)
if (expect_true (!(flags & EVLOOP_NONBLOCK || idleall || !activecnt))) 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 */ /* update time to cancel out callback processing overhead */
time_update (EV_A_ 1e100); time_update (EV_A_ 1e100);
@ -2088,23 +2184,32 @@ ev_loop (EV_P_ int flags)
} }
#endif #endif
/* don't let timeouts decrease the waittime below timeout_blocktime */
if (expect_false (waittime < timeout_blocktime)) if (expect_false (waittime < timeout_blocktime))
waittime = timeout_blocktime; waittime = timeout_blocktime;
sleeptime = waittime - backend_fudge; /* extra check because io_blocktime is commonly 0 */
if (expect_false (io_blocktime))
{
sleeptime = io_blocktime - (mn_now - prev_mn_now);
if (expect_true (sleeptime > io_blocktime)) if (sleeptime > waittime - backend_fudge)
sleeptime = io_blocktime; sleeptime = waittime - backend_fudge;
if (sleeptime) if (expect_true (sleeptime > 0.))
{ {
ev_sleep (sleeptime); ev_sleep (sleeptime);
waittime -= sleeptime; waittime -= sleeptime;
} }
} }
}
#if EV_MINIMAL < 2
++loop_count; ++loop_count;
#endif
assert ((loop_done = EVUNLOOP_RECURSE, 1)); /* assert for side effect */
backend_poll (EV_A_ waittime); backend_poll (EV_A_ waittime);
assert ((loop_done = EVUNLOOP_CANCEL, 1)); /* assert for side effect */
/* update ev_rt_now, do magic */ /* update ev_rt_now, do magic */
time_update (EV_A_ waittime + sleeptime); time_update (EV_A_ waittime + sleeptime);
@ -2125,7 +2230,7 @@ ev_loop (EV_P_ int flags)
if (expect_false (checkcnt)) if (expect_false (checkcnt))
queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK); queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
call_pending (EV_A); EV_INVOKE_PENDING;
} }
while (expect_true ( while (expect_true (
activecnt activecnt
@ -2135,6 +2240,10 @@ ev_loop (EV_P_ int flags)
if (loop_done == EVUNLOOP_ONE) if (loop_done == EVUNLOOP_ONE)
loop_done = EVUNLOOP_CANCEL; loop_done = EVUNLOOP_CANCEL;
#if EV_MINIMAL < 2
--loop_depth;
#endif
} }
void void
@ -2236,10 +2345,10 @@ ev_clear_pending (EV_P_ void *w)
inline_size void inline_size void
pri_adjust (EV_P_ W w) 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_MINPRI ? EV_MINPRI : pri;
pri = pri > EV_MAXPRI ? EV_MAXPRI : pri; pri = pri > EV_MAXPRI ? EV_MAXPRI : pri;
w->priority = pri; ev_set_priority (w, pri);
} }
inline_speed void 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); array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
wlist_add (&anfds[fd].head, (WL)w); 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; w->events &= ~EV__IOFDSET;
EV_FREQUENT_CHECK; EV_FREQUENT_CHECK;
@ -2380,6 +2489,12 @@ ev_timer_again (EV_P_ ev_timer *w)
EV_FREQUENT_CHECK; 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 #if EV_PERIODIC_ENABLE
void noinline void noinline
ev_periodic_start (EV_P_ ev_periodic *w) ev_periodic_start (EV_P_ ev_periodic *w)
@ -2490,7 +2605,7 @@ ev_signal_start (EV_P_ ev_signal *w)
#if _WIN32 #if _WIN32
signal (w->signum, ev_sighandler); signal (w->signum, ev_sighandler);
#else #else
struct sigaction sa; struct sigaction sa = { };
sa.sa_handler = ev_sighandler; sa.sa_handler = ev_sighandler;
sigfillset (&sa.sa_mask); sigfillset (&sa.sa_mask);
sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */ sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */

66
deps/libev/ev.h

@ -163,7 +163,7 @@ struct ev_loop;
#endif #endif
#define EV_VERSION_MAJOR 3 #define EV_VERSION_MAJOR 3
#define EV_VERSION_MINOR 0 #define EV_VERSION_MINOR 7
#ifndef EV_CB_DECLARE #ifndef EV_CB_DECLARE
# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents); # 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. * 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 */ /* shared by all watchers */
#define EV_WATCHER(type) \ #define EV_WATCHER(type) \
int active; /* private */ \ int active; /* private */ \
int pending; /* private */ \ int pending; /* private */ \
int priority; /* private */ \ EV_DECL_PRIORITY /* private */ \
EV_COMMON /* rw */ \ EV_COMMON /* rw */ \
EV_CB_DECLARE (type) /* private */ EV_CB_DECLARE (type) /* private */
@ -461,10 +467,8 @@ ev_default_loop (unsigned int flags)
struct ev_loop *ev_loop_new (unsigned int flags); struct ev_loop *ev_loop_new (unsigned int flags);
void ev_loop_destroy (EV_P); void ev_loop_destroy (EV_P);
void ev_loop_fork (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 */ 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 #else
@ -498,6 +502,10 @@ void ev_default_destroy (void); /* destroy the default loop */
/* you can actually call it at any time, anywhere :) */ /* you can actually call it at any time, anywhere :) */
void ev_default_fork (void); 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 #if EV_WALK_ENABLE
/* walk (almost) all watchers in the loop of a given type, invoking the */ /* walk (almost) all watchers in the loop of a given type, invoking the */
/* callback on every such watcher. The callback might stop the watcher, */ /* 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)); void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w));
#endif #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 */ #endif /* prototypes */
#define EVLOOP_NONBLOCK 1 /* do not block/wait */ #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_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_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 * 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. * should not keep ev_loop from running, unref() after starting, and ref() before stopping.
*/ */
void ev_ref (EV_P); void ev_ref (EV_P);
void ev_unref (EV_P); void ev_unref (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. * stop/start the timer handling.
*/ */
void ev_suspend (EV_P); void ev_suspend (EV_P);
void ev_resume (EV_P); void ev_resume (EV_P);
#endif
/*
* 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);
#endif #endif
/* these may evaluate ev multiple times, and the other arguments at most once */ /* 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 */ /* 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 { \ #define ev_init(ev,cb_) do { \
((ev_watcher *)(void *)(ev))->active = \ ((ev_watcher *)(void *)(ev))->active = \
((ev_watcher *)(void *)(ev))->pending = \ ((ev_watcher *)(void *)(ev))->pending = 0; \
((ev_watcher *)(void *)(ev))->priority = 0; \ ev_set_priority ((ev), 0); \
ev_set_cb ((ev), cb_); \ ev_set_cb ((ev), cb_); \
} while (0) } 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_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_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_cb(ev) (ev)->cb /* rw */
#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) # define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri)
#endif
#define ev_periodic_at(ev) (((ev_watcher_time *)(ev))->at + 0.) #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); 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 */ /* 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); 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 #if EV_PERIODIC_ENABLE
void ev_periodic_start (EV_P_ ev_periodic *w); void ev_periodic_start (EV_P_ ev_periodic *w);

325
deps/libev/ev.pod

@ -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 "ticks" the number of loop iterations), as it roughly corresponds with
C<ev_prepare> and C<ev_check> calls. 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) =item unsigned int ev_backend (loop)
Returns one of the C<EVBACKEND_*> flags indicating the event backend in 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, 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 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 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 Likewise, by setting a higher I<timeout collect interval> you allow libev
to spend more time collecting timeouts, at the expense of increased 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 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 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>, 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 Setting the I<timeout collect interval> can improve the opportunity for
saving power, as the program will "bundle" timer callback invocations that 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 reduce iterations/wake-ups is to use C<ev_periodic> watchers and make sure
they fire on, say, one-second boundaries only. 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) =item ev_loop_verify (loop)
This function only does something when C<EV_VERIFY> support has been This function only does something when C<EV_VERIFY> support has been
@ -1186,14 +1275,14 @@ programmers):
static void static void
t1_cb (EV_P_ ev_timer *w, int revents) 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)); (((char *)w) - offsetof (struct my_biggy, t1));
} }
static void static void
t2_cb (EV_P_ ev_timer *w, int revents) 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)); (((char *)w) - offsetof (struct my_biggy, t2));
} }
@ -1279,7 +1368,7 @@ other events are pending:
} }
static void static void
idle-cb (EV_P_ ev_idle *w, int revents) idle_cb (EV_P_ ev_idle *w, int revents)
{ {
// actual processing // actual processing
read (STDIN_FILENO, ...); 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 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 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 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 before ones of the same priority with later time-out values (but this is
callback calls C<ev_loop> recursively). no longer true when a callback calls C<ev_loop> recursively).
=head3 Be smart about timeouts =head3 Be smart about timeouts
@ -1525,7 +1614,7 @@ member and C<ev_timer_again>.
At start: At start:
ev_timer_init (timer, callback); ev_init (timer, callback);
timer->repeat = 60.; timer->repeat = 60.;
ev_timer_again (loop, timer); 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 to the current time (meaning we just have some activity :), then call the
callback, which will "do the right thing" and start the timer: 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); last_activity = ev_now (loop);
callback (loop, timer, EV_TIMEOUT); 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 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 =head3 Watcher-Specific Functions and Data Members
=over 4 =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 This sounds a bit complicated, see L<Be smart about timeouts>, above, for a
usage example. 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] =item ev_tstamp repeat [read-write]
The current C<repeat> value. Will be used each time the watcher times out 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 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., 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, 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 but forking and registering a watcher a few event loop iterations later or
not. in the next callback invocation is not.
Only the default event loop is capable of handling signals, and therefore Only the default event loop is capable of handling signals, and therefore
you can only register child watchers in the default event loop. 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 =head3 Process Interaction
Libev grabs C<SIGCHLD> as soon as the default event loop is 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 *idle_watcher = malloc (sizeof (ev_idle));
ev_idle_init (idle_watcher, idle_cb); 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! =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 ())); adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ()));
/* the callback is illegal, but won't be called as we stop during check */ /* 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); ev_timer_start (loop, &tw);
// create one ev_io per pollfd // create one ev_io per pollfd
@ -3645,9 +3780,19 @@ defined to be C<0>, then they are not.
=item EV_MINIMAL =item EV_MINIMAL
If you need to shave off some kilobytes of code at the expense of some 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 speed (but with the full API), define this symbol to C<1>. Currently this
inlining decisions, saves roughly 30% code size on amd64. It also selects a is used to override some inlining decisions, saves roughly 30% code size
much smaller 2-heap for timer management over the default 4-heap. 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 =item EV_PID_HASHSIZE
@ -3843,14 +3988,152 @@ watcher callback into the event loop interested in the signal.
=back =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 =head3 COROUTINES
Libev is very accommodating to coroutines ("cooperative threads"): Libev is very accommodating to coroutines ("cooperative threads"):
libev fully supports nesting calls to its functions from different 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 coroutines (e.g. you can call C<ev_loop> on the same loop from two
different coroutines, and switch freely between both coroutines running the different coroutines, and switch freely between both coroutines running
loop, as long as you don't confuse yourself). The only exception is that the loop, as long as you don't confuse yourself). The only exception is
you must not do this from C<ev_periodic> reschedule callbacks. 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 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 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 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 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 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 =back

6
deps/libev/ev_epoll.c

@ -119,7 +119,11 @@ static void
epoll_poll (EV_P_ ev_tstamp timeout) epoll_poll (EV_P_ ev_tstamp timeout)
{ {
int i; 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)) if (expect_false (eventcnt < 0))
{ {

2
deps/libev/ev_kqueue.c

@ -93,9 +93,11 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
} }
EV_RELEASE_CB;
ts.tv_sec = (time_t)timeout; ts.tv_sec = (time_t)timeout;
ts.tv_nsec = (long)((timeout - (ev_tstamp)ts.tv_sec) * 1e9); ts.tv_nsec = (long)((timeout - (ev_tstamp)ts.tv_sec) * 1e9);
res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts);
EV_ACQUIRE_CB;
kqueue_changecnt = 0; kqueue_changecnt = 0;
if (expect_false (res < 0)) if (expect_false (res < 0))

6
deps/libev/ev_poll.c

@ -89,7 +89,11 @@ static void
poll_poll (EV_P_ ev_tstamp timeout) poll_poll (EV_P_ ev_tstamp timeout)
{ {
struct pollfd *p; 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)) if (expect_false (res < 0))
{ {

2
deps/libev/ev_port.c

@ -85,9 +85,11 @@ port_poll (EV_P_ ev_tstamp timeout)
struct timespec ts; struct timespec ts;
uint_t nget = 1; uint_t nget = 1;
EV_RELEASE_CB;
ts.tv_sec = (time_t)timeout; ts.tv_sec = (time_t)timeout;
ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9; ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9;
res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts); res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
EV_ACQUIRE_CB;
if (res == -1) if (res == -1)
{ {

2
deps/libev/ev_select.c

@ -140,6 +140,7 @@ select_poll (EV_P_ ev_tstamp timeout)
int res; int res;
int fd_setsize; int fd_setsize;
EV_RELEASE_CB;
tv.tv_sec = (long)timeout; tv.tv_sec = (long)timeout;
tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6); tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
@ -166,6 +167,7 @@ select_poll (EV_P_ ev_tstamp timeout)
#else #else
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
#endif #endif
EV_ACQUIRE_CB;
if (expect_false (res < 0)) if (expect_false (res < 0))
{ {

14
deps/libev/ev_vars.h

@ -1,7 +1,7 @@
/* /*
* loop member variable declarations * 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modifica- * 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, backend)
VARx(int, activecnt) /* total number of active events ("refcount") */ 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(int, backend_fd)
VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */ 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]) VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
#endif #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 #undef VARx

21
deps/libev/ev_win32.c

@ -134,21 +134,20 @@ fail:
#undef pipe #undef pipe
#define pipe(filedes) ev_pipe (filedes) #define pipe(filedes) ev_pipe (filedes)
static int #define EV_HAVE_EV_TIME 1
ev_gettimeofday (struct timeval *tv, struct timezone *tz) ev_tstamp
ev_time (void)
{ {
struct _timeb tb; FILETIME ft;
ULARGE_INTEGER ui;
_ftime (&tb);
tv->tv_sec = (long)tb.time; GetSystemTimeAsFileTime (&ft);
tv->tv_usec = ((long)tb.millitm) * 1000; ui.u.LowPart = ft.dwLowDateTime;
ui.u.HighPart = ft.dwHighDateTime;
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 #endif

16
deps/libev/ev_wrap.h

@ -8,7 +8,7 @@
#define timeout_blocktime ((loop)->timeout_blocktime) #define timeout_blocktime ((loop)->timeout_blocktime)
#define backend ((loop)->backend) #define backend ((loop)->backend)
#define activecnt ((loop)->activecnt) #define activecnt ((loop)->activecnt)
#define loop_count ((loop)->loop_count) #define loop_done ((loop)->loop_done)
#define backend_fd ((loop)->backend_fd) #define backend_fd ((loop)->backend_fd)
#define backend_fudge ((loop)->backend_fudge) #define backend_fudge ((loop)->backend_fudge)
#define backend_modify ((loop)->backend_modify) #define backend_modify ((loop)->backend_modify)
@ -77,6 +77,12 @@
#define fs_w ((loop)->fs_w) #define fs_w ((loop)->fs_w)
#define fs_2625 ((loop)->fs_2625) #define fs_2625 ((loop)->fs_2625)
#define fs_hash ((loop)->fs_hash) #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 #else
#undef EV_WRAP_H #undef EV_WRAP_H
#undef now_floor #undef now_floor
@ -86,7 +92,7 @@
#undef timeout_blocktime #undef timeout_blocktime
#undef backend #undef backend
#undef activecnt #undef activecnt
#undef loop_count #undef loop_done
#undef backend_fd #undef backend_fd
#undef backend_fudge #undef backend_fudge
#undef backend_modify #undef backend_modify
@ -155,4 +161,10 @@
#undef fs_w #undef fs_w
#undef fs_2625 #undef fs_2625
#undef fs_hash #undef fs_hash
#undef loop_count
#undef loop_depth
#undef userdata
#undef release_cb
#undef acquire_cb
#undef invoke_cb
#endif #endif

Loading…
Cancel
Save