mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-30 13:13:44 +00:00
Update libev to 4.22 (#854)
This commit is contained in:
@@ -14,6 +14,16 @@ TODO: embed watchers need updating when fd changes
|
||||
TODO: document portability requirements for atomic pointer access
|
||||
TODO: document requirements for function pointers and calling conventions.
|
||||
|
||||
4.22 Sun Dec 20 22:11:50 CET 2015
|
||||
- when epoll detects unremovable fds in the fd set, rebuild
|
||||
only the epoll descriptor, not the signal pipe, to avoid
|
||||
SIGPIPE in ev_async_send. This doesn't solve it on fork,
|
||||
so document what needs to be done in ev_loop_fork
|
||||
(analyzed by Benjamin Mahler).
|
||||
- remove superfluous sys/timeb.h include on win32
|
||||
(analyzed by Jason Madden).
|
||||
- updated libecb.
|
||||
|
||||
4.20 Sat Jun 20 13:01:43 CEST 2015
|
||||
- prefer noexcept over throw () with C++ 11.
|
||||
- update ecb.h due to incompatibilities with c11.
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ orig_CFLAGS="$CFLAGS"
|
||||
AC_CONFIG_SRCDIR([ev_epoll.c])
|
||||
|
||||
dnl also update ev.h!
|
||||
AM_INIT_AUTOMAKE(libev,4.20)
|
||||
AM_INIT_AUTOMAKE(libev,4.22)
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
|
||||
+1
-1
@@ -575,7 +575,7 @@ namespace ev {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* using a template here would require quite a bit more lines,
|
||||
/* using a template here would require quite a few more lines,
|
||||
* so a macro solution was chosen */
|
||||
#define EV_BEGIN_WATCHER(cppstem,cstem) \
|
||||
\
|
||||
|
||||
+106
-94
@@ -1,4 +1,4 @@
|
||||
.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16)
|
||||
.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
@@ -38,6 +38,8 @@
|
||||
. ds PI \(*p
|
||||
. ds L" ``
|
||||
. ds R" ''
|
||||
. ds C`
|
||||
. ds C'
|
||||
'br\}
|
||||
.\"
|
||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
||||
@@ -48,17 +50,24 @@
|
||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||
.\" output yourself in some meaningful fashion.
|
||||
.ie \nF \{\
|
||||
. de IX
|
||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||
.\"
|
||||
.\" Avoid warning from groff about undefined register 'F'.
|
||||
.de IX
|
||||
..
|
||||
. nr % 0
|
||||
. rr F
|
||||
.\}
|
||||
.el \{\
|
||||
. de IX
|
||||
.nr rF 0
|
||||
.if \n(.g .if rF .nr rF 1
|
||||
.if (\n(rF:(\n(.g==0)) \{
|
||||
. if \nF \{
|
||||
. de IX
|
||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||
..
|
||||
. if !\nF==2 \{
|
||||
. nr % 0
|
||||
. nr F 2
|
||||
. \}
|
||||
. \}
|
||||
.\}
|
||||
.rr rF
|
||||
.\"
|
||||
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
||||
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
||||
@@ -124,7 +133,7 @@
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "LIBEV 3"
|
||||
.TH LIBEV 3 "2015-07-28" "libev-2.2.3" "libev - high performance full featured event loop"
|
||||
.TH LIBEV 3 "2015-12-20" "libev-4.20" "libev - high performance full featured event loop"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.if n .ad l
|
||||
@@ -136,7 +145,7 @@ libev \- a high performance full\-featured event loop written in C
|
||||
.Vb 1
|
||||
\& #include <ev.h>
|
||||
.Ve
|
||||
.SS "\s-1EXAMPLE\s0 \s-1PROGRAM\s0"
|
||||
.SS "\s-1EXAMPLE PROGRAM\s0"
|
||||
.IX Subsection "EXAMPLE PROGRAM"
|
||||
.Vb 2
|
||||
\& // a single header file is required
|
||||
@@ -214,9 +223,9 @@ throughout this document.
|
||||
.IX Header "WHAT TO READ WHEN IN A HURRY"
|
||||
This manual tries to be very detailed, but unfortunately, this also makes
|
||||
it very long. If you just want to know the basics of libev, I suggest
|
||||
reading \*(L"\s-1ANATOMY\s0 \s-1OF\s0 A \s-1WATCHER\s0\*(R", then the \*(L"\s-1EXAMPLE\s0 \s-1PROGRAM\s0\*(R" above and
|
||||
look up the missing functions in \*(L"\s-1GLOBAL\s0 \s-1FUNCTIONS\s0\*(R" and the \f(CW\*(C`ev_io\*(C'\fR and
|
||||
\&\f(CW\*(C`ev_timer\*(C'\fR sections in \*(L"\s-1WATCHER\s0 \s-1TYPES\s0\*(R".
|
||||
reading \*(L"\s-1ANATOMY OF A WATCHER\*(R"\s0, then the \*(L"\s-1EXAMPLE PROGRAM\*(R"\s0 above and
|
||||
look up the missing functions in \*(L"\s-1GLOBAL FUNCTIONS\*(R"\s0 and the \f(CW\*(C`ev_io\*(C'\fR and
|
||||
\&\f(CW\*(C`ev_timer\*(C'\fR sections in \*(L"\s-1WATCHER TYPES\*(R"\s0.
|
||||
.SH "ABOUT LIBEV"
|
||||
.IX Header "ABOUT LIBEV"
|
||||
Libev is an event loop: you register interest in certain events (such as a
|
||||
@@ -257,7 +266,7 @@ more info about various configuration options please have a look at
|
||||
for multiple event loops, then all functions taking an initial argument of
|
||||
name \f(CW\*(C`loop\*(C'\fR (which is always of type \f(CW\*(C`struct ev_loop *\*(C'\fR) will not have
|
||||
this argument.
|
||||
.SS "\s-1TIME\s0 \s-1REPRESENTATION\s0"
|
||||
.SS "\s-1TIME REPRESENTATION\s0"
|
||||
.IX Subsection "TIME REPRESENTATION"
|
||||
Libev represents time as a single floating point number, representing
|
||||
the (fractional) number of seconds since the (\s-1POSIX\s0) epoch (in practice
|
||||
@@ -534,8 +543,8 @@ without a system call and thus \fIvery\fR fast, but my GNU/Linux system also has
|
||||
\&\f(CW\*(C`pthread_atfork\*(C'\fR which is even faster).
|
||||
.Sp
|
||||
The big advantage of this flag is that you can forget about fork (and
|
||||
forget about forgetting to tell libev about forking) when you use this
|
||||
flag.
|
||||
forget about forgetting to tell libev about forking, although you still
|
||||
have to ignore \f(CW\*(C`SIGPIPE\*(C'\fR) when you use this flag.
|
||||
.Sp
|
||||
This flag setting cannot be overridden or specified in the \f(CW\*(C`LIBEV_FLAGS\*(C'\fR
|
||||
environment variable.
|
||||
@@ -576,7 +585,7 @@ It's also required by \s-1POSIX\s0 in a threaded program, as libev calls
|
||||
This flag's behaviour will become the default in future versions of libev.
|
||||
.ie n .IP """EVBACKEND_SELECT"" (value 1, portable select backend)" 4
|
||||
.el .IP "\f(CWEVBACKEND_SELECT\fR (value 1, portable select backend)" 4
|
||||
.IX Item "EVBACKEND_SELECT (value 1, portable select backend)"
|
||||
.IX Item "EVBACKEND_SELECT (value 1, portable select backend)"
|
||||
This is your standard \fIselect\fR\|(2) backend. Not \fIcompletely\fR standard, as
|
||||
libev tries to roll its own fd_set with no limits on the number of fds,
|
||||
but if that fails, expect a fairly low limit on the number of fds when
|
||||
@@ -595,7 +604,7 @@ This backend maps \f(CW\*(C`EV_READ\*(C'\fR to the \f(CW\*(C`readfds\*(C'\fR set
|
||||
\&\f(CW\*(C`exceptfds\*(C'\fR set on that platform).
|
||||
.ie n .IP """EVBACKEND_POLL"" (value 2, poll backend, available everywhere except on windows)" 4
|
||||
.el .IP "\f(CWEVBACKEND_POLL\fR (value 2, poll backend, available everywhere except on windows)" 4
|
||||
.IX Item "EVBACKEND_POLL (value 2, poll backend, available everywhere except on windows)"
|
||||
.IX Item "EVBACKEND_POLL (value 2, poll backend, available everywhere except on windows)"
|
||||
And this is your standard \fIpoll\fR\|(2) backend. It's more complicated
|
||||
than select, but handles sparse fds better and has no artificial
|
||||
limit on the number of fds you can use (except it will slow down
|
||||
@@ -607,7 +616,7 @@ This backend maps \f(CW\*(C`EV_READ\*(C'\fR to \f(CW\*(C`POLLIN | POLLERR | POLL
|
||||
\&\f(CW\*(C`EV_WRITE\*(C'\fR to \f(CW\*(C`POLLOUT | POLLERR | POLLHUP\*(C'\fR.
|
||||
.ie n .IP """EVBACKEND_EPOLL"" (value 4, Linux)" 4
|
||||
.el .IP "\f(CWEVBACKEND_EPOLL\fR (value 4, Linux)" 4
|
||||
.IX Item "EVBACKEND_EPOLL (value 4, Linux)"
|
||||
.IX Item "EVBACKEND_EPOLL (value 4, Linux)"
|
||||
Use the linux-specific \fIepoll\fR\|(7) interface (for both pre\- and post\-2.6.9
|
||||
kernels).
|
||||
.Sp
|
||||
@@ -670,7 +679,7 @@ This backend maps \f(CW\*(C`EV_READ\*(C'\fR and \f(CW\*(C`EV_WRITE\*(C'\fR in th
|
||||
\&\f(CW\*(C`EVBACKEND_POLL\*(C'\fR.
|
||||
.ie n .IP """EVBACKEND_KQUEUE"" (value 8, most \s-1BSD\s0 clones)" 4
|
||||
.el .IP "\f(CWEVBACKEND_KQUEUE\fR (value 8, most \s-1BSD\s0 clones)" 4
|
||||
.IX Item "EVBACKEND_KQUEUE (value 8, most BSD clones)"
|
||||
.IX Item "EVBACKEND_KQUEUE (value 8, most BSD clones)"
|
||||
Kqueue deserves special mention, as at the time of this writing, it
|
||||
was broken on all BSDs except NetBSD (usually it doesn't work reliably
|
||||
with anything but sockets and pipes, except on Darwin, where of course
|
||||
@@ -700,7 +709,7 @@ everywhere, so you might need to test for this. And since it is broken
|
||||
almost everywhere, you should only use it when you have a lot of sockets
|
||||
(for which it usually works), by embedding it into another event loop
|
||||
(e.g. \f(CW\*(C`EVBACKEND_SELECT\*(C'\fR or \f(CW\*(C`EVBACKEND_POLL\*(C'\fR (but \f(CW\*(C`poll\*(C'\fR is of course
|
||||
also broken on \s-1OS\s0 X)) and, did I mention it, using it only for sockets.
|
||||
also broken on \s-1OS X\s0)) and, did I mention it, using it only for sockets.
|
||||
.Sp
|
||||
This backend maps \f(CW\*(C`EV_READ\*(C'\fR into an \f(CW\*(C`EVFILT_READ\*(C'\fR kevent with
|
||||
\&\f(CW\*(C`NOTE_EOF\*(C'\fR, and \f(CW\*(C`EV_WRITE\*(C'\fR into an \f(CW\*(C`EVFILT_WRITE\*(C'\fR kevent with
|
||||
@@ -714,7 +723,7 @@ and is not embeddable, which would limit the usefulness of this backend
|
||||
immensely.
|
||||
.ie n .IP """EVBACKEND_PORT"" (value 32, Solaris 10)" 4
|
||||
.el .IP "\f(CWEVBACKEND_PORT\fR (value 32, Solaris 10)" 4
|
||||
.IX Item "EVBACKEND_PORT (value 32, Solaris 10)"
|
||||
.IX Item "EVBACKEND_PORT (value 32, Solaris 10)"
|
||||
This uses the Solaris 10 event port mechanism. As with everything on Solaris,
|
||||
it's really slow, but it still scales very well (O(active_fds)).
|
||||
.Sp
|
||||
@@ -810,6 +819,9 @@ watchers (except inside an \f(CW\*(C`ev_prepare\*(C'\fR callback), but it makes
|
||||
sense after forking, in the child process. You \fImust\fR call it (or use
|
||||
\&\f(CW\*(C`EVFLAG_FORKCHECK\*(C'\fR) in the child before resuming or calling \f(CW\*(C`ev_run\*(C'\fR.
|
||||
.Sp
|
||||
In addition, if you want to reuse a loop (via this function or
|
||||
\&\f(CW\*(C`EVFLAG_FORKCHECK\*(C'\fR), you \fIalso\fR have to ignore \f(CW\*(C`SIGPIPE\*(C'\fR.
|
||||
.Sp
|
||||
Again, you \fIhave\fR to call it on \fIany\fR loop that you want to re-use after
|
||||
a fork, \fIeven if you do not plan to use the loop in the parent\fR. This is
|
||||
because some kernel interfaces *cough* \fIkqueue\fR *cough* do funny things
|
||||
@@ -1357,7 +1369,7 @@ callbacks is well-written it can just attempt the operation and cope with
|
||||
the error from \fIread()\fR or \fIwrite()\fR. This will not work in multi-threaded
|
||||
programs, though, as the fd could already be closed and reused for another
|
||||
thing, so beware.
|
||||
.SS "\s-1GENERIC\s0 \s-1WATCHER\s0 \s-1FUNCTIONS\s0"
|
||||
.SS "\s-1GENERIC WATCHER FUNCTIONS\s0"
|
||||
.IX Subsection "GENERIC WATCHER FUNCTIONS"
|
||||
.ie n .IP """ev_init"" (ev_TYPE *watcher, callback)" 4
|
||||
.el .IP "\f(CWev_init\fR (ev_TYPE *watcher, callback)" 4
|
||||
@@ -1475,7 +1487,7 @@ or might not have been clamped to the valid range.
|
||||
The default priority used by watchers when no priority has been set is
|
||||
always \f(CW0\fR, which is supposed to not be too high and not be too low :).
|
||||
.Sp
|
||||
See \*(L"\s-1WATCHER\s0 \s-1PRIORITY\s0 \s-1MODELS\s0\*(R", below, for a more thorough treatment of
|
||||
See \*(L"\s-1WATCHER PRIORITY MODELS\*(R"\s0, below, for a more thorough treatment of
|
||||
priorities.
|
||||
.IP "ev_invoke (loop, ev_TYPE *watcher, int revents)" 4
|
||||
.IX Item "ev_invoke (loop, ev_TYPE *watcher, int revents)"
|
||||
@@ -1505,9 +1517,9 @@ not started in the first place.
|
||||
See also \f(CW\*(C`ev_feed_fd_event\*(C'\fR and \f(CW\*(C`ev_feed_signal_event\*(C'\fR for related
|
||||
functions that do not need a watcher.
|
||||
.PP
|
||||
See also the \*(L"\s-1ASSOCIATING\s0 \s-1CUSTOM\s0 \s-1DATA\s0 \s-1WITH\s0 A \s-1WATCHER\s0\*(R" and \*(L"\s-1BUILDING\s0 \s-1YOUR\s0
|
||||
\&\s-1OWN\s0 \s-1COMPOSITE\s0 \s-1WATCHERS\s0\*(R" idioms.
|
||||
.SS "\s-1WATCHER\s0 \s-1STATES\s0"
|
||||
See also the \*(L"\s-1ASSOCIATING CUSTOM DATA WITH A WATCHER\*(R"\s0 and \*(L"\s-1BUILDING YOUR
|
||||
OWN COMPOSITE WATCHERS\*(R"\s0 idioms.
|
||||
.SS "\s-1WATCHER STATES\s0"
|
||||
.IX Subsection "WATCHER STATES"
|
||||
There are various watcher states mentioned throughout this manual \-
|
||||
active, pending and so on. In this section these states and the rules to
|
||||
@@ -1560,7 +1572,7 @@ While stopped (and not pending) the watcher is essentially in the
|
||||
initialised state, that is, it can be reused, moved, modified in any way
|
||||
you wish (but when you trash the memory block, you need to \f(CW\*(C`ev_TYPE_init\*(C'\fR
|
||||
it again).
|
||||
.SS "\s-1WATCHER\s0 \s-1PRIORITY\s0 \s-1MODELS\s0"
|
||||
.SS "\s-1WATCHER PRIORITY MODELS\s0"
|
||||
.IX Subsection "WATCHER PRIORITY MODELS"
|
||||
Many event loops support \fIwatcher priorities\fR, which are usually small
|
||||
integers that influence the ordering of event callback invocation
|
||||
@@ -1768,7 +1780,7 @@ wish to read \- you would first have to request some data.
|
||||
Since files are typically not-so-well supported by advanced notification
|
||||
mechanism, libev tries hard to emulate \s-1POSIX\s0 behaviour with respect
|
||||
to files, even though you should not use it. The reason for this is
|
||||
convenience: sometimes you want to watch \s-1STDIN\s0 or \s-1STDOUT\s0, which is
|
||||
convenience: sometimes you want to watch \s-1STDIN\s0 or \s-1STDOUT,\s0 which is
|
||||
usually a tty, often a pipe, but also sometimes files or special devices
|
||||
(for example, \f(CW\*(C`epoll\*(C'\fR on Linux works with \fI/dev/random\fR but not with
|
||||
\&\fI/dev/urandom\fR), and even though the file might better be served with
|
||||
@@ -1776,7 +1788,7 @@ asynchronous I/O instead of with non-blocking I/O, it is still useful when
|
||||
it \*(L"just works\*(R" instead of freezing.
|
||||
.PP
|
||||
So avoid file descriptors pointing to files when you know it (e.g. use
|
||||
libeio), but use them when it is convenient, e.g. for \s-1STDIN/STDOUT\s0, or
|
||||
libeio), but use them when it is convenient, e.g. for \s-1STDIN/STDOUT,\s0 or
|
||||
when you rarely read from a file instead of from a socket, and want to
|
||||
reuse the same code path.
|
||||
.PP
|
||||
@@ -1796,17 +1808,17 @@ To support fork in your child processes, you have to call \f(CW\*(C`ev_loop_fork
|
||||
.PP
|
||||
While not really specific to libev, it is easy to forget about \f(CW\*(C`SIGPIPE\*(C'\fR:
|
||||
when writing to a pipe whose other end has been closed, your program gets
|
||||
sent a \s-1SIGPIPE\s0, which, by default, aborts your program. For most programs
|
||||
sent a \s-1SIGPIPE,\s0 which, by default, aborts your program. For most programs
|
||||
this is sensible behaviour, for daemons, this is usually undesirable.
|
||||
.PP
|
||||
So when you encounter spurious, unexplained daemon exits, make sure you
|
||||
ignore \s-1SIGPIPE\s0 (and maybe make sure you log the exit status of your daemon
|
||||
ignore \s-1SIGPIPE \s0(and maybe make sure you log the exit status of your daemon
|
||||
somewhere, as that would have given you a big clue).
|
||||
.PP
|
||||
\fIThe special problem of \fIaccept()\fIing when you can't\fR
|
||||
.IX Subsection "The special problem of accept()ing when you can't"
|
||||
.PP
|
||||
Many implementations of the \s-1POSIX\s0 \f(CW\*(C`accept\*(C'\fR function (for example,
|
||||
Many implementations of the \s-1POSIX \s0\f(CW\*(C`accept\*(C'\fR function (for example,
|
||||
found in post\-2004 Linux) have the peculiar behaviour of not removing a
|
||||
connection from the pending queue in all error cases.
|
||||
.PP
|
||||
@@ -2423,7 +2435,7 @@ ignored. Instead, each time the periodic watcher gets scheduled, the
|
||||
reschedule callback will be called with the watcher as first, and the
|
||||
current time as second argument.
|
||||
.Sp
|
||||
\&\s-1NOTE:\s0 \fIThis callback \s-1MUST\s0 \s-1NOT\s0 stop or destroy any periodic watcher, ever,
|
||||
\&\s-1NOTE: \s0\fIThis callback \s-1MUST NOT\s0 stop or destroy any periodic watcher, ever,
|
||||
or make \s-1ANY\s0 other event loop modifications whatsoever, unless explicitly
|
||||
allowed by documentation here\fR.
|
||||
.Sp
|
||||
@@ -2447,7 +2459,7 @@ It must return the next time to trigger, based on the passed time value
|
||||
will usually be called just before the callback will be triggered, but
|
||||
might be called at other times, too.
|
||||
.Sp
|
||||
\&\s-1NOTE:\s0 \fIThis callback must always return a time that is higher than or
|
||||
\&\s-1NOTE: \s0\fIThis callback must always return a time that is higher than or
|
||||
equal to the passed \f(CI\*(C`now\*(C'\fI value\fR.
|
||||
.Sp
|
||||
This can be used to create very complex timers, such as a timer that
|
||||
@@ -2582,7 +2594,7 @@ to install a fork handler with \f(CW\*(C`pthread_atfork\*(C'\fR that resets it.
|
||||
catch fork calls done by libraries (such as the libc) as well.
|
||||
.PP
|
||||
In current versions of libev, the signal will not be blocked indefinitely
|
||||
unless you use the \f(CW\*(C`signalfd\*(C'\fR \s-1API\s0 (\f(CW\*(C`EV_SIGNALFD\*(C'\fR). While this reduces
|
||||
unless you use the \f(CW\*(C`signalfd\*(C'\fR \s-1API \s0(\f(CW\*(C`EV_SIGNALFD\*(C'\fR). While this reduces
|
||||
the window of opportunity for problems, it will not go away, as libev
|
||||
\&\fIhas\fR to modify the signal mask, at least temporarily.
|
||||
.PP
|
||||
@@ -2622,7 +2634,7 @@ The signal the watcher watches out for.
|
||||
\fIExamples\fR
|
||||
.IX Subsection "Examples"
|
||||
.PP
|
||||
Example: Try to exit cleanly on \s-1SIGINT\s0.
|
||||
Example: Try to exit cleanly on \s-1SIGINT.\s0
|
||||
.PP
|
||||
.Vb 5
|
||||
\& static void
|
||||
@@ -2789,7 +2801,7 @@ support disabled by default, you get the 32 bit version of the stat
|
||||
structure. When using the library from programs that change the \s-1ABI\s0 to
|
||||
use 64 bit file offsets the programs will fail. In that case you have to
|
||||
compile libev with the same flags to get binary compatibility. This is
|
||||
obviously the case with any flags that change the \s-1ABI\s0, but the problem is
|
||||
obviously the case with any flags that change the \s-1ABI,\s0 but the problem is
|
||||
most noticeably displayed with ev_stat and large file support.
|
||||
.PP
|
||||
The solution for this is to lobby your distribution maker to make large
|
||||
@@ -3230,7 +3242,7 @@ callbacks, and only destroy/create the watchers in the prepare watcher.
|
||||
Method 4: Do not use a prepare or check watcher because the module you
|
||||
want to embed is not flexible enough to support it. Instead, you can
|
||||
override their poll function. The drawback with this solution is that the
|
||||
main loop is now no longer controllable by \s-1EV\s0. The \f(CW\*(C`Glib::EV\*(C'\fR module uses
|
||||
main loop is now no longer controllable by \s-1EV.\s0 The \f(CW\*(C`Glib::EV\*(C'\fR module uses
|
||||
this approach, effectively embedding \s-1EV\s0 as a client into the horrible
|
||||
libglib event loop.
|
||||
.PP
|
||||
@@ -3657,7 +3669,7 @@ value passed to \f(CW\*(C`ev_once\*(C'\fR. Note that it is possible to receive \
|
||||
a timeout and an io event at the same time \- you probably should give io
|
||||
events precedence.
|
||||
.Sp
|
||||
Example: wait up to ten seconds for data to appear on \s-1STDIN_FILENO\s0.
|
||||
Example: wait up to ten seconds for data to appear on \s-1STDIN_FILENO.\s0
|
||||
.Sp
|
||||
.Vb 7
|
||||
\& static void stdin_ready (int revents, void *arg)
|
||||
@@ -3683,7 +3695,7 @@ which is async-safe.
|
||||
This section explains some common idioms that are not immediately
|
||||
obvious. Note that examples are sprinkled over the whole manual, and this
|
||||
section only contains stuff that wouldn't fit anywhere else.
|
||||
.SS "\s-1ASSOCIATING\s0 \s-1CUSTOM\s0 \s-1DATA\s0 \s-1WITH\s0 A \s-1WATCHER\s0"
|
||||
.SS "\s-1ASSOCIATING CUSTOM DATA WITH A WATCHER\s0"
|
||||
.IX Subsection "ASSOCIATING CUSTOM DATA WITH A WATCHER"
|
||||
Each watcher has, by default, a \f(CW\*(C`void *data\*(C'\fR member that you can read
|
||||
or modify at any time: libev will completely ignore it. This can be used
|
||||
@@ -3719,7 +3731,7 @@ can cast it back to your own type:
|
||||
.PP
|
||||
More interesting and less C\-conformant ways of casting your callback
|
||||
function type instead have been omitted.
|
||||
.SS "\s-1BUILDING\s0 \s-1YOUR\s0 \s-1OWN\s0 \s-1COMPOSITE\s0 \s-1WATCHERS\s0"
|
||||
.SS "\s-1BUILDING YOUR OWN COMPOSITE WATCHERS\s0"
|
||||
.IX Subsection "BUILDING YOUR OWN COMPOSITE WATCHERS"
|
||||
Another common scenario is to use some data structure with multiple
|
||||
embedded watchers, in effect creating your own watcher that combines
|
||||
@@ -3757,7 +3769,7 @@ real programmers):
|
||||
\& (((char *)w) \- offsetof (struct my_biggy, t2));
|
||||
\& }
|
||||
.Ve
|
||||
.SS "\s-1AVOIDING\s0 \s-1FINISHING\s0 \s-1BEFORE\s0 \s-1RETURNING\s0"
|
||||
.SS "\s-1AVOIDING FINISHING BEFORE RETURNING\s0"
|
||||
.IX Subsection "AVOIDING FINISHING BEFORE RETURNING"
|
||||
Often you have structures like this in event-based programs:
|
||||
.PP
|
||||
@@ -3800,7 +3812,7 @@ pushing it into the pending queue:
|
||||
.PP
|
||||
This way, \f(CW\*(C`start_new_request\*(C'\fR can safely return before the callback is
|
||||
invoked, while not delaying callback invocation too much.
|
||||
.SS "\s-1MODEL/NESTED\s0 \s-1EVENT\s0 \s-1LOOP\s0 \s-1INVOCATIONS\s0 \s-1AND\s0 \s-1EXIT\s0 \s-1CONDITIONS\s0"
|
||||
.SS "\s-1MODEL/NESTED EVENT LOOP INVOCATIONS AND EXIT CONDITIONS\s0"
|
||||
.IX Subsection "MODEL/NESTED EVENT LOOP INVOCATIONS AND EXIT CONDITIONS"
|
||||
Often (especially in \s-1GUI\s0 toolkits) there are places where you have
|
||||
\&\fImodal\fR interaction, which is most easily implemented by recursively
|
||||
@@ -3842,7 +3854,7 @@ To exit from any of these loops, just set the corresponding exit variable:
|
||||
\& // exit both
|
||||
\& exit_main_loop = exit_nested_loop = 1;
|
||||
.Ve
|
||||
.SS "\s-1THREAD\s0 \s-1LOCKING\s0 \s-1EXAMPLE\s0"
|
||||
.SS "\s-1THREAD LOCKING EXAMPLE\s0"
|
||||
.IX Subsection "THREAD LOCKING EXAMPLE"
|
||||
Here is a fictitious example of how to run an event loop in a different
|
||||
thread from where callbacks are being invoked and watchers are
|
||||
@@ -3993,7 +4005,7 @@ Note that sending the \f(CW\*(C`ev_async\*(C'\fR watcher is required because oth
|
||||
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.
|
||||
.SS "\s-1THREADS\s0, \s-1COROUTINES\s0, \s-1CONTINUATIONS\s0, \s-1QUEUES\s0... \s-1INSTEAD\s0 \s-1OF\s0 \s-1CALLBACKS\s0"
|
||||
.SS "\s-1THREADS, COROUTINES, CONTINUATIONS, QUEUES... INSTEAD OF CALLBACKS\s0"
|
||||
.IX Subsection "THREADS, COROUTINES, CONTINUATIONS, QUEUES... INSTEAD OF CALLBACKS"
|
||||
While the overhead of a callback that e.g. schedules a thread is small, it
|
||||
is still an overhead. If you embed libev, and your main usage is with some
|
||||
@@ -4039,7 +4051,7 @@ instead of storing a coroutine, you store the queue object and instead of
|
||||
switching to a coroutine, you push the watcher onto the queue and notify
|
||||
any waiters.
|
||||
.PP
|
||||
To embed libev, see \*(L"\s-1EMBEDDING\s0\*(R", but in short, it's easiest to create two
|
||||
To embed libev, see \*(L"\s-1EMBEDDING\*(R"\s0, but in short, it's easiest to create two
|
||||
files, \fImy_ev.h\fR and \fImy_ev.c\fR that include the respective libev files:
|
||||
.PP
|
||||
.Vb 4
|
||||
@@ -4344,7 +4356,7 @@ to \f(CW\*(C`libadns\*(C'\fR (\f(CW\*(C`EV::ADNS\*(C'\fR, but \f(CW\*(C`AnyEvent
|
||||
\&\f(CW\*(C`Net::SNMP\*(C'\fR (\f(CW\*(C`Net::SNMP::EV\*(C'\fR) and the \f(CW\*(C`libglib\*(C'\fR event core (\f(CW\*(C`Glib::EV\*(C'\fR
|
||||
and \f(CW\*(C`EV::Glib\*(C'\fR).
|
||||
.Sp
|
||||
It can be found and installed via \s-1CPAN\s0, its homepage is at
|
||||
It can be found and installed via \s-1CPAN,\s0 its homepage is at
|
||||
<http://software.schmorp.de/pkg/EV>.
|
||||
.IP "Python" 4
|
||||
.IX Item "Python"
|
||||
@@ -4362,7 +4374,7 @@ makes rev work even on mingw.
|
||||
.IP "Haskell" 4
|
||||
.IX Item "Haskell"
|
||||
A haskell binding to libev is available at
|
||||
http://hackage.haskell.org/cgi\-bin/hackage\-scripts/package/hlibev <http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hlibev>.
|
||||
<http://hackage.haskell.org/cgi\-bin/hackage\-scripts/package/hlibev>.
|
||||
.IP "D" 4
|
||||
.IX Item "D"
|
||||
Leandro Lucarella has written a D language binding (\fIev.d\fR) for libev, to
|
||||
@@ -4370,12 +4382,12 @@ be found at <http://www.llucax.com.ar/proj/ev.d/index.html>.
|
||||
.IP "Ocaml" 4
|
||||
.IX Item "Ocaml"
|
||||
Erkki Seppala has written Ocaml bindings for libev, to be found at
|
||||
http://modeemi.cs.tut.fi/~flux/software/ocaml\-ev/ <http://modeemi.cs.tut.fi/~flux/software/ocaml-ev/>.
|
||||
<http://modeemi.cs.tut.fi/~flux/software/ocaml\-ev/>.
|
||||
.IP "Lua" 4
|
||||
.IX Item "Lua"
|
||||
Brian Maher has written a partial interface to libev for lua (at the
|
||||
time of this writing, only \f(CW\*(C`ev_io\*(C'\fR and \f(CW\*(C`ev_timer\*(C'\fR), to be found at
|
||||
http://github.com/brimworks/lua\-ev <http://github.com/brimworks/lua-ev>.
|
||||
<http://github.com/brimworks/lua\-ev>.
|
||||
.IP "Javascript" 4
|
||||
.IX Item "Javascript"
|
||||
Node.js (<http://nodejs.org>) uses libev as the underlying event library.
|
||||
@@ -4474,7 +4486,7 @@ libev somewhere in your source tree).
|
||||
Depending on what features you need you need to include one or more sets of files
|
||||
in your application.
|
||||
.PP
|
||||
\fI\s-1CORE\s0 \s-1EVENT\s0 \s-1LOOP\s0\fR
|
||||
\fI\s-1CORE EVENT LOOP\s0\fR
|
||||
.IX Subsection "CORE EVENT LOOP"
|
||||
.PP
|
||||
To include only the libev core (all the \f(CW\*(C`ev_*\*(C'\fR functions), with manual
|
||||
@@ -4487,7 +4499,7 @@ configuration (no autoconf):
|
||||
.PP
|
||||
This will automatically include \fIev.h\fR, too, and should be done in a
|
||||
single C source file only to provide the function implementations. To use
|
||||
it, do the same for \fIev.h\fR in all files wishing to use this \s-1API\s0 (best
|
||||
it, do the same for \fIev.h\fR in all files wishing to use this \s-1API \s0(best
|
||||
done by writing a wrapper around \fIev.h\fR that you can include instead and
|
||||
where you can put other configuration options):
|
||||
.PP
|
||||
@@ -4521,10 +4533,10 @@ in your include path (e.g. in libev/ when using \-Ilibev):
|
||||
\&\fIev.c\fR includes the backend files directly when enabled, so you only need
|
||||
to compile this single file.
|
||||
.PP
|
||||
\fI\s-1LIBEVENT\s0 \s-1COMPATIBILITY\s0 \s-1API\s0\fR
|
||||
\fI\s-1LIBEVENT COMPATIBILITY API\s0\fR
|
||||
.IX Subsection "LIBEVENT COMPATIBILITY API"
|
||||
.PP
|
||||
To include the libevent compatibility \s-1API\s0, also include:
|
||||
To include the libevent compatibility \s-1API,\s0 also include:
|
||||
.PP
|
||||
.Vb 1
|
||||
\& #include "event.c"
|
||||
@@ -4536,7 +4548,7 @@ in the file including \fIev.c\fR, and:
|
||||
\& #include "event.h"
|
||||
.Ve
|
||||
.PP
|
||||
in the files that want to use the libevent \s-1API\s0. This also includes \fIev.h\fR.
|
||||
in the files that want to use the libevent \s-1API.\s0 This also includes \fIev.h\fR.
|
||||
.PP
|
||||
You need the following additional files for this:
|
||||
.PP
|
||||
@@ -4545,7 +4557,7 @@ You need the following additional files for this:
|
||||
\& event.c
|
||||
.Ve
|
||||
.PP
|
||||
\fI\s-1AUTOCONF\s0 \s-1SUPPORT\s0\fR
|
||||
\fI\s-1AUTOCONF SUPPORT\s0\fR
|
||||
.IX Subsection "AUTOCONF SUPPORT"
|
||||
.PP
|
||||
Instead of using \f(CW\*(C`EV_STANDALONE=1\*(C'\fR and providing your configuration in
|
||||
@@ -4558,19 +4570,19 @@ For this of course you need the m4 file:
|
||||
.Vb 1
|
||||
\& libev.m4
|
||||
.Ve
|
||||
.SS "\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0"
|
||||
.SS "\s-1PREPROCESSOR SYMBOLS/MACROS\s0"
|
||||
.IX Subsection "PREPROCESSOR SYMBOLS/MACROS"
|
||||
Libev can be configured via a variety of preprocessor symbols you have to
|
||||
define before including (or compiling) any of its files. The default in
|
||||
the absence of autoconf is documented for every option.
|
||||
.PP
|
||||
Symbols marked with \*(L"(h)\*(R" do not change the \s-1ABI\s0, and can have different
|
||||
Symbols marked with \*(L"(h)\*(R" do not change the \s-1ABI,\s0 and can have different
|
||||
values when compiling libev vs. including \fIev.h\fR, so it is permissible
|
||||
to redefine them before including \fIev.h\fR without breaking compatibility
|
||||
to a compiled library. All other symbols change the \s-1ABI\s0, which means all
|
||||
to a compiled library. All other symbols change the \s-1ABI,\s0 which means all
|
||||
users of libev and the libev code itself must be compiled with compatible
|
||||
settings.
|
||||
.IP "\s-1EV_COMPAT3\s0 (h)" 4
|
||||
.IP "\s-1EV_COMPAT3 \s0(h)" 4
|
||||
.IX Item "EV_COMPAT3 (h)"
|
||||
Backwards compatibility is a major concern for libev. This is why this
|
||||
release of libev comes with wrappers for the functions and symbols that
|
||||
@@ -4585,7 +4597,7 @@ typedef in that case.
|
||||
In some future version, the default for \f(CW\*(C`EV_COMPAT3\*(C'\fR will become \f(CW0\fR,
|
||||
and in some even more future version the compatibility code will be
|
||||
removed completely.
|
||||
.IP "\s-1EV_STANDALONE\s0 (h)" 4
|
||||
.IP "\s-1EV_STANDALONE \s0(h)" 4
|
||||
.IX Item "EV_STANDALONE (h)"
|
||||
Must always be \f(CW1\fR if you do not use autoconf configuration, which
|
||||
keeps libev from including \fIconfig.h\fR, and it also defines dummy
|
||||
@@ -4753,21 +4765,21 @@ watchers.
|
||||
.Sp
|
||||
In the absence of this define, libev will use \f(CW\*(C`sig_atomic_t volatile\*(C'\fR
|
||||
(from \fIsignal.h\fR), which is usually good enough on most platforms.
|
||||
.IP "\s-1EV_H\s0 (h)" 4
|
||||
.IP "\s-1EV_H \s0(h)" 4
|
||||
.IX Item "EV_H (h)"
|
||||
The name of the \fIev.h\fR header file used to include it. The default if
|
||||
undefined is \f(CW"ev.h"\fR in \fIevent.h\fR, \fIev.c\fR and \fIev++.h\fR. This can be
|
||||
used to virtually rename the \fIev.h\fR header file in case of conflicts.
|
||||
.IP "\s-1EV_CONFIG_H\s0 (h)" 4
|
||||
.IP "\s-1EV_CONFIG_H \s0(h)" 4
|
||||
.IX Item "EV_CONFIG_H (h)"
|
||||
If \f(CW\*(C`EV_STANDALONE\*(C'\fR isn't \f(CW1\fR, this variable can be used to override
|
||||
\&\fIev.c\fR's idea of where to find the \fIconfig.h\fR file, similarly to
|
||||
\&\f(CW\*(C`EV_H\*(C'\fR, above.
|
||||
.IP "\s-1EV_EVENT_H\s0 (h)" 4
|
||||
.IP "\s-1EV_EVENT_H \s0(h)" 4
|
||||
.IX Item "EV_EVENT_H (h)"
|
||||
Similarly to \f(CW\*(C`EV_H\*(C'\fR, this macro can be used to override \fIevent.c\fR's idea
|
||||
of how the \fIevent.h\fR header can be found, the default is \f(CW"event.h"\fR.
|
||||
.IP "\s-1EV_PROTOTYPES\s0 (h)" 4
|
||||
.IP "\s-1EV_PROTOTYPES \s0(h)" 4
|
||||
.IX Item "EV_PROTOTYPES (h)"
|
||||
If defined to be \f(CW0\fR, then \fIev.h\fR will not define any function
|
||||
prototypes, but still define all the structs and other symbols. This is
|
||||
@@ -4801,8 +4813,8 @@ and time, so using the defaults of five priorities (\-2 .. +2) is usually
|
||||
fine.
|
||||
.Sp
|
||||
If your embedding application does not need any priorities, defining these
|
||||
both to \f(CW0\fR will save some memory and \s-1CPU\s0.
|
||||
.IP "\s-1EV_PERIODIC_ENABLE\s0, \s-1EV_IDLE_ENABLE\s0, \s-1EV_EMBED_ENABLE\s0, \s-1EV_STAT_ENABLE\s0, \s-1EV_PREPARE_ENABLE\s0, \s-1EV_CHECK_ENABLE\s0, \s-1EV_FORK_ENABLE\s0, \s-1EV_SIGNAL_ENABLE\s0, \s-1EV_ASYNC_ENABLE\s0, \s-1EV_CHILD_ENABLE\s0." 4
|
||||
both to \f(CW0\fR will save some memory and \s-1CPU.\s0
|
||||
.IP "\s-1EV_PERIODIC_ENABLE, EV_IDLE_ENABLE, EV_EMBED_ENABLE, EV_STAT_ENABLE, EV_PREPARE_ENABLE, EV_CHECK_ENABLE, EV_FORK_ENABLE, EV_SIGNAL_ENABLE, EV_ASYNC_ENABLE, EV_CHILD_ENABLE.\s0" 4
|
||||
.IX Item "EV_PERIODIC_ENABLE, EV_IDLE_ENABLE, EV_EMBED_ENABLE, EV_STAT_ENABLE, EV_PREPARE_ENABLE, EV_CHECK_ENABLE, EV_FORK_ENABLE, EV_SIGNAL_ENABLE, EV_ASYNC_ENABLE, EV_CHILD_ENABLE."
|
||||
If undefined or defined to be \f(CW1\fR (and the platform supports it), then
|
||||
the respective watcher type is supported. If defined to be \f(CW0\fR, then it
|
||||
@@ -4986,10 +4998,10 @@ For example, the perl \s-1EV\s0 module uses something like this:
|
||||
\& SV *self; /* contains this struct */ \e
|
||||
\& SV *cb_sv, *fh /* note no trailing ";" */
|
||||
.Ve
|
||||
.IP "\s-1EV_CB_DECLARE\s0 (type)" 4
|
||||
.IP "\s-1EV_CB_DECLARE \s0(type)" 4
|
||||
.IX Item "EV_CB_DECLARE (type)"
|
||||
.PD 0
|
||||
.IP "\s-1EV_CB_INVOKE\s0 (watcher, revents)" 4
|
||||
.IP "\s-1EV_CB_INVOKE \s0(watcher, revents)" 4
|
||||
.IX Item "EV_CB_INVOKE (watcher, revents)"
|
||||
.IP "ev_set_cb (ev, cb)" 4
|
||||
.IX Item "ev_set_cb (ev, cb)"
|
||||
@@ -5000,9 +5012,9 @@ definition and a statement, respectively. See the \fIev.h\fR header file for
|
||||
their default definitions. One possible use for overriding these is to
|
||||
avoid the \f(CW\*(C`struct ev_loop *\*(C'\fR as first argument in all cases, or to use
|
||||
method calls instead of plain function calls in \*(C+.
|
||||
.SS "\s-1EXPORTED\s0 \s-1API\s0 \s-1SYMBOLS\s0"
|
||||
.SS "\s-1EXPORTED API SYMBOLS\s0"
|
||||
.IX Subsection "EXPORTED API SYMBOLS"
|
||||
If you need to re-export the \s-1API\s0 (e.g. via a \s-1DLL\s0) and you need a list of
|
||||
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
|
||||
all public symbols, one per line:
|
||||
.PP
|
||||
@@ -5064,7 +5076,7 @@ And a \fIev_cpp.C\fR implementation file that contains libev proper and is compi
|
||||
.Ve
|
||||
.SH "INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT"
|
||||
.IX Header "INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT"
|
||||
.SS "\s-1THREADS\s0 \s-1AND\s0 \s-1COROUTINES\s0"
|
||||
.SS "\s-1THREADS AND COROUTINES\s0"
|
||||
.IX Subsection "THREADS AND COROUTINES"
|
||||
\fI\s-1THREADS\s0\fR
|
||||
.IX Subsection "THREADS"
|
||||
@@ -5120,7 +5132,7 @@ work in the default loop by registering the signal watcher with the
|
||||
default loop and triggering an \f(CW\*(C`ev_async\*(C'\fR watcher from the default loop
|
||||
watcher callback into the event loop interested in the signal.
|
||||
.PP
|
||||
See also \*(L"\s-1THREAD\s0 \s-1LOCKING\s0 \s-1EXAMPLE\s0\*(R".
|
||||
See also \*(L"\s-1THREAD LOCKING EXAMPLE\*(R"\s0.
|
||||
.PP
|
||||
\fI\s-1COROUTINES\s0\fR
|
||||
.IX Subsection "COROUTINES"
|
||||
@@ -5135,7 +5147,7 @@ that you must not do this from \f(CW\*(C`ev_periodic\*(C'\fR reschedule callback
|
||||
Care has been taken to ensure that libev does not keep local state inside
|
||||
\&\f(CW\*(C`ev_run\*(C'\fR, and other calls do not usually allow for coroutine switches as
|
||||
they do not call any callbacks.
|
||||
.SS "\s-1COMPILER\s0 \s-1WARNINGS\s0"
|
||||
.SS "\s-1COMPILER WARNINGS\s0"
|
||||
.IX Subsection "COMPILER WARNINGS"
|
||||
Depending on your compiler and compiler settings, you might get no or a
|
||||
lot of warnings when compiling libev code. Some people are apparently
|
||||
@@ -5197,7 +5209,7 @@ If you need, for some reason, empty reports from valgrind for your project
|
||||
I suggest using suppression lists.
|
||||
.SH "PORTABILITY NOTES"
|
||||
.IX Header "PORTABILITY NOTES"
|
||||
.SS "\s-1GNU/LINUX\s0 32 \s-1BIT\s0 \s-1LIMITATIONS\s0"
|
||||
.SS "\s-1GNU/LINUX 32 BIT LIMITATIONS\s0"
|
||||
.IX Subsection "GNU/LINUX 32 BIT LIMITATIONS"
|
||||
GNU/Linux is the only common platform that supports 64 bit file/large file
|
||||
interfaces but \fIdisables\fR them by default.
|
||||
@@ -5206,13 +5218,13 @@ That means that libev compiled in the default environment doesn't support
|
||||
files larger than 2GiB or so, which mainly affects \f(CW\*(C`ev_stat\*(C'\fR watchers.
|
||||
.PP
|
||||
Unfortunately, many programs try to work around this GNU/Linux issue
|
||||
by enabling the large file \s-1API\s0, which makes them incompatible with the
|
||||
by enabling the large file \s-1API,\s0 which makes them incompatible with the
|
||||
standard libev compiled for their system.
|
||||
.PP
|
||||
Likewise, libev cannot enable the large file \s-1API\s0 itself as this would
|
||||
suddenly make it incompatible to the default compile time environment,
|
||||
i.e. all programs not using special compile switches.
|
||||
.SS "\s-1OS/X\s0 \s-1AND\s0 \s-1DARWIN\s0 \s-1BUGS\s0"
|
||||
.SS "\s-1OS/X AND DARWIN BUGS\s0"
|
||||
.IX Subsection "OS/X AND DARWIN BUGS"
|
||||
The whole thing is a bug if you ask me \- basically any system interface
|
||||
you touch is broken, whether it is locales, poll, kqueue or even the
|
||||
@@ -5244,14 +5256,14 @@ a loop.
|
||||
.IX Subsection "select is buggy"
|
||||
.PP
|
||||
All that's left is \f(CW\*(C`select\*(C'\fR, and of course Apple found a way to fuck this
|
||||
one up as well: On \s-1OS/X\s0, \f(CW\*(C`select\*(C'\fR actively limits the number of file
|
||||
one up as well: On \s-1OS/X, \s0\f(CW\*(C`select\*(C'\fR actively limits the number of file
|
||||
descriptors you can pass in to 1024 \- your program suddenly crashes when
|
||||
you use more.
|
||||
.PP
|
||||
There is an undocumented \*(L"workaround\*(R" for this \- defining
|
||||
\&\f(CW\*(C`_DARWIN_UNLIMITED_SELECT\*(C'\fR, which libev tries to use, so select \fIshould\fR
|
||||
work on \s-1OS/X\s0.
|
||||
.SS "\s-1SOLARIS\s0 \s-1PROBLEMS\s0 \s-1AND\s0 \s-1WORKAROUNDS\s0"
|
||||
work on \s-1OS/X.\s0
|
||||
.SS "\s-1SOLARIS PROBLEMS AND WORKAROUNDS\s0"
|
||||
.IX Subsection "SOLARIS PROBLEMS AND WORKAROUNDS"
|
||||
\fI\f(CI\*(C`errno\*(C'\fI reentrancy\fR
|
||||
.IX Subsection "errno reentrancy"
|
||||
@@ -5278,13 +5290,13 @@ great.
|
||||
If you can't get it to work, you can try running the program by setting
|
||||
the environment variable \f(CW\*(C`LIBEV_FLAGS=3\*(C'\fR to only allow \f(CW\*(C`poll\*(C'\fR and
|
||||
\&\f(CW\*(C`select\*(C'\fR backends.
|
||||
.SS "\s-1AIX\s0 \s-1POLL\s0 \s-1BUG\s0"
|
||||
.SS "\s-1AIX POLL BUG\s0"
|
||||
.IX Subsection "AIX POLL BUG"
|
||||
\&\s-1AIX\s0 unfortunately has a broken \f(CW\*(C`poll.h\*(C'\fR header. Libev works around
|
||||
this by trying to avoid the poll backend altogether (i.e. it's not even
|
||||
compiled in), which normally isn't a big problem as \f(CW\*(C`select\*(C'\fR works fine
|
||||
with large bitsets on \s-1AIX\s0, and \s-1AIX\s0 is dead anyway.
|
||||
.SS "\s-1WIN32\s0 \s-1PLATFORM\s0 \s-1LIMITATIONS\s0 \s-1AND\s0 \s-1WORKAROUNDS\s0"
|
||||
with large bitsets on \s-1AIX,\s0 and \s-1AIX\s0 is dead anyway.
|
||||
.SS "\s-1WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS\s0"
|
||||
.IX Subsection "WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS"
|
||||
\fIGeneral issues\fR
|
||||
.IX Subsection "General issues"
|
||||
@@ -5390,7 +5402,7 @@ runtime libraries. This might get you to about \f(CW512\fR or \f(CW2048\fR socke
|
||||
(depending on windows version and/or the phase of the moon). To get more,
|
||||
you need to wrap all I/O functions and provide your own fd management, but
|
||||
the cost of calling select (O(nX)) will likely make this unworkable.
|
||||
.SS "\s-1PORTABILITY\s0 \s-1REQUIREMENTS\s0"
|
||||
.SS "\s-1PORTABILITY REQUIREMENTS\s0"
|
||||
.IX Subsection "PORTABILITY REQUIREMENTS"
|
||||
In addition to a working ISO-C implementation and of course the
|
||||
backend-specific APIs, libev relies on a few additional extensions:
|
||||
@@ -5398,7 +5410,7 @@ backend-specific APIs, libev relies on a few additional extensions:
|
||||
.el .IP "\f(CWvoid (*)(ev_watcher_type *, int revents)\fR must have compatible calling conventions regardless of \f(CWev_watcher_type *\fR." 4
|
||||
.IX Item "void (*)(ev_watcher_type *, int revents) must have compatible calling conventions regardless of ev_watcher_type *."
|
||||
Libev assumes not only that all watcher pointers have the same internal
|
||||
structure (guaranteed by \s-1POSIX\s0 but not by \s-1ISO\s0 C for example), but it also
|
||||
structure (guaranteed by \s-1POSIX\s0 but not by \s-1ISO C\s0 for example), but it also
|
||||
assumes that the same (machine) code can be used to call any watcher
|
||||
callback: The watcher callbacks have different type signatures, but libev
|
||||
calls them using an \f(CW\*(C`ev_watcher *\*(C'\fR internally.
|
||||
@@ -5429,7 +5441,7 @@ thread as well.
|
||||
.ie n .IP """long"" must be large enough for common memory allocation sizes" 4
|
||||
.el .IP "\f(CWlong\fR must be large enough for common memory allocation sizes" 4
|
||||
.IX Item "long must be large enough for common memory allocation sizes"
|
||||
To improve portability and simplify its \s-1API\s0, libev uses \f(CW\*(C`long\*(C'\fR internally
|
||||
To improve portability and simplify its \s-1API,\s0 libev uses \f(CW\*(C`long\*(C'\fR internally
|
||||
instead of \f(CW\*(C`size_t\*(C'\fR when allocating its data structures. On non-POSIX
|
||||
systems (Microsoft...) this might be unexpectedly low, but is still at
|
||||
least 31 bits everywhere, which is enough for hundreds of millions of
|
||||
@@ -5441,9 +5453,9 @@ The type \f(CW\*(C`double\*(C'\fR is used to represent timestamps. It is require
|
||||
have at least 51 bits of mantissa (and 9 bits of exponent), which is
|
||||
good enough for at least into the year 4000 with millisecond accuracy
|
||||
(the design goal for libev). This requirement is overfulfilled by
|
||||
implementations using \s-1IEEE\s0 754, which is basically all existing ones.
|
||||
implementations using \s-1IEEE 754,\s0 which is basically all existing ones.
|
||||
.Sp
|
||||
With \s-1IEEE\s0 754 doubles, you get microsecond accuracy until at least the
|
||||
With \s-1IEEE 754\s0 doubles, you get microsecond accuracy until at least the
|
||||
year 2255 (and millisecond accuracy till the year 287396 \- by then, libev
|
||||
is either obsolete or somebody patched it to use \f(CW\*(C`long double\*(C'\fR or
|
||||
something like that, just kidding).
|
||||
@@ -5515,7 +5527,7 @@ blocked. Checking for async and signal events involves iterating over all
|
||||
running async watchers or all signal numbers.
|
||||
.SH "PORTING FROM LIBEV 3.X TO 4.X"
|
||||
.IX Header "PORTING FROM LIBEV 3.X TO 4.X"
|
||||
The major version 4 introduced some incompatible changes to the \s-1API\s0.
|
||||
The major version 4 introduced some incompatible changes to the \s-1API.\s0
|
||||
.PP
|
||||
At the moment, the \f(CW\*(C`ev.h\*(C'\fR header file provides compatibility definitions
|
||||
for all changes, so most programs should still compile. The compatibility
|
||||
@@ -5525,7 +5537,7 @@ new \s-1API\s0 early than late.
|
||||
.el .IP "\f(CWEV_COMPAT3\fR backwards compatibility mechanism" 4
|
||||
.IX Item "EV_COMPAT3 backwards compatibility mechanism"
|
||||
The backward compatibility mechanism can be controlled by
|
||||
\&\f(CW\*(C`EV_COMPAT3\*(C'\fR. See \*(L"\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0\*(R" in the \*(L"\s-1EMBEDDING\s0\*(R"
|
||||
\&\f(CW\*(C`EV_COMPAT3\*(C'\fR. See \*(L"\s-1PREPROCESSOR SYMBOLS/MACROS\*(R"\s0 in the \*(L"\s-1EMBEDDING\*(R"\s0
|
||||
section.
|
||||
.ie n .IP """ev_default_destroy"" and ""ev_default_fork"" have been removed" 4
|
||||
.el .IP "\f(CWev_default_destroy\fR and \f(CWev_default_fork\fR have been removed" 4
|
||||
@@ -5575,7 +5587,7 @@ and work, but the library code will of course be larger.
|
||||
.IP "active" 4
|
||||
.IX Item "active"
|
||||
A watcher is active as long as it has been started and not yet stopped.
|
||||
See \*(L"\s-1WATCHER\s0 \s-1STATES\s0\*(R" for details.
|
||||
See \*(L"\s-1WATCHER STATES\*(R"\s0 for details.
|
||||
.IP "application" 4
|
||||
.IX Item "application"
|
||||
In this document, an application is whatever is using libev.
|
||||
@@ -5612,7 +5624,7 @@ watchers and events.
|
||||
.IP "pending" 4
|
||||
.IX Item "pending"
|
||||
A watcher is pending as soon as the corresponding event has been
|
||||
detected. See \*(L"\s-1WATCHER\s0 \s-1STATES\s0\*(R" for details.
|
||||
detected. See \*(L"\s-1WATCHER STATES\*(R"\s0 for details.
|
||||
.IP "real time" 4
|
||||
.IX Item "real time"
|
||||
The physical time that is observed. It is apparently strictly monotonic :)
|
||||
|
||||
+172
-39
@@ -534,7 +534,7 @@ struct signalfd_siginfo
|
||||
#define ECB_H
|
||||
|
||||
/* 16 bits major, 16 bits minor */
|
||||
#define ECB_VERSION 0x00010004
|
||||
#define ECB_VERSION 0x00010005
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef signed char int8_t;
|
||||
@@ -561,7 +561,7 @@ struct signalfd_siginfo
|
||||
#endif
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#if UINTMAX_MAX > 0xffffffffU
|
||||
#if (defined INTPTR_MAX ? INTPTR_MAX : ULONG_MAX) > 0xffffffffU
|
||||
#define ECB_PTRSIZE 8
|
||||
#else
|
||||
#define ECB_PTRSIZE 4
|
||||
@@ -649,6 +649,10 @@ struct signalfd_siginfo
|
||||
#include <builtins.h>
|
||||
#endif
|
||||
|
||||
#if 1400 <= _MSC_VER
|
||||
#include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */
|
||||
#endif
|
||||
|
||||
#ifndef ECB_MEMORY_FENCE
|
||||
#if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
|
||||
#if __i386 || __i386__
|
||||
@@ -661,15 +665,23 @@ struct signalfd_siginfo
|
||||
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
|
||||
#elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
|
||||
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
|
||||
#elif defined __ARM_ARCH_2__ \
|
||||
|| defined __ARM_ARCH_3__ || defined __ARM_ARCH_3M__ \
|
||||
|| defined __ARM_ARCH_4__ || defined __ARM_ARCH_4T__ \
|
||||
|| defined __ARM_ARCH_5__ || defined __ARM_ARCH_5E__ \
|
||||
|| defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__ \
|
||||
|| defined __ARM_ARCH_5TEJ__
|
||||
/* should not need any, unless running old code on newer cpu - arm doesn't support that */
|
||||
#elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \
|
||||
|| defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__
|
||||
|| defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ \
|
||||
|| defined __ARM_ARCH_6T2__
|
||||
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
|
||||
#elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
|
||||
|| defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__
|
||||
|| defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__
|
||||
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
|
||||
#elif __aarch64__
|
||||
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||
#elif (__sparc || __sparc__) && !__sparcv8
|
||||
#elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8)
|
||||
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
|
||||
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
|
||||
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
|
||||
@@ -917,6 +929,11 @@ typedef int ecb_bool;
|
||||
ecb_function_ ecb_const int
|
||||
ecb_ctz32 (uint32_t x)
|
||||
{
|
||||
#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
|
||||
unsigned long r;
|
||||
_BitScanForward (&r, x);
|
||||
return (int)r;
|
||||
#else
|
||||
int r = 0;
|
||||
|
||||
x &= ~x + 1; /* this isolates the lowest bit */
|
||||
@@ -936,14 +953,21 @@ typedef int ecb_bool;
|
||||
#endif
|
||||
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);
|
||||
ecb_function_ ecb_const int
|
||||
ecb_ctz64 (uint64_t x)
|
||||
{
|
||||
int shift = x & 0xffffffffU ? 0 : 32;
|
||||
#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
|
||||
unsigned long r;
|
||||
_BitScanForward64 (&r, x);
|
||||
return (int)r;
|
||||
#else
|
||||
int shift = x & 0xffffffff ? 0 : 32;
|
||||
return ecb_ctz32 (x >> shift) + shift;
|
||||
#endif
|
||||
}
|
||||
|
||||
ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);
|
||||
@@ -961,6 +985,11 @@ typedef int ecb_bool;
|
||||
ecb_function_ ecb_const int ecb_ld32 (uint32_t x);
|
||||
ecb_function_ ecb_const int ecb_ld32 (uint32_t x)
|
||||
{
|
||||
#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
|
||||
unsigned long r;
|
||||
_BitScanReverse (&r, x);
|
||||
return (int)r;
|
||||
#else
|
||||
int r = 0;
|
||||
|
||||
if (x >> 16) { x >>= 16; r += 16; }
|
||||
@@ -970,16 +999,23 @@ typedef int ecb_bool;
|
||||
if (x >> 1) { r += 1; }
|
||||
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
ecb_function_ ecb_const int ecb_ld64 (uint64_t x);
|
||||
ecb_function_ ecb_const int ecb_ld64 (uint64_t x)
|
||||
{
|
||||
#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
|
||||
unsigned long r;
|
||||
_BitScanReverse64 (&r, x);
|
||||
return (int)r;
|
||||
#else
|
||||
int r = 0;
|
||||
|
||||
if (x >> 32) { x >>= 32; r += 32; }
|
||||
|
||||
return r + ecb_ld32 (x);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1092,8 +1128,8 @@ ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { retu
|
||||
/* try to tell the compiler that some condition is definitely true */
|
||||
#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
|
||||
|
||||
ecb_inline ecb_const unsigned char ecb_byteorder_helper (void);
|
||||
ecb_inline ecb_const unsigned char
|
||||
ecb_inline ecb_const uint32_t ecb_byteorder_helper (void);
|
||||
ecb_inline ecb_const uint32_t
|
||||
ecb_byteorder_helper (void)
|
||||
{
|
||||
/* the union code still generates code under pressure in gcc, */
|
||||
@@ -1102,26 +1138,28 @@ ecb_byteorder_helper (void)
|
||||
/* the reason why we have this horrible preprocessor mess */
|
||||
/* is to avoid it in all cases, at least on common architectures */
|
||||
/* or when using a recent enough gcc version (>= 4.6) */
|
||||
#if ((__i386 || __i386__) && !__VOS__) || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64
|
||||
return 0x44;
|
||||
#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
return 0x44;
|
||||
#elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
return 0x11;
|
||||
#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
|
||||
|| ((__i386 || __i386__ || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64) && !__VOS__)
|
||||
#define ECB_LITTLE_ENDIAN 1
|
||||
return 0x44332211;
|
||||
#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \
|
||||
|| ((__AARCH64EB__ || __MIPSEB__ || __ARMEB__) && !__VOS__)
|
||||
#define ECB_BIG_ENDIAN 1
|
||||
return 0x11223344;
|
||||
#else
|
||||
union
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t c;
|
||||
} u = { 0x11223344 };
|
||||
return u.c;
|
||||
uint8_t c[4];
|
||||
uint32_t u;
|
||||
} u = { 0x11, 0x22, 0x33, 0x44 };
|
||||
return u.u;
|
||||
#endif
|
||||
}
|
||||
|
||||
ecb_inline ecb_const ecb_bool ecb_big_endian (void);
|
||||
ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; }
|
||||
ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11223344; }
|
||||
ecb_inline ecb_const ecb_bool ecb_little_endian (void);
|
||||
ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; }
|
||||
ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; }
|
||||
|
||||
#if ECB_GCC_VERSION(3,0) || ECB_C99
|
||||
#define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
|
||||
@@ -1156,6 +1194,102 @@ ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_he
|
||||
#define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
|
||||
#endif
|
||||
|
||||
ecb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);
|
||||
ecb_function_ ecb_const uint32_t
|
||||
ecb_binary16_to_binary32 (uint32_t x)
|
||||
{
|
||||
unsigned int s = (x & 0x8000) << (31 - 15);
|
||||
int e = (x >> 10) & 0x001f;
|
||||
unsigned int m = x & 0x03ff;
|
||||
|
||||
if (ecb_expect_false (e == 31))
|
||||
/* infinity or NaN */
|
||||
e = 255 - (127 - 15);
|
||||
else if (ecb_expect_false (!e))
|
||||
{
|
||||
if (ecb_expect_true (!m))
|
||||
/* zero, handled by code below by forcing e to 0 */
|
||||
e = 0 - (127 - 15);
|
||||
else
|
||||
{
|
||||
/* subnormal, renormalise */
|
||||
unsigned int s = 10 - ecb_ld32 (m);
|
||||
|
||||
m = (m << s) & 0x3ff; /* mask implicit bit */
|
||||
e -= s - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* e and m now are normalised, or zero, (or inf or nan) */
|
||||
e += 127 - 15;
|
||||
|
||||
return s | (e << 23) | (m << (23 - 10));
|
||||
}
|
||||
|
||||
ecb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x);
|
||||
ecb_function_ ecb_const uint16_t
|
||||
ecb_binary32_to_binary16 (uint32_t x)
|
||||
{
|
||||
unsigned int s = (x >> 16) & 0x00008000; /* sign bit, the easy part */
|
||||
unsigned int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */
|
||||
unsigned int m = x & 0x007fffff;
|
||||
|
||||
x &= 0x7fffffff;
|
||||
|
||||
/* if it's within range of binary16 normals, use fast path */
|
||||
if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff))
|
||||
{
|
||||
/* mantissa round-to-even */
|
||||
m += 0x00000fff + ((m >> (23 - 10)) & 1);
|
||||
|
||||
/* handle overflow */
|
||||
if (ecb_expect_false (m >= 0x00800000))
|
||||
{
|
||||
m >>= 1;
|
||||
e += 1;
|
||||
}
|
||||
|
||||
return s | (e << 10) | (m >> (23 - 10));
|
||||
}
|
||||
|
||||
/* handle large numbers and infinity */
|
||||
if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000))
|
||||
return s | 0x7c00;
|
||||
|
||||
/* handle zero, subnormals and small numbers */
|
||||
if (ecb_expect_true (x < 0x38800000))
|
||||
{
|
||||
/* zero */
|
||||
if (ecb_expect_true (!x))
|
||||
return s;
|
||||
|
||||
/* handle subnormals */
|
||||
|
||||
/* too small, will be zero */
|
||||
if (e < (14 - 24)) /* might not be sharp, but is good enough */
|
||||
return s;
|
||||
|
||||
m |= 0x00800000; /* make implicit bit explicit */
|
||||
|
||||
/* very tricky - we need to round to the nearest e (+10) bit value */
|
||||
{
|
||||
unsigned int bits = 14 - e;
|
||||
unsigned int half = (1 << (bits - 1)) - 1;
|
||||
unsigned int even = (m >> bits) & 1;
|
||||
|
||||
/* if this overflows, we will end up with a normalised number */
|
||||
m = (m + half + even) >> bits;
|
||||
}
|
||||
|
||||
return s | m;
|
||||
}
|
||||
|
||||
/* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */
|
||||
m >>= 13;
|
||||
|
||||
return s | 0x7c00 | m | !m;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/* floating point stuff, can be disabled by defining ECB_NO_LIBM */
|
||||
|
||||
@@ -1207,23 +1341,6 @@ ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_he
|
||||
#define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))
|
||||
#endif
|
||||
|
||||
/* converts an ieee half/binary16 to a float */
|
||||
ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);
|
||||
ecb_function_ ecb_const float
|
||||
ecb_binary16_to_float (uint16_t x)
|
||||
{
|
||||
int e = (x >> 10) & 0x1f;
|
||||
int m = x & 0x3ff;
|
||||
float r;
|
||||
|
||||
if (!e ) r = ecb_ldexpf (m , -24);
|
||||
else if (e != 31) r = ecb_ldexpf (m + 0x400, e - 25);
|
||||
else if (m ) r = ECB_NAN;
|
||||
else r = ECB_INFINITY;
|
||||
|
||||
return x & 0x8000 ? -r : r;
|
||||
}
|
||||
|
||||
/* convert a float to ieee single/binary32 */
|
||||
ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);
|
||||
ecb_function_ ecb_const uint32_t
|
||||
@@ -1364,6 +1481,22 @@ ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_he
|
||||
return r;
|
||||
}
|
||||
|
||||
/* convert a float to ieee half/binary16 */
|
||||
ecb_function_ ecb_const uint16_t ecb_float_to_binary16 (float x);
|
||||
ecb_function_ ecb_const uint16_t
|
||||
ecb_float_to_binary16 (float x)
|
||||
{
|
||||
return ecb_binary32_to_binary16 (ecb_float_to_binary32 (x));
|
||||
}
|
||||
|
||||
/* convert an ieee half/binary16 to float */
|
||||
ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);
|
||||
ecb_function_ ecb_const float
|
||||
ecb_binary16_to_float (uint16_t x)
|
||||
{
|
||||
return ecb_binary32_to_float (ecb_binary16_to_binary32 (x));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -2603,7 +2736,7 @@ ev_recommended_backends (void) EV_THROW
|
||||
{
|
||||
unsigned int flags = ev_supported_backends ();
|
||||
|
||||
#if !defined(__NetBSD__) && !defined(__FreeBSD__)
|
||||
#ifndef __NetBSD__
|
||||
/* kqueue is borked on everything but netbsd apparently */
|
||||
/* it usually doesn't work correctly on anything but sockets and pipes */
|
||||
flags &= ~EVBACKEND_KQUEUE;
|
||||
@@ -2918,7 +3051,7 @@ loop_fork (EV_P)
|
||||
#endif
|
||||
|
||||
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
||||
if (ev_is_active (&pipe_w))
|
||||
if (ev_is_active (&pipe_w) && postfork != 2)
|
||||
{
|
||||
/* pipe_write_wanted must be false now, so modifying fd vars should be safe */
|
||||
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ struct ev_loop;
|
||||
/*****************************************************************************/
|
||||
|
||||
#define EV_VERSION_MAJOR 4
|
||||
#define EV_VERSION_MINOR 20
|
||||
#define EV_VERSION_MINOR 22
|
||||
|
||||
/* eventmask, revents, events... */
|
||||
enum {
|
||||
|
||||
+5
-2
@@ -418,8 +418,8 @@ without a system call and thus I<very> fast, but my GNU/Linux system also has
|
||||
C<pthread_atfork> which is even faster).
|
||||
|
||||
The big advantage of this flag is that you can forget about fork (and
|
||||
forget about forgetting to tell libev about forking) when you use this
|
||||
flag.
|
||||
forget about forgetting to tell libev about forking, although you still
|
||||
have to ignore C<SIGPIPE>) when you use this flag.
|
||||
|
||||
This flag setting cannot be overridden or specified in the C<LIBEV_FLAGS>
|
||||
environment variable.
|
||||
@@ -691,6 +691,9 @@ watchers (except inside an C<ev_prepare> callback), but it makes most
|
||||
sense after forking, in the child process. You I<must> call it (or use
|
||||
C<EVFLAG_FORKCHECK>) in the child before resuming or calling C<ev_run>.
|
||||
|
||||
In addition, if you want to reuse a loop (via this function or
|
||||
C<EVFLAG_FORKCHECK>), you I<also> have to ignore C<SIGPIPE>.
|
||||
|
||||
Again, you I<have> to call it on I<any> loop that you want to re-use after
|
||||
a fork, I<even if you do not plan to use the loop in the parent>. This is
|
||||
because some kernel interfaces *cough* I<kqueue> *cough* do funny things
|
||||
|
||||
+2
-2
@@ -179,7 +179,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
|
||||
if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
|
||||
{
|
||||
/* recreate kernel state */
|
||||
postfork = 1;
|
||||
postfork |= 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
|
||||
/* which is fortunately easy to do for us. */
|
||||
if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))
|
||||
{
|
||||
postfork = 1; /* an error occurred, recreate kernel state */
|
||||
postfork |= 2; /* an error occurred, recreate kernel state */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -39,9 +39,6 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* timeb.h is actually xsi legacy functionality */
|
||||
#include <sys/timeb.h>
|
||||
|
||||
/* note: the comment below could not be substantiated, but what would I care */
|
||||
/* MSDN says this is required to handle SIGFPE */
|
||||
/* my wild guess would be that using something floating-pointy is required */
|
||||
@@ -91,6 +88,8 @@ ev_pipe (int filedes [2])
|
||||
if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
|
||||
goto fail;
|
||||
|
||||
/* TODO: returns INVALID_SOCKET on winsock accept, not < 0. fix it */
|
||||
/* when convenient, probably by just removing error checking altogether? */
|
||||
if ((sock [1] = accept (listener, 0, 0)) < 0)
|
||||
goto fail;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user