Commit 7fa9deca authored by Jason Madden's avatar Jason Madden Committed by GitHub

Merge pull request #1756 from gevent/libev-4.33

Update to libev 4.33. Fixes #1754.
parents f7b2b6dc 6ac4a329
...@@ -75,8 +75,13 @@ def build_extension(): ...@@ -75,8 +75,13 @@ def build_extension():
'src/gevent/libev/stathelper.c', 'src/gevent/libev/stathelper.c',
'src/gevent/libev/libev*.h', 'src/gevent/libev/libev*.h',
'deps/libev/*.[ch]')) 'deps/libev/*.[ch]'))
# While we don't actually use periodic watchers,
# on Windows we need to enable them to work around an issue
# in libev 4.33 where ``have_monotonic`` is not defined.
EV_PERIODIC_ENABLE = "0"
if WIN: if WIN:
CORE.define_macros.append(('EV_STANDALONE', '1')) CORE.define_macros.append(('EV_STANDALONE', '1'))
EV_PERIODIC_ENABLE = "1"
# QQQ libev can also use -lm, however it seems to be added implicitly # QQQ libev can also use -lm, however it seems to be added implicitly
if LIBEV_EMBED: if LIBEV_EMBED:
...@@ -88,7 +93,7 @@ def build_extension(): ...@@ -88,7 +93,7 @@ def build_extension():
# libev watchers that we don't use currently: # libev watchers that we don't use currently:
('EV_CLEANUP_ENABLE', '0'), ('EV_CLEANUP_ENABLE', '0'),
('EV_EMBED_ENABLE', '0'), ('EV_EMBED_ENABLE', '0'),
("EV_PERIODIC_ENABLE", '0'), ("EV_PERIODIC_ENABLE", EV_PERIODIC_ENABLE),
# Time keeping. If possible, use the realtime and/or monotonic # Time keeping. If possible, use the realtime and/or monotonic
# clocks. On Linux, this can reduce the number of observable syscalls. # clocks. On Linux, this can reduce the number of observable syscalls.
# On older linux, such as the version in manylinux2010, this requires # On older linux, such as the version in manylinux2010, this requires
......
Revision history for libev, a high-performance and full-featured event loop. Revision history for libev, a high-performance and full-featured event loop.
TODO: revisit 59.x timer in the light of modern powersaving TODO: for next ABI/API change, consider moving EV__IOFDSSET into io->fd instead and provide a getter.
TODO: document EV_TSTAMP_T TODO: document EV_TSTAMP_T
4.33 Wed Mar 18 13:22:29 CET 2020
- no changes w.r.t. 4.32.
4.32 (EV only)
- the 4.31 timerfd code wrongly changed the priority of the signal
fd watcher, which is usually harmless unless signal fds are
also used (found via cpan tester service).
- the documentation wrongly claimed that user may modify fd and events
members in io watchers when the watcher was stopped
(found by b_jonas).
- new ev_io_modify mutator which changes only the events member,
which can be faster. also added ev::io::set (int events) method
to ev++.h.
- officially allow a zero events mask for io watchers. this should
work with older libev versions as well but was not officially
allowed before.
- do not wake up every minute when timerfd is used to detect timejumps.
- do not wake up every minute when periodics are disabled and we have
a monotonic clock.
- support a lot more "uncommon" compile time configurations,
such as ev_embed enabled but ev_timer disabled.
- use a start/stop wrapper class to reduce code duplication in
ev++.h and make it needlessly more c++-y.
- the linux aio backend is no longer compiled in by default.
- update to libecb version 0x00010008.
4.31 Fri Dec 20 21:58:29 CET 2019 4.31 Fri Dec 20 21:58:29 CET 2019
- handle backends with minimum wait time a bit better by not - handle backends with minimum wait time a bit better by not
waiting in the presence of already-expired timers waiting in the presence of already-expired timers
......
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for libev 4.31. # Generated by GNU Autoconf 2.69 for libev 4.33.
# #
# #
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
...@@ -587,8 +587,8 @@ MAKEFLAGS= ...@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='libev' PACKAGE_NAME='libev'
PACKAGE_TARNAME='libev' PACKAGE_TARNAME='libev'
PACKAGE_VERSION='4.31' PACKAGE_VERSION='4.33'
PACKAGE_STRING='libev 4.31' PACKAGE_STRING='libev 4.33'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='' PACKAGE_URL=''
...@@ -1325,7 +1325,7 @@ if test "$ac_init_help" = "long"; then ...@@ -1325,7 +1325,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures libev 4.31 to adapt to many kinds of systems. \`configure' configures libev 4.33 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
...@@ -1396,7 +1396,7 @@ fi ...@@ -1396,7 +1396,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of libev 4.31:";; short | recursive ) echo "Configuration of libev 4.33:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
...@@ -1509,7 +1509,7 @@ fi ...@@ -1509,7 +1509,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
libev configure 4.31 libev configure 4.33
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
...@@ -1928,7 +1928,7 @@ cat >config.log <<_ACEOF ...@@ -1928,7 +1928,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by libev $as_me 4.31, which was It was created by libev $as_me 4.33, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
...@@ -2795,7 +2795,7 @@ fi ...@@ -2795,7 +2795,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='libev' PACKAGE='libev'
VERSION='4.31' VERSION='4.33'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
...@@ -12871,7 +12871,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ...@@ -12871,7 +12871,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by libev $as_me 4.31, which was This file was extended by libev $as_me 4.33, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
...@@ -12937,7 +12937,7 @@ _ACEOF ...@@ -12937,7 +12937,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
libev config.status 4.31 libev config.status 4.33
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"
......
/* /*
* libev simple C++ wrapper classes * libev simple C++ wrapper classes
* *
* Copyright (c) 2007,2008,2010,2018 Marc Alexander Lehmann <libev@schmorp.de> * Copyright (c) 2007,2008,2010,2018,2020 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-
...@@ -421,6 +421,24 @@ namespace ev { ...@@ -421,6 +421,24 @@ namespace ev {
template<class ev_watcher, class watcher> template<class ev_watcher, class watcher>
struct base : ev_watcher struct base : ev_watcher
{ {
// scoped pause/unpause of a watcher
struct freeze_guard
{
watcher &w;
bool active;
freeze_guard (watcher *self) EV_NOEXCEPT
: w (*self), active (w.is_active ())
{
if (active) w.stop ();
}
~freeze_guard ()
{
if (active) w.start ();
}
};
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
EV_PX; EV_PX;
...@@ -614,18 +632,14 @@ namespace ev { ...@@ -614,18 +632,14 @@ namespace ev {
EV_BEGIN_WATCHER (io, io) EV_BEGIN_WATCHER (io, io)
void set (int fd, int events) EV_NOEXCEPT void set (int fd, int events) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop ();
ev_io_set (static_cast<ev_io *>(this), fd, events); ev_io_set (static_cast<ev_io *>(this), fd, events);
if (active) start ();
} }
void set (int events) EV_NOEXCEPT void set (int events) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop (); ev_io_modify (static_cast<ev_io *>(this), events);
ev_io_set (static_cast<ev_io *>(this), fd, events);
if (active) start ();
} }
void start (int fd, int events) EV_NOEXCEPT void start (int fd, int events) EV_NOEXCEPT
...@@ -638,10 +652,8 @@ namespace ev { ...@@ -638,10 +652,8 @@ namespace ev {
EV_BEGIN_WATCHER (timer, timer) EV_BEGIN_WATCHER (timer, timer)
void set (ev_tstamp after, ev_tstamp repeat = 0.) EV_NOEXCEPT void set (ev_tstamp after, ev_tstamp repeat = 0.) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop ();
ev_timer_set (static_cast<ev_timer *>(this), after, repeat); ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
if (active) start ();
} }
void start (ev_tstamp after, ev_tstamp repeat = 0.) EV_NOEXCEPT void start (ev_tstamp after, ev_tstamp repeat = 0.) EV_NOEXCEPT
...@@ -665,10 +677,8 @@ namespace ev { ...@@ -665,10 +677,8 @@ namespace ev {
EV_BEGIN_WATCHER (periodic, periodic) EV_BEGIN_WATCHER (periodic, periodic)
void set (ev_tstamp at, ev_tstamp interval = 0.) EV_NOEXCEPT void set (ev_tstamp at, ev_tstamp interval = 0.) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop ();
ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0); ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
if (active) start ();
} }
void start (ev_tstamp at, ev_tstamp interval = 0.) EV_NOEXCEPT void start (ev_tstamp at, ev_tstamp interval = 0.) EV_NOEXCEPT
...@@ -688,10 +698,8 @@ namespace ev { ...@@ -688,10 +698,8 @@ namespace ev {
EV_BEGIN_WATCHER (sig, signal) EV_BEGIN_WATCHER (sig, signal)
void set (int signum) EV_NOEXCEPT void set (int signum) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop ();
ev_signal_set (static_cast<ev_signal *>(this), signum); ev_signal_set (static_cast<ev_signal *>(this), signum);
if (active) start ();
} }
void start (int signum) EV_NOEXCEPT void start (int signum) EV_NOEXCEPT
...@@ -706,10 +714,8 @@ namespace ev { ...@@ -706,10 +714,8 @@ namespace ev {
EV_BEGIN_WATCHER (child, child) EV_BEGIN_WATCHER (child, child)
void set (int pid, int trace = 0) EV_NOEXCEPT void set (int pid, int trace = 0) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop ();
ev_child_set (static_cast<ev_child *>(this), pid, trace); ev_child_set (static_cast<ev_child *>(this), pid, trace);
if (active) start ();
} }
void start (int pid, int trace = 0) EV_NOEXCEPT void start (int pid, int trace = 0) EV_NOEXCEPT
...@@ -724,10 +730,8 @@ namespace ev { ...@@ -724,10 +730,8 @@ namespace ev {
EV_BEGIN_WATCHER (stat, stat) EV_BEGIN_WATCHER (stat, stat)
void set (const char *path, ev_tstamp interval = 0.) EV_NOEXCEPT void set (const char *path, ev_tstamp interval = 0.) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop ();
ev_stat_set (static_cast<ev_stat *>(this), path, interval); ev_stat_set (static_cast<ev_stat *>(this), path, interval);
if (active) start ();
} }
void start (const char *path, ev_tstamp interval = 0.) EV_NOEXCEPT void start (const char *path, ev_tstamp interval = 0.) EV_NOEXCEPT
...@@ -766,10 +770,8 @@ namespace ev { ...@@ -766,10 +770,8 @@ namespace ev {
EV_BEGIN_WATCHER (embed, embed) EV_BEGIN_WATCHER (embed, embed)
void set_embed (struct ev_loop *embedded_loop) EV_NOEXCEPT void set_embed (struct ev_loop *embedded_loop) EV_NOEXCEPT
{ {
int active = is_active (); freeze_guard freeze (this);
if (active) stop ();
ev_embed_set (static_cast<ev_embed *>(this), embedded_loop); ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);
if (active) start ();
} }
void start (struct ev_loop *embedded_loop) EV_NOEXCEPT void start (struct ev_loop *embedded_loop) EV_NOEXCEPT
......
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
.\" ======================================================================== .\" ========================================================================
.\" .\"
.IX Title "LIBEV 3" .IX Title "LIBEV 3"
.TH LIBEV 3 "2019-12-21" "libev-4.31" "libev - high performance full featured event loop" .TH LIBEV 3 "2020-03-12" "libev-4.31" "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
...@@ -1351,8 +1351,9 @@ with a watcher-specific start function (\f(CW\*(C`ev_TYPE_start (loop, watcher ...@@ -1351,8 +1351,9 @@ with a watcher-specific start function (\f(CW\*(C`ev_TYPE_start (loop, watcher
corresponding stop function (\f(CW\*(C`ev_TYPE_stop (loop, watcher *)\*(C'\fR. corresponding stop function (\f(CW\*(C`ev_TYPE_stop (loop, watcher *)\*(C'\fR.
.PP .PP
As long as your watcher is active (has been started but not stopped) you As long as your watcher is active (has been started but not stopped) you
must not touch the values stored in it. Most specifically you must never must not touch the values stored in it except when explicitly documented
reinitialise it or call its \f(CW\*(C`ev_TYPE_set\*(C'\fR macro. otherwise. Most specifically you must never reinitialise it or call its
\&\f(CW\*(C`ev_TYPE_set\*(C'\fR macro.
.PP .PP
Each and every callback receives the event loop pointer as first, the Each and every callback receives the event loop pointer as first, the
registered watcher structure as second, and a bitset of received events as registered watcher structure as second, and a bitset of received events as
...@@ -1769,14 +1770,18 @@ This section describes each watcher in detail, but will not repeat ...@@ -1769,14 +1770,18 @@ This section describes each watcher in detail, but will not repeat
information given in the last section. Any initialisation/set macros, information given in the last section. Any initialisation/set macros,
functions and members specific to the watcher type are explained. functions and members specific to the watcher type are explained.
.PP .PP
Members are additionally marked with either \fI[read\-only]\fR, meaning that, Most members are additionally marked with either \fI[read\-only]\fR, meaning
while the watcher is active, you can look at the member and expect some that, while the watcher is active, you can look at the member and expect
sensible content, but you must not modify it (you can modify it while the some sensible content, but you must not modify it (you can modify it while
watcher is stopped to your hearts content), or \fI[read\-write]\fR, which the watcher is stopped to your hearts content), or \fI[read\-write]\fR, which
means you can expect it to have some sensible content while the watcher means you can expect it to have some sensible content while the watcher is
is active, but you can also modify it. Modifying it may not do something active, but you can also modify it (within the same thread as the event
loop, i.e. without creating data races). Modifying it may not do something
sensible or take immediate effect (or do anything at all), but libev will 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.
.PP
In any case, the documentation for each member will explain what the
effects are, and if there are any additional access restrictions.
.ie n .SS """ev_io"" \- is this file descriptor readable or writable?" .ie n .SS """ev_io"" \- is this file descriptor readable or writable?"
.el .SS "\f(CWev_io\fP \- is this file descriptor readable or writable?" .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?"
...@@ -1952,14 +1957,33 @@ opportunity for a DoS attack. ...@@ -1952,14 +1957,33 @@ opportunity for a DoS attack.
.IX Item "ev_io_set (ev_io *, int fd, int events)" .IX Item "ev_io_set (ev_io *, int fd, int events)"
.PD .PD
Configures an \f(CW\*(C`ev_io\*(C'\fR watcher. The \f(CW\*(C`fd\*(C'\fR is the file descriptor to Configures an \f(CW\*(C`ev_io\*(C'\fR watcher. The \f(CW\*(C`fd\*(C'\fR is the file descriptor to
receive events for and \f(CW\*(C`events\*(C'\fR is either \f(CW\*(C`EV_READ\*(C'\fR, \f(CW\*(C`EV_WRITE\*(C'\fR or receive events for and \f(CW\*(C`events\*(C'\fR is either \f(CW\*(C`EV_READ\*(C'\fR, \f(CW\*(C`EV_WRITE\*(C'\fR, both
\&\f(CW\*(C`EV_READ | EV_WRITE\*(C'\fR, to express the desire to receive the given events. \&\f(CW\*(C`EV_READ | EV_WRITE\*(C'\fR or \f(CW0\fR, to express the desire to receive the given
.IP "int fd [read\-only]" 4 events.
.IX Item "int fd [read-only]" .Sp
The file descriptor being watched. Note that setting the \f(CW\*(C`events\*(C'\fR to \f(CW0\fR and starting the watcher is
.IP "int events [read\-only]" 4 supported, but not specially optimized \- if your program sometimes happens
.IX Item "int events [read-only]" to generate this combination this is fine, but if it is easy to avoid
The events being watched. starting an io watcher watching for no events you should do so.
.IP "ev_io_modify (ev_io *, int events)" 4
.IX Item "ev_io_modify (ev_io *, int events)"
Similar to \f(CW\*(C`ev_io_set\*(C'\fR, but only changes the requested events. Using this
might be faster with some backends, as libev can assume that the \f(CW\*(C`fd\*(C'\fR
still refers to the same underlying file description, something it cannot
do when using \f(CW\*(C`ev_io_set\*(C'\fR.
.IP "int fd [no\-modify]" 4
.IX Item "int fd [no-modify]"
The file descriptor being watched. While it can be read at any time, you
must not modify this member even when the watcher is stopped \- always use
\&\f(CW\*(C`ev_io_set\*(C'\fR for that.
.IP "int events [no\-modify]" 4
.IX Item "int events [no-modify]"
The set of events the fd is being watched for, among other flags. Remember
that this is a bit set \- to test for \f(CW\*(C`EV_READ\*(C'\fR, use \f(CW\*(C`w\->events &
EV_READ\*(C'\fR, and similarly for \f(CW\*(C`EV_WRITE\*(C'\fR.
.Sp
As with \f(CW\*(C`fd\*(C'\fR, you must not modify this member even when the watcher is
stopped, always use \f(CW\*(C`ev_io_set\*(C'\fR or \f(CW\*(C`ev_io_modify\*(C'\fR for that.
.PP .PP
\fIExamples\fR \fIExamples\fR
.IX Subsection "Examples" .IX Subsection "Examples"
...@@ -4397,6 +4421,9 @@ method. ...@@ -4397,6 +4421,9 @@ method.
.Sp .Sp
For \f(CW\*(C`ev::embed\*(C'\fR watchers this method is called \f(CW\*(C`set_embed\*(C'\fR, to avoid For \f(CW\*(C`ev::embed\*(C'\fR watchers this method is called \f(CW\*(C`set_embed\*(C'\fR, to avoid
clashing with the \f(CW\*(C`set (loop)\*(C'\fR method. clashing with the \f(CW\*(C`set (loop)\*(C'\fR method.
.Sp
For \f(CW\*(C`ev::io\*(C'\fR watchers there is an additional \f(CW\*(C`set\*(C'\fR method that acepts a
new event mask only, and internally calls \f(CW\*(C`ev_io_modfify\*(C'\fR.
.IP "w\->start ()" 4 .IP "w\->start ()" 4
.IX Item "w->start ()" .IX Item "w->start ()"
Starts the watcher. Note that there is no \f(CW\*(C`loop\*(C'\fR argument, as the Starts the watcher. Note that there is no \f(CW\*(C`loop\*(C'\fR argument, as the
......
This diff is collapsed.
/* /*
* libev native API header * libev native API header
* *
* Copyright (c) 2007-2019 Marc Alexander Lehmann <libev@schmorp.de> * Copyright (c) 2007-2020 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-
...@@ -215,7 +215,7 @@ struct ev_loop; ...@@ -215,7 +215,7 @@ struct ev_loop;
/*****************************************************************************/ /*****************************************************************************/
#define EV_VERSION_MAJOR 4 #define EV_VERSION_MAJOR 4
#define EV_VERSION_MINOR 31 #define EV_VERSION_MINOR 33
/* eventmask, revents, events... */ /* eventmask, revents, events... */
enum { enum {
...@@ -392,14 +392,12 @@ typedef struct ev_stat ...@@ -392,14 +392,12 @@ typedef struct ev_stat
} ev_stat; } ev_stat;
#endif #endif
#if EV_IDLE_ENABLE
/* invoked when the nothing else needs to be done, keeps the process from blocking */ /* invoked when the nothing else needs to be done, keeps the process from blocking */
/* revent EV_IDLE */ /* revent EV_IDLE */
typedef struct ev_idle typedef struct ev_idle
{ {
EV_WATCHER (ev_idle) EV_WATCHER (ev_idle)
} ev_idle; } ev_idle;
#endif
/* invoked for each run of the mainloop, just before the blocking call */ /* invoked for each run of the mainloop, just before the blocking call */
/* you can still change events in any way you like */ /* you can still change events in any way you like */
...@@ -416,23 +414,19 @@ typedef struct ev_check ...@@ -416,23 +414,19 @@ typedef struct ev_check
EV_WATCHER (ev_check) EV_WATCHER (ev_check)
} ev_check; } ev_check;
#if EV_FORK_ENABLE
/* the callback gets invoked before check in the child process when a fork was detected */ /* the callback gets invoked before check in the child process when a fork was detected */
/* revent EV_FORK */ /* revent EV_FORK */
typedef struct ev_fork typedef struct ev_fork
{ {
EV_WATCHER (ev_fork) EV_WATCHER (ev_fork)
} ev_fork; } ev_fork;
#endif
#if EV_CLEANUP_ENABLE
/* is invoked just before the loop gets destroyed */ /* is invoked just before the loop gets destroyed */
/* revent EV_CLEANUP */ /* revent EV_CLEANUP */
typedef struct ev_cleanup typedef struct ev_cleanup
{ {
EV_WATCHER (ev_cleanup) EV_WATCHER (ev_cleanup)
} ev_cleanup; } ev_cleanup;
#endif
#if EV_EMBED_ENABLE #if EV_EMBED_ENABLE
/* used to embed an event loop inside another */ /* used to embed an event loop inside another */
...@@ -442,16 +436,18 @@ typedef struct ev_embed ...@@ -442,16 +436,18 @@ typedef struct ev_embed
EV_WATCHER (ev_embed) EV_WATCHER (ev_embed)
struct ev_loop *other; /* ro */ struct ev_loop *other; /* ro */
#undef EV_IO_ENABLE
#define EV_IO_ENABLE 1
ev_io io; /* private */ ev_io io; /* private */
#undef EV_PREPARE_ENABLE
#define EV_PREPARE_ENABLE 1
ev_prepare prepare; /* private */ ev_prepare prepare; /* private */
ev_check check; /* unused */ ev_check check; /* unused */
ev_timer timer; /* unused */ ev_timer timer; /* unused */
ev_periodic periodic; /* unused */ ev_periodic periodic; /* unused */
ev_idle idle; /* unused */ ev_idle idle; /* unused */
ev_fork fork; /* private */ ev_fork fork; /* private */
#if EV_CLEANUP_ENABLE
ev_cleanup cleanup; /* unused */ ev_cleanup cleanup; /* unused */
#endif
} ev_embed; } ev_embed;
#endif #endif
...@@ -526,7 +522,7 @@ enum { ...@@ -526,7 +522,7 @@ enum {
EVBACKEND_KQUEUE = 0x00000008U, /* bsd, broken on osx */ EVBACKEND_KQUEUE = 0x00000008U, /* bsd, broken on osx */
EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */ EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
EVBACKEND_PORT = 0x00000020U, /* solaris 10 */ EVBACKEND_PORT = 0x00000020U, /* solaris 10 */
EVBACKEND_LINUXAIO = 0x00000040U, /* linuix AIO, 4.19+ */ EVBACKEND_LINUXAIO = 0x00000040U, /* linux AIO, 4.19+ */
EVBACKEND_IOURING = 0x00000080U, /* linux io_uring, 5.1+ */ EVBACKEND_IOURING = 0x00000080U, /* linux io_uring, 5.1+ */
EVBACKEND_ALL = 0x000000FFU, /* all known backends */ EVBACKEND_ALL = 0x000000FFU, /* all known backends */
EVBACKEND_MASK = 0x0000FFFFU /* all future backends */ EVBACKEND_MASK = 0x0000FFFFU /* all future backends */
...@@ -660,6 +656,8 @@ EV_API_DECL void ev_unref (EV_P) EV_NOEXCEPT; ...@@ -660,6 +656,8 @@ EV_API_DECL void ev_unref (EV_P) EV_NOEXCEPT;
*/ */
EV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_NOEXCEPT; EV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_NOEXCEPT;
EV_API_DECL void ev_invoke_pending (EV_P); /* invoke all pending watchers */
# if EV_FEATURE_API # if EV_FEATURE_API
EV_API_DECL unsigned int ev_iteration (EV_P) EV_NOEXCEPT; /* number of loop iterations */ EV_API_DECL unsigned int ev_iteration (EV_P) EV_NOEXCEPT; /* number of loop iterations */
EV_API_DECL unsigned int ev_depth (EV_P) EV_NOEXCEPT; /* #ev_loop enters - #ev_loop leaves */ EV_API_DECL unsigned int ev_depth (EV_P) EV_NOEXCEPT; /* #ev_loop enters - #ev_loop leaves */
...@@ -677,7 +675,6 @@ EV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending ...@@ -677,7 +675,6 @@ EV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending
EV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)(EV_P) EV_NOEXCEPT) EV_NOEXCEPT; EV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)(EV_P) EV_NOEXCEPT) EV_NOEXCEPT;
EV_API_DECL unsigned int ev_pending_count (EV_P) EV_NOEXCEPT; /* number of pending events, if any */ EV_API_DECL unsigned int ev_pending_count (EV_P) EV_NOEXCEPT; /* number of pending events, if any */
EV_API_DECL void ev_invoke_pending (EV_P); /* invoke all pending watchers */
/* /*
* stop/start the timer handling. * stop/start the timer handling.
...@@ -697,6 +694,7 @@ EV_API_DECL void ev_resume (EV_P) EV_NOEXCEPT; ...@@ -697,6 +694,7 @@ EV_API_DECL void ev_resume (EV_P) EV_NOEXCEPT;
ev_set_cb ((ev), cb_); \ ev_set_cb ((ev), cb_); \
} while (0) } while (0)
#define ev_io_modify(ev,events_) do { (ev)->events = (ev)->events & EV__IOFDSET | (events_); } while (0)
#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0) #define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0)
#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0) #define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)
#define ev_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0) #define ev_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0)
...@@ -742,6 +740,7 @@ EV_API_DECL void ev_resume (EV_P) EV_NOEXCEPT; ...@@ -742,6 +740,7 @@ EV_API_DECL void ev_resume (EV_P) EV_NOEXCEPT;
#define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at) #define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at)
#ifndef ev_set_cb #ifndef ev_set_cb
/* memmove is used here to avoid strict aliasing violations, and hopefully is optimized out by any reasonable compiler */
# define ev_set_cb(ev,cb_) (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev)))) # define ev_set_cb(ev,cb_) (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev))))
#endif #endif
......
...@@ -1220,8 +1220,9 @@ with a watcher-specific start function (C<< ev_TYPE_start (loop, watcher ...@@ -1220,8 +1220,9 @@ with a watcher-specific start function (C<< ev_TYPE_start (loop, watcher
corresponding stop function (C<< ev_TYPE_stop (loop, watcher *) >>. corresponding stop function (C<< ev_TYPE_stop (loop, watcher *) >>.
As long as your watcher is active (has been started but not stopped) you As long as your watcher is active (has been started but not stopped) you
must not touch the values stored in it. Most specifically you must never must not touch the values stored in it except when explicitly documented
reinitialise it or call its C<ev_TYPE_set> macro. otherwise. Most specifically you must never reinitialise it or call its
C<ev_TYPE_set> macro.
Each and every callback receives the event loop pointer as first, the Each and every callback receives the event loop pointer as first, the
registered watcher structure as second, and a bitset of received events as registered watcher structure as second, and a bitset of received events as
...@@ -1650,15 +1651,18 @@ This section describes each watcher in detail, but will not repeat ...@@ -1650,15 +1651,18 @@ This section describes each watcher in detail, but will not repeat
information given in the last section. Any initialisation/set macros, information given in the last section. Any initialisation/set macros,
functions and members specific to the watcher type are explained. functions and members specific to the watcher type are explained.
Members are additionally marked with either I<[read-only]>, meaning that, Most members are additionally marked with either I<[read-only]>, meaning
while the watcher is active, you can look at the member and expect some that, while the watcher is active, you can look at the member and expect
sensible content, but you must not modify it (you can modify it while the some sensible content, but you must not modify it (you can modify it while
watcher is stopped to your hearts content), or I<[read-write]>, which the watcher is stopped to your hearts content), or I<[read-write]>, which
means you can expect it to have some sensible content while the watcher means you can expect it to have some sensible content while the watcher is
is active, but you can also modify it. Modifying it may not do something active, but you can also modify it (within the same thread as the event
loop, i.e. without creating data races). Modifying it may not do something
sensible or take immediate effect (or do anything at all), but libev will 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.
In any case, the documentation for each member will explain what the
effects are, and if there are any additional access restrictions.
=head2 C<ev_io> - is this file descriptor readable or writable? =head2 C<ev_io> - is this file descriptor readable or writable?
...@@ -1828,16 +1832,36 @@ opportunity for a DoS attack. ...@@ -1828,16 +1832,36 @@ opportunity for a DoS attack.
=item ev_io_set (ev_io *, int fd, int events) =item ev_io_set (ev_io *, int fd, int events)
Configures an C<ev_io> watcher. The C<fd> is the file descriptor to Configures an C<ev_io> watcher. The C<fd> is the file descriptor to
receive events for and C<events> is either C<EV_READ>, C<EV_WRITE> or receive events for and C<events> is either C<EV_READ>, C<EV_WRITE>, both
C<EV_READ | EV_WRITE>, to express the desire to receive the given events. C<EV_READ | EV_WRITE> or C<0>, to express the desire to receive the given
events.
=item int fd [read-only] Note that setting the C<events> to C<0> and starting the watcher is
supported, but not specially optimized - if your program sometimes happens
to generate this combination this is fine, but if it is easy to avoid
starting an io watcher watching for no events you should do so.
The file descriptor being watched. =item ev_io_modify (ev_io *, int events)
=item int events [read-only] Similar to C<ev_io_set>, but only changes the requested events. Using this
might be faster with some backends, as libev can assume that the C<fd>
still refers to the same underlying file description, something it cannot
do when using C<ev_io_set>.
The events being watched. =item int fd [no-modify]
The file descriptor being watched. While it can be read at any time, you
must not modify this member even when the watcher is stopped - always use
C<ev_io_set> for that.
=item int events [no-modify]
The set of events the fd is being watched for, among other flags. Remember
that this is a bit set - to test for C<EV_READ>, use C<< w->events &
EV_READ >>, and similarly for C<EV_WRITE>.
As with C<fd>, you must not modify this member even when the watcher is
stopped, always use C<ev_io_set> or C<ev_io_modify> for that.
=back =back
...@@ -4245,6 +4269,9 @@ method. ...@@ -4245,6 +4269,9 @@ method.
For C<ev::embed> watchers this method is called C<set_embed>, to avoid For C<ev::embed> watchers this method is called C<set_embed>, to avoid
clashing with the C<set (loop)> method. clashing with the C<set (loop)> method.
For C<ev::io> watchers there is an additional C<set> method that acepts a
new event mask only, and internally calls C<ev_io_modfify>.
=item w->start () =item w->start ()
Starts the watcher. Note that there is no C<loop> argument, as the Starts the watcher. Note that there is no C<loop> argument, as the
......
This diff is collapsed.
...@@ -270,8 +270,7 @@ linuxaio_modify (EV_P_ int fd, int oev, int nev) ...@@ -270,8 +270,7 @@ linuxaio_modify (EV_P_ int fd, int oev, int nev)
++anfd->egen; ++anfd->egen;
} }
iocb->io.aio_buf = iocb->io.aio_buf = (nev & EV_READ ? POLLIN : 0)
(nev & EV_READ ? POLLIN : 0)
| (nev & EV_WRITE ? POLLOUT : 0); | (nev & EV_WRITE ? POLLOUT : 0);
if (nev) if (nev)
......
...@@ -145,7 +145,6 @@ VARx(uint32_t, iouring_cq_cqes) ...@@ -145,7 +145,6 @@ VARx(uint32_t, iouring_cq_cqes)
VARx(ev_tstamp, iouring_tfd_to) VARx(ev_tstamp, iouring_tfd_to)
VARx(int, iouring_tfd) VARx(int, iouring_tfd)
VARx(ev_io, iouring_tfd_w) VARx(ev_io, iouring_tfd_w)
VARx(ev_io, iouring_epoll_w)
#endif #endif
#if EV_USE_KQUEUE || EV_GENWRAP #if EV_USE_KQUEUE || EV_GENWRAP
......
...@@ -53,7 +53,6 @@ ...@@ -53,7 +53,6 @@
#define iouring_cq_ring_size ((loop)->iouring_cq_ring_size) #define iouring_cq_ring_size ((loop)->iouring_cq_ring_size)
#define iouring_cq_tail ((loop)->iouring_cq_tail) #define iouring_cq_tail ((loop)->iouring_cq_tail)
#define iouring_entries ((loop)->iouring_entries) #define iouring_entries ((loop)->iouring_entries)
#define iouring_epoll_w ((loop)->iouring_epoll_w)
#define iouring_fd ((loop)->iouring_fd) #define iouring_fd ((loop)->iouring_fd)
#define iouring_max_entries ((loop)->iouring_max_entries) #define iouring_max_entries ((loop)->iouring_max_entries)
#define iouring_sq_array ((loop)->iouring_sq_array) #define iouring_sq_array ((loop)->iouring_sq_array)
...@@ -189,7 +188,6 @@ ...@@ -189,7 +188,6 @@
#undef iouring_cq_ring_size #undef iouring_cq_ring_size
#undef iouring_cq_tail #undef iouring_cq_tail
#undef iouring_entries #undef iouring_entries
#undef iouring_epoll_w
#undef iouring_fd #undef iouring_fd
#undef iouring_max_entries #undef iouring_max_entries
#undef iouring_sq_array #undef iouring_sq_array
......
Update the embedded libev from 4.31 to 4.33.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment