added libev files

This commit is contained in:
wangyu- 2018-08-29 02:03:10 -05:00
parent b9d4264225
commit 6718627e9d
37 changed files with 21626 additions and 1 deletions

31
libev/CVS/Entries Normal file
View File

@ -0,0 +1,31 @@
/Changes/1.315/Wed Jun 21 14:42:30 2017//
/LICENSE/1.11/Thu Jan 16 11:51:05 2014//
/Makefile.am/1.9/Wed Dec 21 18:16:08 2011//
/README/1.21/Fri Mar 30 17:43:55 2012//
/README.embed/1.29/Sat Nov 24 10:10:26 2007//
/Symbols.ev/1.14/Tue Jan 11 13:45:28 2011//
/Symbols.event/1.4/Tue May 8 15:52:13 2012//
/autogen.sh/1.3/Mon May 30 15:28:54 2011//
/configure.ac/1.42/Wed Dec 28 04:22:06 2016//
/ev++.h/1.63/Fri Dec 1 06:37:30 2017//
/ev.3/1.107/Wed Jun 21 14:42:30 2017//
/ev.c/1.481/Thu Jun 1 20:25:50 2017//
/ev.h/1.187/Wed Dec 28 04:22:06 2016//
/ev.pod/1.441/Thu Jul 13 10:46:52 2017//
/ev_epoll.c/1.72/Wed Jun 21 14:42:30 2017//
/ev_kqueue.c/1.56/Thu Feb 18 04:48:05 2016//
/ev_poll.c/1.40/Thu Feb 18 04:48:05 2016//
/ev_port.c/1.29/Thu Feb 18 04:48:05 2016//
/ev_select.c/1.56/Thu Feb 18 04:48:05 2016//
/ev_vars.h/1.58/Tue Sep 9 21:51:35 2014//
/ev_win32.c/1.18/Thu Nov 12 07:02:37 2015//
/ev_wrap.h/1.38/Tue Nov 6 20:56:50 2012//
/event.c/1.52/Mon Apr 2 23:14:41 2012//
/event.h/1.26/Mon Apr 2 23:15:27 2012//
/event_compat.h/1.8/Wed Feb 16 08:02:51 2011//
/import_libevent/1.29/Tue Apr 15 04:34:07 2008//
/libev.m4/1.16/Mon Oct 28 12:36:44 2013//
/update_ev_c/1.2/Wed Jan 18 12:13:14 2012//
/update_ev_wrap/1.6/Sun May 6 13:09:29 2012//
/update_symbols/1.1/Wed Dec 19 01:59:29 2007//
D

1
libev/CVS/Repository Normal file
View File

@ -0,0 +1 @@
libev

1
libev/CVS/Root Normal file
View File

@ -0,0 +1 @@
:pserver:anonymous@cvs.schmorp.de/schmorpforge

517
libev/Changes Normal file
View File

@ -0,0 +1,517 @@
Revision history for libev, a high-performance and full-featured event loop.
- ANDROID => __ANDROID__ (reported by enh@google.com).
- disable epoll_create1 on android because it has broken header files
and google is unwilling to fix them (reported by enh@google.com).
4.24 Wed Dec 28 05:19:55 CET 2016
- bump version to 4.24, as the release tarball inexplicably
didn't have the right version in ev.h, even though the cvs-tagged
version did have the right one (reported by Ales Teska).
4.23 Wed Nov 16 18:23:41 CET 2016
- move some declarations at the beginning to help certain retarded
microsoft compilers, even though their documentation claims
otherwise (reported by Ruslan Osmanov).
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.
- fix a potential aliasing issue when reading and writing
watcher callbacks.
4.19 Thu Sep 25 08:18:25 CEST 2014
- ev.h wasn't valid C++ anymore, which tripped compilers other than
clang, msvc or gcc (analyzed by Raphael 'kena' Poss). Unfortunately,
C++ doesn't support typedefs for function pointers fully, so the affected
declarations have to spell out the types each time.
- when not using autoconf, tighten the check for clock_gettime and related
functionality.
4.18 Fri Sep 5 17:55:26 CEST 2014
- events on files were not always generated properly with the
epoll backend (testcase by Assaf Inbal).
- mark event pipe fd as cloexec after a fork (analyzed by Sami Farin).
- (ecb) support m68k, m88k and sh (patch by Miod Vallat).
- use a reasonable fallback for EV_NSIG instead of erroring out
when we can't detect the signal set size.
- in the absence of autoconf, do not use the clock syscall
on glibc >= 2.17 (avoids the syscall AND -lrt on systems
doing clock_gettime in userspace).
- ensure extern "C" function pointers are used for externally-visible
loop callbacks (not watcher callbacks yet).
- (ecb) work around memory barriers and volatile apparently both being
broken in visual studio 2008 and later (analysed and patch by Nicolas Noble).
4.15 Fri Mar 1 12:04:50 CET 2013
- destroying a non-default loop would stop the global waitpid
watcher (Denis Bilenko).
- queueing pending watchers of higher priority from a watcher now invokes
them in a timely fashion (reported by Denis Bilenko).
- add throw() to all libev functions that cannot throw exceptions, for
further code size decrease when compiling for C++.
- add throw () to callbacks that must not throw exceptions (allocator,
syserr, loop acquire/release, periodic reschedule cbs).
- fix event_base_loop return code, add event_get_callback, event_base_new,
event_base_get_method calls to improve libevent 1.x emulation and add
some libevent 2.x functionality (based on a patch by Jeff Davey).
- add more memory fences to fix a bug reported by Jeff Davey. Better
be overfenced than underprotected.
- ev_run now returns a boolean status (true meaning watchers are
still active).
- ev_once: undef EV_ERROR in ev_kqueue.c, to avoid clashing with
libev's EV_ERROR (reported by 191919).
- (ecb) add memory fence support for xlC (Darin McBride).
- (ecb) add memory fence support for gcc-mips (Anton Kirilov).
- (ecb) add memory fence support for gcc-alpha (Christian Weisgerber).
- work around some kernels losing file descriptors by leaking
the kqueue descriptor in the child.
- work around linux inotify not reporting IN_ATTRIB changes for directories
in many cases.
- include sys/syscall.h instead of plain syscall.h.
- check for io watcher loops in ev_verify, check for the most
common reported usage bug in ev_io_start.
- choose socket vs. WSASocket at compiletime using EV_USE_WSASOCKET.
- always use WSASend/WSARecv directly on windows, hoping that this
works in all cases (unlike read/write/send/recv...).
- try to detect signals around a fork faster (test program by
Denis Bilenko).
- work around recent glibc versions that leak memory in realloc.
- rename ev::embed::set to ev::embed::set_embed to avoid clashing
the watcher base set (loop) method.
- rewrite the async/signal pipe logic to always keep a valid fd, which
simplifies (and hopefully correctifies :) the race checking
on fork, at the cost of one extra fd.
- add fat, msdos, jffs2, ramfs, ntfs and btrfs to the list of
inotify-supporting filesystems.
- move orig_CFLAGS assignment to after AC_INIT, as newer autoconf
versions ignore it before
(https://bugzilla.redhat.com/show_bug.cgi?id=908096).
- add some untested android support.
- enum expressions must be of type int (reported by Juan Pablo L).
4.11 Sat Feb 4 19:52:39 CET 2012
- INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as
was documented already, but not implemented in the repeating case.
- new compiletime symbols: EV_NO_SMP and EV_NO_THREADS.
- fix a race where the workaround against the epoll fork bugs
caused signals to not be handled anymore.
- correct backend_fudge for most backends, and implement a windows
specific workaround to avoid looping because we call both
select and Sleep, both with different time resolutions.
- document range and guarantees of ev_sleep.
- document reasonable ranges for periodics interval and offset.
- rename backend_fudge to backend_mintime to avoid future confusion :)
- change the default periodic reschedule function to hopefully be more
exact and correct even in corner cases or in the far future.
- do not rely on -lm anymore: use it when available but use our
own floor () if it is missing. This should make it easier to embed,
as no external libraries are required.
- strategically import macros from libecb and mark rarely-used functions
as cache-cold (saving almost 2k code size on typical amd64 setups).
- add Symbols.ev and Symbols.event files, that were missing.
- fix backend_mintime value for epoll (was 1/1024, is 1/1000 now).
- fix #3 "be smart about timeouts" to not "deadlock" when
timeout == now, also improve the section overall.
- avoid "AVOIDING FINISHING BEFORE RETURNING" idiom.
- support new EV_API_STATIC mode to make all libev symbols
static.
- supply default CFLAGS of -g -O3 with gcc when original CFLAGS
were empty.
4.04 Wed Feb 16 09:01:51 CET 2011
- fix two problems in the native win32 backend, where reuse of fd's
with different underlying handles caused handles not to be removed
or added to the select set (analyzed and tested by Bert Belder).
- do no rely on ceil() in ev_e?poll.c.
- backport libev to HP-UX versions before 11 v3.
- configure did not detect nanosleep and clock_gettime properly when
they are available in the libc (as opposed to -lrt).
4.03 Tue Jan 11 14:37:25 CET 2011
- officially support polling files with all backends.
- support files, /dev/zero etc. the same way as select in the epoll
backend, by generating events on our own.
- ports backend: work around solaris bug 6874410 and many related ones
(EINTR, maybe more), with no performance loss (note that the solaris
bug report is actually wrong, reality is far more bizarre and broken
than that).
- define EV_READ/EV_WRITE as macros in event.h, as some programs use
#ifdef to test for them.
- new (experimental) function: ev_feed_signal.
- new (to become default) EVFLAG_NOSIGMASK flag.
- new EVBACKEND_MASK symbol.
- updated COMMON IDIOMS SECTION.
4.01 Fri Nov 5 21:51:29 CET 2010
- automake fucked it up, apparently, --add-missing -f is not quite enough
to make it update its files, so 4.00 didn't install ev++.h and
event.h on make install. grrr.
- ev_loop(count|depth) didn't return anything (Robin Haberkorn).
- change EV_UNDEF to 0xffffffff to silence some overzealous compilers.
- use "(libev) " prefix for all libev error messages now.
4.00 Mon Oct 25 12:32:12 CEST 2010
- "PORTING FROM LIBEV 3.X TO 4.X" (in ev.pod) is recommended reading.
- ev_embed_stop did not correctly stop the watcher (very good
testcase by Vladimir Timofeev).
- ev_run will now always update the current loop time - it erroneously
didn't when idle watchers were active, causing timers not to fire.
- fix a bug where a timeout of zero caused the timer not to fire
in the libevent emulation (testcase by Péter Szabó).
- applied win32 fixes by Michael Lenaghan (also James Mansion).
- replace EV_MINIMAL by EV_FEATURES.
- prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it
seems the former is *much* faster than the latter.
- linux kernel version detection (for inotify bug workarounds)
did not work properly.
- reduce the number of spurious wake-ups with the ports backend.
- remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu).
- do async init within ev_async_start, not ev_async_set, which avoids
an API quirk where the set function must be called in the C++ API
even when there is nothing to set.
- add (undocumented) EV_ENABLE when adding events with kqueue,
this might help with OS X, which seems to need it despite documenting
not to need it (helpfully pointed out by Tilghman Lesher).
- do not use poll by default on freebsd, it's broken (what isn't
on freebsd...).
- allow to embed epoll on kernels >= 2.6.32.
- configure now prepends -O3, not appends it, so one can still
override it.
- ev.pod: greatly expanded the portability section, added a porting
section, a description of watcher states and made lots of minor fixes.
- disable poll backend on AIX, the poll header spams the namespace
and it's not worth working around dead platforms (reported
and analyzed by Aivars Kalvans).
- improve header file compatibility of the standalone eventfd code
in an obscure case.
- implement EV_AVOID_STDIO option.
- do not use sscanf to parse linux version number (smaller, faster,
no sscanf dependency).
- new EV_CHILD_ENABLE and EV_SIGNAL_ENABLE configurable settings.
- update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs.
- add section on accept() problems to the manpage.
- rename EV_TIMEOUT to EV_TIMER.
- rename ev_loop_count/depth/verify/loop/unloop.
- remove ev_default_destroy and ev_default_fork.
- switch to two-digit minor version.
- work around an apparent gentoo compiler bug.
- define _DARWIN_UNLIMITED_SELECT. just so.
- use enum instead of #define for most constants.
- improve compatibility to older C++ compilers.
- (experimental) ev_run/ev_default_loop/ev_break/ev_loop_new have now
default arguments when compiled as C++.
- enable automake dependency tracking.
- ev_loop_new no longer leaks memory when loop creation failed.
- new ev_cleanup watcher type.
3.9 Thu Dec 31 07:59:59 CET 2009
- signalfd is no longer used by default and has to be requested
explicitly - this means that easy to catch bugs become hard to
catch race conditions, but the users have spoken.
- point out the unspecified signal mask in the documentation, and
that this is a race condition regardless of EV_SIGNALFD.
- backport inotify code to C89.
- inotify file descriptors could leak into child processes.
- ev_stat watchers could keep an erroneous extra ref on the loop,
preventing exit when unregistering all watchers (testcases
provided by ry@tinyclouds.org).
- implement EV_WIN32_HANDLE_TO_FD and EV_WIN32_CLOSE_FD configuration
symbols to make it easier for apps to do their own fd management.
- support EV_IDLE_ENABLE being disabled in ev++.h
(patch by Didier Spezia).
- take advantage of inotify_init1, if available, to set cloexec/nonblock
on fd creation, to avoid races.
- the signal handling pipe wasn't always initialised under windows
(analysed by lekma).
- changed minimum glibc requirement from glibc 2.9 to 2.7, for
signalfd.
- add missing string.h include (Denis F. Latypoff).
- only replace ev_stat.prev when we detect an actual difference,
so prev is (almost) always different to attr. this might
have caused the problems with 04_stat.t.
- add ev::timer->remaining () method to C++ API.
3.8 Sun Aug 9 14:30:45 CEST 2009
- incompatible change: do not necessarily reset signal handler
to SIG_DFL when a sighandler is stopped.
- ev_default_destroy did not properly free or zero some members,
potentially causing crashes and memory corruption on repeated
ev_default_destroy/ev_default_loop calls.
- take advantage of signalfd on GNU/Linux systems.
- document that the signal mask might be in an unspecified
state when using libev's signal handling.
- take advantage of some GNU/Linux calls to set cloexec/nonblock
on fd creation, to avoid race conditions.
3.7 Fri Jul 17 16:36:32 CEST 2009
- ev_unloop and ev_loop wrongly used a global variable to exit loops,
instead of using a per-loop variable (bug caught by accident...).
- the ev_set_io_collect_interval interpretation has changed.
- add new functionality: ev_set_userdata, ev_userdata,
ev_set_invoke_pending_cb, ev_set_loop_release_cb,
ev_invoke_pending, ev_pending_count, together with a long example
about thread locking.
- add ev_timer_remaining (as requested by Denis F. Latypoff).
- add ev_loop_depth.
- calling ev_unloop in fork/prepare watchers will no longer poll
for new events.
- Denis F. Latypoff corrected many typos in example code snippets.
- honor autoconf detection of EV_USE_CLOCK_SYSCALL, also double-
check that the syscall number is available before trying to
use it (reported by ry@tinyclouds).
- use GetSystemTimeAsFileTime instead of _timeb on windows, for
slightly higher accuracy.
- properly declare ev_loop_verify and ev_now_update even when
!EV_MULTIPLICITY.
- do not compile in any priority code when EV_MAXPRI == EV_MINPRI.
- support EV_MINIMAL==2 for a reduced API.
- actually 0-initialise struct sigaction when installing signals.
- add section on hibernate and stopped processes to ev_timer docs.
3.6 Tue Apr 28 02:49:30 CEST 2009
- multiple timers becoming ready within an event loop iteration
will be invoked in the "correct" order now.
- do not leave the event loop early just because we have no active
watchers, fixing a problem when embedding a kqueue loop
that has active kernel events but no registered watchers
(reported by blacksand blacksand).
- correctly zero the idx values for arrays, so destroying and
reinitialising the default loop actually works (patch by
Malek Hadj-Ali).
- implement ev_suspend and ev_resume.
- new EV_CUSTOM revents flag for use by applications.
- add documentation section about priorities.
- add a glossary to the documentation.
- extend the ev_fork description slightly.
- optimize a jump out of call_pending.
3.53 Sun Feb 15 02:38:20 CET 2009
- fix a bug in event pipe creation on win32 that would cause a
failed assertion on event loop creation (patch by Malek Hadj-Ali).
- probe for CLOCK_REALTIME support at runtime as well and fall
back to gettimeofday if there is an error, to support older
operating systems with newer header files/libraries.
- prefer gettimeofday over clock_gettime with USE_CLOCK_SYSCALL
(default most everywhere), otherwise not.
3.52 Wed Jan 7 21:43:02 CET 2009
- fix compilation of select backend in fd_set mode when NFDBITS is
missing (to get it to compile on QNX, reported by Rodrigo Campos).
- better select-nfds handling when select backend is in fd_set mode.
- diagnose fd_set overruns when select backend is in fd_set mode.
- due to a thinko, instead of disabling everything but
select on the borked OS X platform, everything but select was
allowed (reported by Emanuele Giaquinta).
- actually verify that local and remote port are matching in
libev's socketpair emulation, which makes denial-of-service
attacks harder (but not impossible - it's windows). Make sure
it even works under vista, which thinks that getpeer/sockname
should return fantasy port numbers.
- include "libev" in all assertion messages for potentially
clearer diagnostics.
- event_get_version (libevent compatibility) returned
a useless string instead of the expected version string
(patch by W.C.A. Wijngaards).
3.51 Wed Dec 24 23:00:11 CET 2008
- fix a bug where an inotify watcher was added twice, causing
freezes on hash collisions (reported and analysed by Graham Leggett).
- new config symbol, EV_USE_CLOCK_SYSCALL, to make libev use
a direct syscall - slower, but no dependency on librt et al.
- assume negative return values != -1 signals success of port_getn
(http://cvs.epicsol.org/cgi/viewcvs.cgi/epic5/source/newio.c?rev=1.52)
(no known failure reports, but it doesn't hurt).
- fork detection in ev_embed now stops and restarts the watcher
automatically.
- EXPERIMENTAL: default the method to operator () in ev++.h,
to make it nicer to use functors (requested by Benedek László).
- fixed const object callbacks in ev++.h.
- replaced loop_ref argument of watcher.set (loop) by a direct
ev_loop * in ev++.h, to avoid clashes with functor patch.
- do not try to watch the empty string via inotify.
- inotify watchers could be leaked under certain circumstances.
- OS X 10.5 is actually even more broken than earlier versions,
so fall back to select on that piece of garbage.
- fixed some weirdness in the ev_embed documentation.
3.49 Wed Nov 19 11:26:53 CET 2008
- ev_stat watchers will now use inotify as a mere hint on
kernels <2.6.25, or if the filesystem is not in the
"known to be good" list.
- better mingw32 compatibility (it's not as borked as native win32)
(analysed by Roger Pack).
- include stdio.h in the example program, as too many people are
confused by the weird C language otherwise. I guess the next thing
I get told is that the "..." ellipses in the examples don't compile
with their C compiler.
3.48 Thu Oct 30 09:02:37 CET 2008
- further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll
backend by assuming the kernel event mask hasn't changed if
ADD fails with EEXIST.
- work around spurious event notification bugs in epoll by using
a 32-bit generation counter. recreate kernel state if we receive
spurious notifications or unwanted events. this is very costly,
but I didn't come up with this horrible design.
- use memset to initialise most arrays now and do away with the
init functions.
- expand time-out strategies into a "Be smart about timeouts" section.
- drop the "struct" from all ev_watcher declarations in the
documentation and did other clarifications (yeah, it was a mistake
to have a struct AND a function called ev_loop).
- fix a bug where ev_default would not initialise the default
loop again after it was destroyed with ev_default_destroy.
- rename syserr to ev_syserr to avoid name clashes when embedding,
do similar changes for event.c.
3.45 Tue Oct 21 21:59:26 CEST 2008
- disable inotify usage on linux <2.6.25, as it is broken
(reported by Yoann Vandoorselaere).
- ev_stat erroneously would try to add inotify watchers
even when inotify wasn't available (this should only
have a performance impact).
- ev_once now passes both timeout and io to the callback if both
occur concurrently, instead of giving timeouts precedence.
- disable EV_USE_INOTIFY when sys/inotify.h is too old.
3.44 Mon Sep 29 05:18:39 CEST 2008
- embed watchers now automatically invoke ev_loop_fork on the
embedded loop when the parent loop forks.
- new function: ev_now_update (loop).
- verify_watcher was not marked static.
- improve the "associating..." manpage section.
- documentation tweaks here and there.
3.43 Sun Jul 6 05:34:41 CEST 2008
- include more include files on windows to get struct _stati64
(reported by Chris Hulbert, but doesn't quite fix his issue).
- add missing #include <io.h> in ev.c on windows (reported by
Matt Tolton).
3.42 Tue Jun 17 12:12:07 CEST 2008
- work around yet another windows bug: FD_SET actually adds fd's
multiple times to the fd_*SET*, despite official MSN docs claiming
otherwise. Reported and well-analysed by Matt Tolton.
- define NFDBITS to 0 when EV_SELECT_IS_WINSOCKET to make it compile
(reported any analysed by Chris Hulbert).
- fix a bug in ev_ebadf (this function is only used to catch
programming errors in the libev user). reported by Matt Tolton.
- fix a bug in fd_intern on win32 (could lead to compile errors
under some circumstances, but would work correctly if it compiles).
reported by Matt Tolton.
- (try to) work around missing lstat on windows.
- pass in the write fd set as except fd set under windows. windows
is so uncontrollably lame that it requires this. this means that
switching off oobinline is not supported (but tcp/ip doesn't
have oob, so that would be stupid anyways.
- use posix module symbol to auto-detect monotonic clock presence
and some other default values.
3.41 Fri May 23 18:42:54 CEST 2008
- work around an obscure bug in winsocket select: if you
provide only empty fd sets then select returns WSAEINVAL. how sucky.
- improve timer scheduling stability and reduce use of time_epsilon.
- use 1-based 2-heap for EV_MINIMAL, simplifies code, reduces
codesize and makes for better cache-efficiency.
- use 3-based 4-heap for !EV_MINIMAL. this makes better use
of cpu cache lines and gives better growth behaviour than
2-based heaps.
- cache timestamp within heap for !EV_MINIMAL, to avoid random
memory accesses.
- document/add EV_USE_4HEAP and EV_HEAP_CACHE_AT.
- fix a potential aliasing issue in ev_timer_again.
- add/document ev_periodic_at, retract direct access to ->at.
- improve ev_stat docs.
- add portability requirements section.
- fix manpage headers etc.
- normalise WSA error codes to lower range on windows.
- add consistency check code that can be called automatically
or on demand to check for internal structures (ev_loop_verify).
3.31 Wed Apr 16 20:45:04 CEST 2008
- added last minute fix for ev_poll.c by Brandon Black.
3.3 Wed Apr 16 19:04:10 CEST 2008
- event_base_loopexit should return 0 on success
(W.C.A. Wijngaards).
- added linux eventfd support.
- try to autodetect epoll and inotify support
by libc header version if not using autoconf.
- new symbols: EV_DEFAULT_UC and EV_DEFAULT_UC_.
- declare functions defined in ev.h as inline if
C99 or gcc are available.
- enable inlining with gcc versions 2 and 3.
- work around broken poll implementations potentially
not clearing revents field in ev_poll (Brandon Black)
(no such systems are known at this time).
- work around a bug in realloc on openbsd and darwin,
also makes the erroneous valgrind complaints
go away (noted by various people).
- fix ev_async_pending, add c++ wrapper for ev_async
(based on patch sent by Johannes Deisenhofer).
- add sensible set method to ev::embed.
- made integer constants type int in ev.h.
3.2 Wed Apr 2 17:11:19 CEST 2008
- fix a 64 bit overflow issue in the select backend,
by using fd_mask instead of int for the mask.
- rename internal sighandler to avoid clash with very old perls.
- entering ev_loop will not clear the ONESHOT or NONBLOCKING
flags of any outer loops anymore.
- add ev_async_pending.
3.1 Thu Mar 13 13:45:22 CET 2008
- implement ev_async watchers.
- only initialise signal pipe on demand.
- make use of sig_atomic_t configurable.
- improved documentation.
3.0 Mon Jan 28 13:14:47 CET 2008
- API/ABI bump to version 3.0.
- ev++.h includes "ev.h" by default now, not <ev.h>.
- slightly improved documentation.
- speed up signal detection after a fork.
- only optionally return trace status changed in ev_child
watchers.
- experimental (and undocumented) loop wrappers for ev++.h.
2.01 Tue Dec 25 08:04:41 CET 2007
- separate Changes file.
- fix ev_path_set => ev_stat_set typo.
- remove event_compat.h from the libev tarball.
- change how include files are found.
- doc updates.
- update licenses, explicitly allow for GPL relicensing.
2.0 Sat Dec 22 17:47:03 CET 2007
- new ev_sleep, ev_set_(io|timeout)_collect_interval.
- removed epoll from embeddable fd set.
- fix embed watchers.
- renamed ev_embed.loop to other.
- added exported Symbol tables.
- undefine member wrapper macros at the end of ev.c.
- respect EV_H in ev++.h.
1.86 Tue Dec 18 02:36:57 CET 2007
- fix memleak on loop destroy (not relevant for perl).
1.85 Fri Dec 14 20:32:40 CET 2007
- fix some aliasing issues w.r.t. timers and periodics
(not relevant for perl).
(for historic versions refer to EV/Changes, found in the Perl interface)
0.1 Wed Oct 31 21:31:48 CET 2007
- original version; hacked together in <24h.

37
libev/LICENSE Normal file
View File

@ -0,0 +1,37 @@
All files in libev are
Copyright (c)2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Alternatively, the contents of this package may be used under the terms
of the GNU General Public License ("GPL") version 2 or any later version,
in which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this package only
under the terms of the GPL and not to allow others to use your version of
this file under the BSD license, indicate your decision by deleting the
provisions above and replace them with the notice and other provisions
required by the GPL in this and the other files of this package. If you do
not delete the provisions above, a recipient may use your version of this
file under either the BSD or the GPL.

20
libev/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
AUTOMAKE_OPTIONS = foreign
VERSION_INFO = 4:0:0
EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \
ev_vars.h ev_wrap.h \
ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c \
ev.3 ev.pod Symbols.ev Symbols.event
man_MANS = ev.3
include_HEADERS = ev.h ev++.h event.h
lib_LTLIBRARIES = libev.la
libev_la_SOURCES = ev.c event.c
libev_la_LDFLAGS = -version-info $(VERSION_INFO)
ev.3: ev.pod
pod2man -n LIBEV -r "libev-$(VERSION)" -c "libev - high performance full featured event loop" -s3 <$< >$@

58
libev/README Normal file
View File

@ -0,0 +1,58 @@
libev is a high-performance event loop/event model with lots of features.
(see benchmark at http://libev.schmorp.de/bench.html)
ABOUT
Homepage: http://software.schmorp.de/pkg/libev
Mailinglist: libev@lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
Libev is modelled (very losely) after libevent and the Event perl
module, but is faster, scales better and is more correct, and also more
featureful. And also smaller. Yay.
Some of the specialties of libev not commonly found elsewhere are:
- extensive and detailed, readable documentation (not doxygen garbage).
- fully supports fork, can detect fork in various ways and automatically
re-arms kernel mechanisms that do not support fork.
- highly optimised select, poll, epoll, kqueue and event ports backends.
- filesystem object (path) watching (with optional linux inotify support).
- wallclock-based times (using absolute time, cron-like).
- relative timers/timeouts (handle time jumps).
- fast intra-thread communication between multiple
event loops (with optional fast linux eventfd backend).
- extremely easy to embed (fully documented, no dependencies,
autoconf supported but optional).
- very small codebase, no bloated library, simple code.
- fully extensible by being able to plug into the event loop,
integrate other event loops, integrate other event loop users.
- very little memory use (small watchers, small event loop data).
- optional C++ interface allowing method and function callbacks
at no extra memory or runtime overhead.
- optional Perl interface with similar characteristics (capable
of running Glib/Gtk2 on libev).
- support for other languages (multiple C++ interfaces, D, Ruby,
Python) available from third-parties.
Examples of programs that embed libev: the EV perl module, node.js,
auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the
Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a
next-generation Ruby VM), the Ebb web server, the Rev event toolkit.
CONTRIBUTORS
libev was written and designed by Marc Lehmann and Emanuele Giaquinta.
The following people sent in patches or made other noteworthy
contributions to the design (for minor patches, see the Changes
file. If I forgot to include you, please shout at me, it was an
accident):
W.C.A. Wijngaards
Christopher Layne
Chris Brody

3
libev/README.embed Normal file
View File

@ -0,0 +1,3 @@
This file is now included in the main libev documentation, see
http://cvs.schmorp.de/libev/ev.html

73
libev/Symbols.ev Normal file
View File

@ -0,0 +1,73 @@
ev_async_send
ev_async_start
ev_async_stop
ev_backend
ev_break
ev_check_start
ev_check_stop
ev_child_start
ev_child_stop
ev_cleanup_start
ev_cleanup_stop
ev_clear_pending
ev_default_loop
ev_default_loop_ptr
ev_depth
ev_embed_start
ev_embed_stop
ev_embed_sweep
ev_embeddable_backends
ev_feed_event
ev_feed_fd_event
ev_feed_signal
ev_feed_signal_event
ev_fork_start
ev_fork_stop
ev_idle_start
ev_idle_stop
ev_invoke
ev_invoke_pending
ev_io_start
ev_io_stop
ev_iteration
ev_loop_destroy
ev_loop_fork
ev_loop_new
ev_now
ev_now_update
ev_once
ev_pending_count
ev_periodic_again
ev_periodic_start
ev_periodic_stop
ev_prepare_start
ev_prepare_stop
ev_recommended_backends
ev_ref
ev_resume
ev_run
ev_set_allocator
ev_set_invoke_pending_cb
ev_set_io_collect_interval
ev_set_loop_release_cb
ev_set_syserr_cb
ev_set_timeout_collect_interval
ev_set_userdata
ev_signal_start
ev_signal_stop
ev_sleep
ev_stat_start
ev_stat_stat
ev_stat_stop
ev_supported_backends
ev_suspend
ev_time
ev_timer_again
ev_timer_remaining
ev_timer_start
ev_timer_stop
ev_unref
ev_userdata
ev_verify
ev_version_major
ev_version_minor

24
libev/Symbols.event Normal file
View File

@ -0,0 +1,24 @@
event_active
event_add
event_base_dispatch
event_base_free
event_base_get_method
event_base_loop
event_base_loopexit
event_base_new
event_base_once
event_base_priority_init
event_base_set
event_del
event_dispatch
event_get_callback
event_get_method
event_get_version
event_init
event_loop
event_loopexit
event_once
event_pending
event_priority_init
event_priority_set
event_set

3
libev/autogen.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/sh
autoreconf --install --symlink --force

27
libev/configure.ac Normal file
View File

@ -0,0 +1,27 @@
AC_INIT
orig_CFLAGS="$CFLAGS"
AC_CONFIG_SRCDIR([ev_epoll.c])
dnl also update ev.h!
AM_INIT_AUTOMAKE(libev,4.24)
AC_CONFIG_HEADERS([config.h])
AM_MAINTAINER_MODE
AC_PROG_CC
dnl Supply default CFLAGS, if not specified
if test -z "$orig_CFLAGS"; then
if test x$GCC = xyes; then
CFLAGS="-g -O3"
fi
fi
AC_PROG_INSTALL
AC_PROG_LIBTOOL
m4_include([libev.m4])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

816
libev/ev++.h Normal file
View File

@ -0,0 +1,816 @@
/*
* libev simple C++ wrapper classes
*
* Copyright (c) 2007,2008,2010 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef EVPP_H__
#define EVPP_H__
#ifdef EV_H
# include EV_H
#else
# include "ev.h"
#endif
#ifndef EV_USE_STDEXCEPT
# define EV_USE_STDEXCEPT 1
#endif
#if EV_USE_STDEXCEPT
# include <stdexcept>
#endif
namespace ev {
typedef ev_tstamp tstamp;
enum {
UNDEF = EV_UNDEF,
NONE = EV_NONE,
READ = EV_READ,
WRITE = EV_WRITE,
#if EV_COMPAT3
TIMEOUT = EV_TIMEOUT,
#endif
TIMER = EV_TIMER,
PERIODIC = EV_PERIODIC,
SIGNAL = EV_SIGNAL,
CHILD = EV_CHILD,
STAT = EV_STAT,
IDLE = EV_IDLE,
CHECK = EV_CHECK,
PREPARE = EV_PREPARE,
FORK = EV_FORK,
ASYNC = EV_ASYNC,
EMBED = EV_EMBED,
# undef ERROR // some systems stupidly #define ERROR
ERROR = EV_ERROR
};
enum
{
AUTO = EVFLAG_AUTO,
NOENV = EVFLAG_NOENV,
FORKCHECK = EVFLAG_FORKCHECK,
SELECT = EVBACKEND_SELECT,
POLL = EVBACKEND_POLL,
EPOLL = EVBACKEND_EPOLL,
KQUEUE = EVBACKEND_KQUEUE,
DEVPOLL = EVBACKEND_DEVPOLL,
PORT = EVBACKEND_PORT
};
enum
{
#if EV_COMPAT3
NONBLOCK = EVLOOP_NONBLOCK,
ONESHOT = EVLOOP_ONESHOT,
#endif
NOWAIT = EVRUN_NOWAIT,
ONCE = EVRUN_ONCE
};
enum how_t
{
ONE = EVBREAK_ONE,
ALL = EVBREAK_ALL
};
struct bad_loop
#if EV_USE_STDEXCEPT
: std::runtime_error
#endif
{
#if EV_USE_STDEXCEPT
bad_loop ()
: std::runtime_error ("libev event loop cannot be initialized, bad value of LIBEV_FLAGS?")
{
}
#endif
};
#ifdef EV_AX
# undef EV_AX
#endif
#ifdef EV_AX_
# undef EV_AX_
#endif
#if EV_MULTIPLICITY
# define EV_AX raw_loop
# define EV_AX_ raw_loop,
#else
# define EV_AX
# define EV_AX_
#endif
struct loop_ref
{
loop_ref (EV_P) throw ()
#if EV_MULTIPLICITY
: EV_AX (EV_A)
#endif
{
}
bool operator == (const loop_ref &other) const throw ()
{
#if EV_MULTIPLICITY
return EV_AX == other.EV_AX;
#else
return true;
#endif
}
bool operator != (const loop_ref &other) const throw ()
{
#if EV_MULTIPLICITY
return ! (*this == other);
#else
return false;
#endif
}
#if EV_MULTIPLICITY
bool operator == (const EV_P) const throw ()
{
return this->EV_AX == EV_A;
}
bool operator != (const EV_P) const throw ()
{
return ! (*this == EV_A);
}
operator struct ev_loop * () const throw ()
{
return EV_AX;
}
operator const struct ev_loop * () const throw ()
{
return EV_AX;
}
bool is_default () const throw ()
{
return EV_AX == ev_default_loop (0);
}
#endif
#if EV_COMPAT3
void loop (int flags = 0)
{
ev_run (EV_AX_ flags);
}
void unloop (how_t how = ONE) throw ()
{
ev_break (EV_AX_ how);
}
#endif
void run (int flags = 0)
{
ev_run (EV_AX_ flags);
}
void break_loop (how_t how = ONE) throw ()
{
ev_break (EV_AX_ how);
}
void post_fork () throw ()
{
ev_loop_fork (EV_AX);
}
unsigned int backend () const throw ()
{
return ev_backend (EV_AX);
}
tstamp now () const throw ()
{
return ev_now (EV_AX);
}
void ref () throw ()
{
ev_ref (EV_AX);
}
void unref () throw ()
{
ev_unref (EV_AX);
}
#if EV_FEATURE_API
unsigned int iteration () const throw ()
{
return ev_iteration (EV_AX);
}
unsigned int depth () const throw ()
{
return ev_depth (EV_AX);
}
void set_io_collect_interval (tstamp interval) throw ()
{
ev_set_io_collect_interval (EV_AX_ interval);
}
void set_timeout_collect_interval (tstamp interval) throw ()
{
ev_set_timeout_collect_interval (EV_AX_ interval);
}
#endif
// function callback
void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw ()
{
ev_once (EV_AX_ fd, events, timeout, cb, arg);
}
// method callback
template<class K, void (K::*method)(int)>
void once (int fd, int events, tstamp timeout, K *object) throw ()
{
once (fd, events, timeout, method_thunk<K, method>, object);
}
// default method == operator ()
template<class K>
void once (int fd, int events, tstamp timeout, K *object) throw ()
{
once (fd, events, timeout, method_thunk<K, &K::operator ()>, object);
}
template<class K, void (K::*method)(int)>
static void method_thunk (int revents, void *arg)
{
(static_cast<K *>(arg)->*method)
(revents);
}
// no-argument method callback
template<class K, void (K::*method)()>
void once (int fd, int events, tstamp timeout, K *object) throw ()
{
once (fd, events, timeout, method_noargs_thunk<K, method>, object);
}
template<class K, void (K::*method)()>
static void method_noargs_thunk (int revents, void *arg)
{
(static_cast<K *>(arg)->*method)
();
}
// simpler function callback
template<void (*cb)(int)>
void once (int fd, int events, tstamp timeout) throw ()
{
once (fd, events, timeout, simpler_func_thunk<cb>);
}
template<void (*cb)(int)>
static void simpler_func_thunk (int revents, void *arg)
{
(*cb)
(revents);
}
// simplest function callback
template<void (*cb)()>
void once (int fd, int events, tstamp timeout) throw ()
{
once (fd, events, timeout, simplest_func_thunk<cb>);
}
template<void (*cb)()>
static void simplest_func_thunk (int revents, void *arg)
{
(*cb)
();
}
void feed_fd_event (int fd, int revents) throw ()
{
ev_feed_fd_event (EV_AX_ fd, revents);
}
void feed_signal_event (int signum) throw ()
{
ev_feed_signal_event (EV_AX_ signum);
}
#if EV_MULTIPLICITY
struct ev_loop* EV_AX;
#endif
};
#if EV_MULTIPLICITY
struct dynamic_loop : loop_ref
{
dynamic_loop (unsigned int flags = AUTO) throw (bad_loop)
: loop_ref (ev_loop_new (flags))
{
if (!EV_AX)
throw bad_loop ();
}
~dynamic_loop () throw ()
{
ev_loop_destroy (EV_AX);
EV_AX = 0;
}
private:
dynamic_loop (const dynamic_loop &);
dynamic_loop & operator= (const dynamic_loop &);
};
#endif
struct default_loop : loop_ref
{
default_loop (unsigned int flags = AUTO) throw (bad_loop)
#if EV_MULTIPLICITY
: loop_ref (ev_default_loop (flags))
#endif
{
if (
#if EV_MULTIPLICITY
!EV_AX
#else
!ev_default_loop (flags)
#endif
)
throw bad_loop ();
}
private:
default_loop (const default_loop &);
default_loop &operator = (const default_loop &);
};
inline loop_ref get_default_loop () throw ()
{
#if EV_MULTIPLICITY
return ev_default_loop (0);
#else
return loop_ref ();
#endif
}
#undef EV_AX
#undef EV_AX_
#undef EV_PX
#undef EV_PX_
#if EV_MULTIPLICITY
# define EV_PX loop_ref EV_A
# define EV_PX_ loop_ref EV_A_
#else
# define EV_PX
# define EV_PX_
#endif
template<class ev_watcher, class watcher>
struct base : ev_watcher
{
#if EV_MULTIPLICITY
EV_PX;
// loop set
void set (EV_P) throw ()
{
this->EV_A = EV_A;
}
#endif
base (EV_PX) throw ()
#if EV_MULTIPLICITY
: EV_A (EV_A)
#endif
{
ev_init (this, 0);
}
void set_ (const void *data, void (*cb)(EV_P_ ev_watcher *w, int revents)) throw ()
{
this->data = (void *)data;
ev_set_cb (static_cast<ev_watcher *>(this), cb);
}
// function callback
template<void (*function)(watcher &w, int)>
void set (void *data = 0) throw ()
{
set_ (data, function_thunk<function>);
}
template<void (*function)(watcher &w, int)>
static void function_thunk (EV_P_ ev_watcher *w, int revents)
{
function
(*static_cast<watcher *>(w), revents);
}
// method callback
template<class K, void (K::*method)(watcher &w, int)>
void set (K *object) throw ()
{
set_ (object, method_thunk<K, method>);
}
// default method == operator ()
template<class K>
void set (K *object) throw ()
{
set_ (object, method_thunk<K, &K::operator ()>);
}
template<class K, void (K::*method)(watcher &w, int)>
static void method_thunk (EV_P_ ev_watcher *w, int revents)
{
(static_cast<K *>(w->data)->*method)
(*static_cast<watcher *>(w), revents);
}
// no-argument callback
template<class K, void (K::*method)()>
void set (K *object) throw ()
{
set_ (object, method_noargs_thunk<K, method>);
}
template<class K, void (K::*method)()>
static void method_noargs_thunk (EV_P_ ev_watcher *w, int revents)
{
(static_cast<K *>(w->data)->*method)
();
}
void operator ()(int events = EV_UNDEF)
{
return
ev_cb (static_cast<ev_watcher *>(this))
(static_cast<ev_watcher *>(this), events);
}
bool is_active () const throw ()
{
return ev_is_active (static_cast<const ev_watcher *>(this));
}
bool is_pending () const throw ()
{
return ev_is_pending (static_cast<const ev_watcher *>(this));
}
void feed_event (int revents) throw ()
{
ev_feed_event (EV_A_ static_cast<ev_watcher *>(this), revents);
}
};
inline tstamp now (EV_P) throw ()
{
return ev_now (EV_A);
}
inline void delay (tstamp interval) throw ()
{
ev_sleep (interval);
}
inline int version_major () throw ()
{
return ev_version_major ();
}
inline int version_minor () throw ()
{
return ev_version_minor ();
}
inline unsigned int supported_backends () throw ()
{
return ev_supported_backends ();
}
inline unsigned int recommended_backends () throw ()
{
return ev_recommended_backends ();
}
inline unsigned int embeddable_backends () throw ()
{
return ev_embeddable_backends ();
}
inline void set_allocator (void *(*cb)(void *ptr, long size) throw ()) throw ()
{
ev_set_allocator (cb);
}
inline void set_syserr_cb (void (*cb)(const char *msg) throw ()) throw ()
{
ev_set_syserr_cb (cb);
}
#if EV_MULTIPLICITY
#define EV_CONSTRUCT(cppstem,cstem) \
(EV_PX = get_default_loop ()) throw () \
: base<ev_ ## cstem, cppstem> (EV_A) \
{ \
}
#else
#define EV_CONSTRUCT(cppstem,cstem) \
() throw () \
{ \
}
#endif
/* using a template here would require quite a few more lines,
* so a macro solution was chosen */
#define EV_BEGIN_WATCHER(cppstem,cstem) \
\
struct cppstem : base<ev_ ## cstem, cppstem> \
{ \
void start () throw () \
{ \
ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this)); \
} \
\
void stop () throw () \
{ \
ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this)); \
} \
\
cppstem EV_CONSTRUCT(cppstem,cstem) \
\
~cppstem () throw () \
{ \
stop (); \
} \
\
using base<ev_ ## cstem, cppstem>::set; \
\
private: \
\
cppstem (const cppstem &o); \
\
cppstem &operator =(const cppstem &o); \
\
public:
#define EV_END_WATCHER(cppstem,cstem) \
};
EV_BEGIN_WATCHER (io, io)
void set (int fd, int events) throw ()
{
int active = is_active ();
if (active) stop ();
ev_io_set (static_cast<ev_io *>(this), fd, events);
if (active) start ();
}
void set (int events) throw ()
{
int active = is_active ();
if (active) stop ();
ev_io_set (static_cast<ev_io *>(this), fd, events);
if (active) start ();
}
void start (int fd, int events) throw ()
{
set (fd, events);
start ();
}
EV_END_WATCHER (io, io)
EV_BEGIN_WATCHER (timer, timer)
void set (ev_tstamp after, ev_tstamp repeat = 0.) throw ()
{
int active = is_active ();
if (active) stop ();
ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
if (active) start ();
}
void start (ev_tstamp after, ev_tstamp repeat = 0.) throw ()
{
set (after, repeat);
start ();
}
void again () throw ()
{
ev_timer_again (EV_A_ static_cast<ev_timer *>(this));
}
ev_tstamp remaining ()
{
return ev_timer_remaining (EV_A_ static_cast<ev_timer *>(this));
}
EV_END_WATCHER (timer, timer)
#if EV_PERIODIC_ENABLE
EV_BEGIN_WATCHER (periodic, periodic)
void set (ev_tstamp at, ev_tstamp interval = 0.) throw ()
{
int active = is_active ();
if (active) stop ();
ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
if (active) start ();
}
void start (ev_tstamp at, ev_tstamp interval = 0.) throw ()
{
set (at, interval);
start ();
}
void again () throw ()
{
ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));
}
EV_END_WATCHER (periodic, periodic)
#endif
#if EV_SIGNAL_ENABLE
EV_BEGIN_WATCHER (sig, signal)
void set (int signum) throw ()
{
int active = is_active ();
if (active) stop ();
ev_signal_set (static_cast<ev_signal *>(this), signum);
if (active) start ();
}
void start (int signum) throw ()
{
set (signum);
start ();
}
EV_END_WATCHER (sig, signal)
#endif
#if EV_CHILD_ENABLE
EV_BEGIN_WATCHER (child, child)
void set (int pid, int trace = 0) throw ()
{
int active = is_active ();
if (active) stop ();
ev_child_set (static_cast<ev_child *>(this), pid, trace);
if (active) start ();
}
void start (int pid, int trace = 0) throw ()
{
set (pid, trace);
start ();
}
EV_END_WATCHER (child, child)
#endif
#if EV_STAT_ENABLE
EV_BEGIN_WATCHER (stat, stat)
void set (const char *path, ev_tstamp interval = 0.) throw ()
{
int active = is_active ();
if (active) stop ();
ev_stat_set (static_cast<ev_stat *>(this), path, interval);
if (active) start ();
}
void start (const char *path, ev_tstamp interval = 0.) throw ()
{
stop ();
set (path, interval);
start ();
}
void update () throw ()
{
ev_stat_stat (EV_A_ static_cast<ev_stat *>(this));
}
EV_END_WATCHER (stat, stat)
#endif
#if EV_IDLE_ENABLE
EV_BEGIN_WATCHER (idle, idle)
void set () throw () { }
EV_END_WATCHER (idle, idle)
#endif
#if EV_PREPARE_ENABLE
EV_BEGIN_WATCHER (prepare, prepare)
void set () throw () { }
EV_END_WATCHER (prepare, prepare)
#endif
#if EV_CHECK_ENABLE
EV_BEGIN_WATCHER (check, check)
void set () throw () { }
EV_END_WATCHER (check, check)
#endif
#if EV_EMBED_ENABLE
EV_BEGIN_WATCHER (embed, embed)
void set_embed (struct ev_loop *embedded_loop) throw ()
{
int active = is_active ();
if (active) stop ();
ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);
if (active) start ();
}
void start (struct ev_loop *embedded_loop) throw ()
{
set (embedded_loop);
start ();
}
void sweep ()
{
ev_embed_sweep (EV_A_ static_cast<ev_embed *>(this));
}
EV_END_WATCHER (embed, embed)
#endif
#if EV_FORK_ENABLE
EV_BEGIN_WATCHER (fork, fork)
void set () throw () { }
EV_END_WATCHER (fork, fork)
#endif
#if EV_ASYNC_ENABLE
EV_BEGIN_WATCHER (async, async)
void send () throw ()
{
ev_async_send (EV_A_ static_cast<ev_async *>(this));
}
bool async_pending () throw ()
{
return ev_async_pending (static_cast<ev_async *>(this));
}
EV_END_WATCHER (async, async)
#endif
#undef EV_PX
#undef EV_PX_
#undef EV_CONSTRUCT
#undef EV_BEGIN_WATCHER
#undef EV_END_WATCHER
}
#endif

5647
libev/ev.3 Normal file

File diff suppressed because it is too large Load Diff

5144
libev/ev.c Normal file

File diff suppressed because it is too large Load Diff

854
libev/ev.h Normal file
View File

@ -0,0 +1,854 @@
/*
* libev native API header
*
* Copyright (c) 2007,2008,2009,2010,2011,2012,2015 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef EV_H_
#define EV_H_
#ifdef __cplusplus
# define EV_CPP(x) x
# if __cplusplus >= 201103L
# define EV_THROW noexcept
# else
# define EV_THROW throw ()
# endif
#else
# define EV_CPP(x)
# define EV_THROW
#endif
EV_CPP(extern "C" {)
/*****************************************************************************/
/* pre-4.0 compatibility */
#ifndef EV_COMPAT3
# define EV_COMPAT3 1
#endif
#ifndef EV_FEATURES
# if defined __OPTIMIZE_SIZE__
# define EV_FEATURES 0x7c
# else
# define EV_FEATURES 0x7f
# endif
#endif
#define EV_FEATURE_CODE ((EV_FEATURES) & 1)
#define EV_FEATURE_DATA ((EV_FEATURES) & 2)
#define EV_FEATURE_CONFIG ((EV_FEATURES) & 4)
#define EV_FEATURE_API ((EV_FEATURES) & 8)
#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16)
#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 32)
#define EV_FEATURE_OS ((EV_FEATURES) & 64)
/* these priorities are inclusive, higher priorities will be invoked earlier */
#ifndef EV_MINPRI
# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0)
#endif
#ifndef EV_MAXPRI
# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0)
#endif
#ifndef EV_MULTIPLICITY
# define EV_MULTIPLICITY EV_FEATURE_CONFIG
#endif
#ifndef EV_PERIODIC_ENABLE
# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_STAT_ENABLE
# define EV_STAT_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_PREPARE_ENABLE
# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHECK_ENABLE
# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_IDLE_ENABLE
# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_FORK_ENABLE
# define EV_FORK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CLEANUP_ENABLE
# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHILD_ENABLE
# ifdef _WIN32
# define EV_CHILD_ENABLE 0
# else
# define EV_CHILD_ENABLE EV_FEATURE_WATCHERS
#endif
#endif
#ifndef EV_ASYNC_ENABLE
# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_EMBED_ENABLE
# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_WALK_ENABLE
# define EV_WALK_ENABLE 0 /* not yet */
#endif
/*****************************************************************************/
#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE
# undef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE 1
#endif
/*****************************************************************************/
typedef double ev_tstamp;
#include <string.h> /* for memmove */
#ifndef EV_ATOMIC_T
# include <signal.h>
# define EV_ATOMIC_T sig_atomic_t volatile
#endif
#if EV_STAT_ENABLE
# ifdef _WIN32
# include <time.h>
# include <sys/types.h>
# endif
# include <sys/stat.h>
#endif
/* support multiple event loops? */
#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P, /* a loop as first of multiple parameters */
# define EV_A loop /* a loop as sole argument to a function call */
# define EV_A_ EV_A, /* a loop as first of multiple arguments */
# define EV_DEFAULT_UC ev_default_loop_uc_ () /* the default loop, if initialised, as sole arg */
# define EV_DEFAULT_UC_ EV_DEFAULT_UC, /* the default loop as first of multiple arguments */
# define EV_DEFAULT ev_default_loop (0) /* the default loop as sole arg */
# define EV_DEFAULT_ EV_DEFAULT, /* the default loop as first of multiple arguments */
#else
# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_
# define EV_DEFAULT
# define EV_DEFAULT_
# define EV_DEFAULT_UC
# define EV_DEFAULT_UC_
# undef EV_EMBED_ENABLE
#endif
/* EV_INLINE is used for functions in header files */
#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3
# define EV_INLINE static inline
#else
# define EV_INLINE static
#endif
#ifdef EV_API_STATIC
# define EV_API_DECL static
#else
# define EV_API_DECL extern
#endif
/* EV_PROTOTYPES can be used to switch of prototype declarations */
#ifndef EV_PROTOTYPES
# define EV_PROTOTYPES 1
#endif
/*****************************************************************************/
#define EV_VERSION_MAJOR 4
#define EV_VERSION_MINOR 24
/* eventmask, revents, events... */
enum {
EV_UNDEF = (int)0xFFFFFFFF, /* guaranteed to be invalid */
EV_NONE = 0x00, /* no events */
EV_READ = 0x01, /* ev_io detected read will not block */
EV_WRITE = 0x02, /* ev_io detected write will not block */
EV__IOFDSET = 0x80, /* internal use only */
EV_IO = EV_READ, /* alias for type-detection */
EV_TIMER = 0x00000100, /* timer timed out */
#if EV_COMPAT3
EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */
#endif
EV_PERIODIC = 0x00000200, /* periodic timer timed out */
EV_SIGNAL = 0x00000400, /* signal was received */
EV_CHILD = 0x00000800, /* child/pid had status change */
EV_STAT = 0x00001000, /* stat data changed */
EV_IDLE = 0x00002000, /* event loop is idling */
EV_PREPARE = 0x00004000, /* event loop about to poll */
EV_CHECK = 0x00008000, /* event loop finished poll */
EV_EMBED = 0x00010000, /* embedded event loop needs sweep */
EV_FORK = 0x00020000, /* event loop resumed in child */
EV_CLEANUP = 0x00040000, /* event loop resumed in child */
EV_ASYNC = 0x00080000, /* async intra-loop signal */
EV_CUSTOM = 0x01000000, /* for use by user code */
EV_ERROR = (int)0x80000000 /* sent when an error occurs */
};
/* can be used to add custom fields to all watchers, while losing binary compatibility */
#ifndef EV_COMMON
# define EV_COMMON void *data;
#endif
#ifndef EV_CB_DECLARE
# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents);
#endif
#ifndef EV_CB_INVOKE
# define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents))
#endif
/* not official, do not use */
#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents)
/*
* struct member types:
* private: you may look at them, but not change them,
* and they might not mean anything to you.
* ro: can be read anytime, but only changed when the watcher isn't active.
* rw: can be read and modified anytime, even when the watcher is active.
*
* some internal details that might be helpful for debugging:
*
* active is either 0, which means the watcher is not active,
* or the array index of the watcher (periodics, timers)
* or the array index + 1 (most other watchers)
* or simply 1 for watchers that aren't in some array.
* pending is either 0, in which case the watcher isn't,
* or the array index + 1 in the pendings array.
*/
#if EV_MINPRI == EV_MAXPRI
# define EV_DECL_PRIORITY
#elif !defined (EV_DECL_PRIORITY)
# define EV_DECL_PRIORITY int priority;
#endif
/* shared by all watchers */
#define EV_WATCHER(type) \
int active; /* private */ \
int pending; /* private */ \
EV_DECL_PRIORITY /* private */ \
EV_COMMON /* rw */ \
EV_CB_DECLARE (type) /* private */
#define EV_WATCHER_LIST(type) \
EV_WATCHER (type) \
struct ev_watcher_list *next; /* private */
#define EV_WATCHER_TIME(type) \
EV_WATCHER (type) \
ev_tstamp at; /* private */
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher
{
EV_WATCHER (ev_watcher)
} ev_watcher;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_list
{
EV_WATCHER_LIST (ev_watcher_list)
} ev_watcher_list;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_time
{
EV_WATCHER_TIME (ev_watcher_time)
} ev_watcher_time;
/* invoked when fd is either EV_READable or EV_WRITEable */
/* revent EV_READ, EV_WRITE */
typedef struct ev_io
{
EV_WATCHER_LIST (ev_io)
int fd; /* ro */
int events; /* ro */
} ev_io;
/* invoked after a specific time, repeatable (based on monotonic clock) */
/* revent EV_TIMEOUT */
typedef struct ev_timer
{
EV_WATCHER_TIME (ev_timer)
ev_tstamp repeat; /* rw */
} ev_timer;
/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */
/* revent EV_PERIODIC */
typedef struct ev_periodic
{
EV_WATCHER_TIME (ev_periodic)
ev_tstamp offset; /* rw */
ev_tstamp interval; /* rw */
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_THROW; /* rw */
} ev_periodic;
/* invoked when the given signal has been received */
/* revent EV_SIGNAL */
typedef struct ev_signal
{
EV_WATCHER_LIST (ev_signal)
int signum; /* ro */
} ev_signal;
/* invoked when sigchld is received and waitpid indicates the given pid */
/* revent EV_CHILD */
/* does not support priorities */
typedef struct ev_child
{
EV_WATCHER_LIST (ev_child)
int flags; /* private */
int pid; /* ro */
int rpid; /* rw, holds the received pid */
int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */
} ev_child;
#if EV_STAT_ENABLE
/* st_nlink = 0 means missing file or other error */
# ifdef _WIN32
typedef struct _stati64 ev_statdata;
# else
typedef struct stat ev_statdata;
# endif
/* invoked each time the stat data changes for a given path */
/* revent EV_STAT */
typedef struct ev_stat
{
EV_WATCHER_LIST (ev_stat)
ev_timer timer; /* private */
ev_tstamp interval; /* ro */
const char *path; /* ro */
ev_statdata prev; /* ro */
ev_statdata attr; /* ro */
int wd; /* wd for inotify, fd for kqueue */
} ev_stat;
#endif
#if EV_IDLE_ENABLE
/* invoked when the nothing else needs to be done, keeps the process from blocking */
/* revent EV_IDLE */
typedef struct ev_idle
{
EV_WATCHER (ev_idle)
} ev_idle;
#endif
/* invoked for each run of the mainloop, just before the blocking call */
/* you can still change events in any way you like */
/* revent EV_PREPARE */
typedef struct ev_prepare
{
EV_WATCHER (ev_prepare)
} ev_prepare;
/* invoked for each run of the mainloop, just after the blocking call */
/* revent EV_CHECK */
typedef struct ev_check
{
EV_WATCHER (ev_check)
} ev_check;
#if EV_FORK_ENABLE
/* the callback gets invoked before check in the child process when a fork was detected */
/* revent EV_FORK */
typedef struct ev_fork
{
EV_WATCHER (ev_fork)
} ev_fork;
#endif
#if EV_CLEANUP_ENABLE
/* is invoked just before the loop gets destroyed */
/* revent EV_CLEANUP */
typedef struct ev_cleanup
{
EV_WATCHER (ev_cleanup)
} ev_cleanup;
#endif
#if EV_EMBED_ENABLE
/* used to embed an event loop inside another */
/* the callback gets invoked when the event loop has handled events, and can be 0 */
typedef struct ev_embed
{
EV_WATCHER (ev_embed)
struct ev_loop *other; /* ro */
ev_io io; /* private */
ev_prepare prepare; /* private */
ev_check check; /* unused */
ev_timer timer; /* unused */
ev_periodic periodic; /* unused */
ev_idle idle; /* unused */
ev_fork fork; /* private */
#if EV_CLEANUP_ENABLE
ev_cleanup cleanup; /* unused */
#endif
} ev_embed;
#endif
#if EV_ASYNC_ENABLE
/* invoked when somebody calls ev_async_send on the watcher */
/* revent EV_ASYNC */
typedef struct ev_async
{
EV_WATCHER (ev_async)
EV_ATOMIC_T sent; /* private */
} ev_async;
# define ev_async_pending(w) (+(w)->sent)
#endif
/* the presence of this union forces similar struct layout */
union ev_any_watcher
{
struct ev_watcher w;
struct ev_watcher_list wl;
struct ev_io io;
struct ev_timer timer;
struct ev_periodic periodic;
struct ev_signal signal;
struct ev_child child;
#if EV_STAT_ENABLE
struct ev_stat stat;
#endif
#if EV_IDLE_ENABLE
struct ev_idle idle;
#endif
struct ev_prepare prepare;
struct ev_check check;
#if EV_FORK_ENABLE
struct ev_fork fork;
#endif
#if EV_CLEANUP_ENABLE
struct ev_cleanup cleanup;
#endif
#if EV_EMBED_ENABLE
struct ev_embed embed;
#endif
#if EV_ASYNC_ENABLE
struct ev_async async;
#endif
};
/* flag bits for ev_default_loop and ev_loop_new */
enum {
/* the default */
EVFLAG_AUTO = 0x00000000U, /* not quite a mask */
/* flag bits */
EVFLAG_NOENV = 0x01000000U, /* do NOT consult environment */
EVFLAG_FORKCHECK = 0x02000000U, /* check for a fork in each iteration */
/* debugging/feature disable */
EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */
#if EV_COMPAT3
EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */
#endif
EVFLAG_SIGNALFD = 0x00200000U, /* attempt to use signalfd */
EVFLAG_NOSIGMASK = 0x00400000U /* avoid modifying the signal mask */
};
/* method bits to be ored together */
enum {
EVBACKEND_SELECT = 0x00000001U, /* available just about anywhere */
EVBACKEND_POLL = 0x00000002U, /* !win, !aix, broken on osx */
EVBACKEND_EPOLL = 0x00000004U, /* linux */
EVBACKEND_KQUEUE = 0x00000008U, /* bsd, broken on osx */
EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
EVBACKEND_PORT = 0x00000020U, /* solaris 10 */
EVBACKEND_ALL = 0x0000003FU, /* all known backends */
EVBACKEND_MASK = 0x0000FFFFU /* all future backends */
};
#if EV_PROTOTYPES
EV_API_DECL int ev_version_major (void) EV_THROW;
EV_API_DECL int ev_version_minor (void) EV_THROW;
EV_API_DECL unsigned int ev_supported_backends (void) EV_THROW;
EV_API_DECL unsigned int ev_recommended_backends (void) EV_THROW;
EV_API_DECL unsigned int ev_embeddable_backends (void) EV_THROW;
EV_API_DECL ev_tstamp ev_time (void) EV_THROW;
EV_API_DECL void ev_sleep (ev_tstamp delay) EV_THROW; /* sleep for a while */
/* Sets the allocation function to use, works like realloc.
* It is used to allocate and free memory.
* If it returns zero when memory needs to be allocated, the library might abort
* or take some potentially destructive action.
* The default is your system realloc function.
*/
EV_API_DECL void ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW;
/* set the callback function to call on a
* retryable syscall error
* (such as failed select, poll, epoll_wait)
*/
EV_API_DECL void ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW;
#if EV_MULTIPLICITY
/* the default loop is the only one that handles signals and child watchers */
/* you can call this as often as you like */
EV_API_DECL struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW;
#ifdef EV_API_STATIC
EV_API_DECL struct ev_loop *ev_default_loop_ptr;
#endif
EV_INLINE struct ev_loop *
ev_default_loop_uc_ (void) EV_THROW
{
extern struct ev_loop *ev_default_loop_ptr;
return ev_default_loop_ptr;
}
EV_INLINE int
ev_is_default_loop (EV_P) EV_THROW
{
return EV_A == EV_DEFAULT_UC;
}
/* create and destroy alternative loops that don't handle signals */
EV_API_DECL struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0)) EV_THROW;
EV_API_DECL ev_tstamp ev_now (EV_P) EV_THROW; /* time w.r.t. timers and the eventloop, updated after each poll */
#else
EV_API_DECL int ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW; /* returns true when successful */
EV_API_DECL ev_tstamp ev_rt_now;
EV_INLINE ev_tstamp
ev_now (void) EV_THROW
{
return ev_rt_now;
}
/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */
EV_INLINE int
ev_is_default_loop (void) EV_THROW
{
return 1;
}
#endif /* multiplicity */
/* destroy event loops, also works for the default loop */
EV_API_DECL void ev_loop_destroy (EV_P);
/* this needs to be called after fork, to duplicate the loop */
/* when you want to re-use it in the child */
/* you can call it in either the parent or the child */
/* you can actually call it at any time, anywhere :) */
EV_API_DECL void ev_loop_fork (EV_P) EV_THROW;
EV_API_DECL unsigned int ev_backend (EV_P) EV_THROW; /* backend in use by loop */
EV_API_DECL void ev_now_update (EV_P) EV_THROW; /* update event loop time */
#if EV_WALK_ENABLE
/* walk (almost) all watchers in the loop of a given type, invoking the */
/* callback on every such watcher. The callback might stop the watcher, */
/* but do nothing else with the loop */
EV_API_DECL void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW;
#endif
#endif /* prototypes */
/* ev_run flags values */
enum {
EVRUN_NOWAIT = 1, /* do not block/wait */
EVRUN_ONCE = 2 /* block *once* only */
};
/* ev_break how values */
enum {
EVBREAK_CANCEL = 0, /* undo unloop */
EVBREAK_ONE = 1, /* unloop once */
EVBREAK_ALL = 2 /* unloop all loops */
};
#if EV_PROTOTYPES
EV_API_DECL int ev_run (EV_P_ int flags EV_CPP (= 0));
EV_API_DECL void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)) EV_THROW; /* break out of the loop */
/*
* ref/unref can be used to add or remove a refcount on the mainloop. every watcher
* keeps one reference. if you have a long-running watcher you never unregister that
* should not keep ev_loop from running, unref() after starting, and ref() before stopping.
*/
EV_API_DECL void ev_ref (EV_P) EV_THROW;
EV_API_DECL void ev_unref (EV_P) EV_THROW;
/*
* convenience function, wait for a single event, without registering an event watcher
* if timeout is < 0, do wait indefinitely
*/
EV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW;
# if EV_FEATURE_API
EV_API_DECL unsigned int ev_iteration (EV_P) EV_THROW; /* number of loop iterations */
EV_API_DECL unsigned int ev_depth (EV_P) EV_THROW; /* #ev_loop enters - #ev_loop leaves */
EV_API_DECL void ev_verify (EV_P) EV_THROW; /* abort if loop data corrupted */
EV_API_DECL void ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* sleep at least this time, default 0 */
EV_API_DECL void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* sleep at least this time, default 0 */
/* advanced stuff for threading etc. support, see docs */
EV_API_DECL void ev_set_userdata (EV_P_ void *data) EV_THROW;
EV_API_DECL void *ev_userdata (EV_P) EV_THROW;
typedef void (*ev_loop_callback)(EV_P);
EV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW;
/* C++ doesn't allow the use of the ev_loop_callback typedef here, so we need to spell it out */
EV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW;
EV_API_DECL unsigned int ev_pending_count (EV_P) EV_THROW; /* number of pending events, if any */
EV_API_DECL void ev_invoke_pending (EV_P); /* invoke all pending watchers */
/*
* stop/start the timer handling.
*/
EV_API_DECL void ev_suspend (EV_P) EV_THROW;
EV_API_DECL void ev_resume (EV_P) EV_THROW;
#endif
#endif
/* these may evaluate ev multiple times, and the other arguments at most once */
/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */
#define ev_init(ev,cb_) do { \
((ev_watcher *)(void *)(ev))->active = \
((ev_watcher *)(void *)(ev))->pending = 0; \
ev_set_priority ((ev), 0); \
ev_set_cb ((ev), cb_); \
} 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_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0)
#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0)
#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)
#define ev_stat_set(ev,path_,interval_) do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0)
#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0)
#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_cleanup_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_async_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0)
#define ev_signal_init(ev,cb,signum) do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)
#define ev_child_init(ev,cb,pid,trace) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0)
#define ev_stat_init(ev,cb,path,interval) do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0)
#define ev_idle_init(ev,cb) do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)
#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)
#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
#define ev_cleanup_init(ev,cb) do { ev_init ((ev), (cb)); ev_cleanup_set ((ev)); } while (0)
#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
#define ev_cb_(ev) (ev)->cb /* rw */
#define ev_cb(ev) (memmove (&ev_cb_ (ev), &((ev_watcher *)(ev))->cb, sizeof (ev_cb_ (ev))), (ev)->cb)
#if EV_MINPRI == EV_MAXPRI
# define ev_priority(ev) ((ev), EV_MINPRI)
# define ev_set_priority(ev,pri) ((ev), (pri))
#else
# define ev_priority(ev) (+(((ev_watcher *)(void *)(ev))->priority))
# define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri)
#endif
#define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at)
#ifndef ev_set_cb
# define ev_set_cb(ev,cb_) (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev))))
#endif
/* stopping (enabling, adding) a watcher does nothing if it is already running */
/* stopping (disabling, deleting) a watcher does nothing unless it's already running */
#if EV_PROTOTYPES
/* feeds an event into a watcher as if the event actually occurred */
/* accepts any ev_watcher type */
EV_API_DECL void ev_feed_event (EV_P_ void *w, int revents) EV_THROW;
EV_API_DECL void ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW;
#if EV_SIGNAL_ENABLE
EV_API_DECL void ev_feed_signal (int signum) EV_THROW;
EV_API_DECL void ev_feed_signal_event (EV_P_ int signum) EV_THROW;
#endif
EV_API_DECL void ev_invoke (EV_P_ void *w, int revents);
EV_API_DECL int ev_clear_pending (EV_P_ void *w) EV_THROW;
EV_API_DECL void ev_io_start (EV_P_ ev_io *w) EV_THROW;
EV_API_DECL void ev_io_stop (EV_P_ ev_io *w) EV_THROW;
EV_API_DECL void ev_timer_start (EV_P_ ev_timer *w) EV_THROW;
EV_API_DECL void ev_timer_stop (EV_P_ ev_timer *w) EV_THROW;
/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */
EV_API_DECL void ev_timer_again (EV_P_ ev_timer *w) EV_THROW;
/* return remaining time */
EV_API_DECL ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW;
#if EV_PERIODIC_ENABLE
EV_API_DECL void ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW;
EV_API_DECL void ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW;
EV_API_DECL void ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW;
#endif
/* only supported in the default loop */
#if EV_SIGNAL_ENABLE
EV_API_DECL void ev_signal_start (EV_P_ ev_signal *w) EV_THROW;
EV_API_DECL void ev_signal_stop (EV_P_ ev_signal *w) EV_THROW;
#endif
/* only supported in the default loop */
# if EV_CHILD_ENABLE
EV_API_DECL void ev_child_start (EV_P_ ev_child *w) EV_THROW;
EV_API_DECL void ev_child_stop (EV_P_ ev_child *w) EV_THROW;
# endif
# if EV_STAT_ENABLE
EV_API_DECL void ev_stat_start (EV_P_ ev_stat *w) EV_THROW;
EV_API_DECL void ev_stat_stop (EV_P_ ev_stat *w) EV_THROW;
EV_API_DECL void ev_stat_stat (EV_P_ ev_stat *w) EV_THROW;
# endif
# if EV_IDLE_ENABLE
EV_API_DECL void ev_idle_start (EV_P_ ev_idle *w) EV_THROW;
EV_API_DECL void ev_idle_stop (EV_P_ ev_idle *w) EV_THROW;
# endif
#if EV_PREPARE_ENABLE
EV_API_DECL void ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW;
EV_API_DECL void ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW;
#endif
#if EV_CHECK_ENABLE
EV_API_DECL void ev_check_start (EV_P_ ev_check *w) EV_THROW;
EV_API_DECL void ev_check_stop (EV_P_ ev_check *w) EV_THROW;
#endif
# if EV_FORK_ENABLE
EV_API_DECL void ev_fork_start (EV_P_ ev_fork *w) EV_THROW;
EV_API_DECL void ev_fork_stop (EV_P_ ev_fork *w) EV_THROW;
# endif
# if EV_CLEANUP_ENABLE
EV_API_DECL void ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW;
EV_API_DECL void ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW;
# endif
# if EV_EMBED_ENABLE
/* only supported when loop to be embedded is in fact embeddable */
EV_API_DECL void ev_embed_start (EV_P_ ev_embed *w) EV_THROW;
EV_API_DECL void ev_embed_stop (EV_P_ ev_embed *w) EV_THROW;
EV_API_DECL void ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW;
# endif
# if EV_ASYNC_ENABLE
EV_API_DECL void ev_async_start (EV_P_ ev_async *w) EV_THROW;
EV_API_DECL void ev_async_stop (EV_P_ ev_async *w) EV_THROW;
EV_API_DECL void ev_async_send (EV_P_ ev_async *w) EV_THROW;
# endif
#if EV_COMPAT3
#define EVLOOP_NONBLOCK EVRUN_NOWAIT
#define EVLOOP_ONESHOT EVRUN_ONCE
#define EVUNLOOP_CANCEL EVBREAK_CANCEL
#define EVUNLOOP_ONE EVBREAK_ONE
#define EVUNLOOP_ALL EVBREAK_ALL
#if EV_PROTOTYPES
EV_INLINE void ev_loop (EV_P_ int flags) { ev_run (EV_A_ flags); }
EV_INLINE void ev_unloop (EV_P_ int how ) { ev_break (EV_A_ how ); }
EV_INLINE void ev_default_destroy (void) { ev_loop_destroy (EV_DEFAULT); }
EV_INLINE void ev_default_fork (void) { ev_loop_fork (EV_DEFAULT); }
#if EV_FEATURE_API
EV_INLINE unsigned int ev_loop_count (EV_P) { return ev_iteration (EV_A); }
EV_INLINE unsigned int ev_loop_depth (EV_P) { return ev_depth (EV_A); }
EV_INLINE void ev_loop_verify (EV_P) { ev_verify (EV_A); }
#endif
#endif
#else
typedef struct ev_loop ev_loop;
#endif
#endif
EV_CPP(})
#endif

5570
libev/ev.pod Normal file

File diff suppressed because it is too large Load Diff

285
libev/ev_epoll.c Normal file
View File

@ -0,0 +1,285 @@
/*
* libev epoll fd activity backend
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
/*
* general notes about epoll:
*
* a) epoll silently removes fds from the fd set. as nothing tells us
* that an fd has been removed otherwise, we have to continually
* "rearm" fds that we suspect *might* have changed (same
* problem with kqueue, but much less costly there).
* b) the fact that ADD != MOD creates a lot of extra syscalls due to a)
* and seems not to have any advantage.
* c) the inability to handle fork or file descriptors (think dup)
* limits the applicability over poll, so this is not a generic
* poll replacement.
* d) epoll doesn't work the same as select with many file descriptors
* (such as files). while not critical, no other advanced interface
* seems to share this (rather non-unixy) limitation.
* e) epoll claims to be embeddable, but in practise you never get
* a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32).
* f) epoll_ctl returning EPERM means the fd is always ready.
*
* lots of "weird code" and complication handling in this file is due
* to these design problems with epoll, as we try very hard to avoid
* epoll_ctl syscalls for common usage patterns and handle the breakage
* ensuing from receiving events for closed and otherwise long gone
* file descriptors.
*/
#include <sys/epoll.h>
#define EV_EMASK_EPERM 0x80
static void
epoll_modify (EV_P_ int fd, int oev, int nev)
{
struct epoll_event ev;
unsigned char oldmask;
/*
* we handle EPOLL_CTL_DEL by ignoring it here
* on the assumption that the fd is gone anyways
* if that is wrong, we have to handle the spurious
* event in epoll_poll.
* if the fd is added again, we try to ADD it, and, if that
* fails, we assume it still has the same eventmask.
*/
if (!nev)
return;
oldmask = anfds [fd].emask;
anfds [fd].emask = nev;
/* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */
ev.data.u64 = (uint64_t)(uint32_t)fd
| ((uint64_t)(uint32_t)++anfds [fd].egen << 32);
ev.events = (nev & EV_READ ? EPOLLIN : 0)
| (nev & EV_WRITE ? EPOLLOUT : 0);
if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev)))
return;
if (expect_true (errno == ENOENT))
{
/* if ENOENT then the fd went away, so try to do the right thing */
if (!nev)
goto dec_egen;
if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev))
return;
}
else if (expect_true (errno == EEXIST))
{
/* EEXIST means we ignored a previous DEL, but the fd is still active */
/* if the kernel mask is the same as the new mask, we assume it hasn't changed */
if (oldmask == nev)
goto dec_egen;
if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))
return;
}
else if (expect_true (errno == EPERM))
{
/* EPERM means the fd is always ready, but epoll is too snobbish */
/* to handle it, unlike select or poll. */
anfds [fd].emask = EV_EMASK_EPERM;
/* add fd to epoll_eperms, if not already inside */
if (!(oldmask & EV_EMASK_EPERM))
{
array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2);
epoll_eperms [epoll_epermcnt++] = fd;
}
return;
}
fd_kill (EV_A_ fd);
dec_egen:
/* we didn't successfully call epoll_ctl, so decrement the generation counter again */
--anfds [fd].egen;
}
static void
epoll_poll (EV_P_ ev_tstamp timeout)
{
int i;
int eventcnt;
if (expect_false (epoll_epermcnt))
timeout = 0.;
/* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */
/* the default libev max wait time, however. */
EV_RELEASE_CB;
eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, timeout * 1e3);
EV_ACQUIRE_CB;
if (expect_false (eventcnt < 0))
{
if (errno != EINTR)
ev_syserr ("(libev) epoll_wait");
return;
}
for (i = 0; i < eventcnt; ++i)
{
struct epoll_event *ev = epoll_events + i;
int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */
int want = anfds [fd].events;
int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)
| (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0);
/*
* check for spurious notification.
* this only finds spurious notifications on egen updates
* other spurious notifications will be found by epoll_ctl, below
* we assume that fd is always in range, as we never shrink the anfds array
*/
if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
{
/* recreate kernel state */
postfork |= 2;
continue;
}
if (expect_false (got & ~want))
{
anfds [fd].emask = want;
/*
* we received an event but are not interested in it, try mod or del
* this often happens because we optimistically do not unregister fds
* when we are no longer interested in them, but also when we get spurious
* notifications for fds from another process. this is partially handled
* above with the gencounter check (== our fd is not the event fd), and
* partially here, when epoll_ctl returns an error (== a child has the fd
* but we closed it).
*/
ev->events = (want & EV_READ ? EPOLLIN : 0)
| (want & EV_WRITE ? EPOLLOUT : 0);
/* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */
/* which is fortunately easy to do for us. */
if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))
{
postfork |= 2; /* an error occurred, recreate kernel state */
continue;
}
}
fd_event (EV_A_ fd, got);
}
/* if the receive array was full, increase its size */
if (expect_false (eventcnt == epoll_eventmax))
{
ev_free (epoll_events);
epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);
epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
}
/* now synthesize events for all fds where epoll fails, while select works... */
for (i = epoll_epermcnt; i--; )
{
int fd = epoll_eperms [i];
unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE);
if (anfds [fd].emask & EV_EMASK_EPERM && events)
fd_event (EV_A_ fd, events);
else
{
epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];
anfds [fd].emask = 0;
}
}
}
inline_size
int
epoll_init (EV_P_ int flags)
{
#if defined EPOLL_CLOEXEC && !defined __ANDROID__
backend_fd = epoll_create1 (EPOLL_CLOEXEC);
if (backend_fd < 0 && (errno == EINVAL || errno == ENOSYS))
#endif
backend_fd = epoll_create (256);
if (backend_fd < 0)
return 0;
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
backend_mintime = 1e-3; /* epoll does sometimes return early, this is just to avoid the worst */
backend_modify = epoll_modify;
backend_poll = epoll_poll;
epoll_eventmax = 64; /* initial number of events receivable per poll */
epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
return EVBACKEND_EPOLL;
}
inline_size
void
epoll_destroy (EV_P)
{
ev_free (epoll_events);
array_free (epoll_eperm, EMPTY);
}
inline_size
void
epoll_fork (EV_P)
{
close (backend_fd);
while ((backend_fd = epoll_create (256)) < 0)
ev_syserr ("(libev) epoll_create");
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
fd_rearm_all (EV_A);
}

218
libev/ev_kqueue.c Normal file
View File

@ -0,0 +1,218 @@
/*
* libev kqueue backend
*
* Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/event.h>
#include <string.h>
#include <errno.h>
inline_speed
void
kqueue_change (EV_P_ int fd, int filter, int flags, int fflags)
{
++kqueue_changecnt;
array_needsize (struct kevent, kqueue_changes, kqueue_changemax, kqueue_changecnt, EMPTY2);
EV_SET (&kqueue_changes [kqueue_changecnt - 1], fd, filter, flags, fflags, 0, 0);
}
/* OS X at least needs this */
#ifndef EV_ENABLE
# define EV_ENABLE 0
#endif
#ifndef NOTE_EOF
# define NOTE_EOF 0
#endif
static void
kqueue_modify (EV_P_ int fd, int oev, int nev)
{
if (oev != nev)
{
if (oev & EV_READ)
kqueue_change (EV_A_ fd, EVFILT_READ , EV_DELETE, 0);
if (oev & EV_WRITE)
kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0);
}
/* to detect close/reopen reliably, we have to re-add */
/* event requests even when oev == nev */
if (nev & EV_READ)
kqueue_change (EV_A_ fd, EVFILT_READ , EV_ADD | EV_ENABLE, NOTE_EOF);
if (nev & EV_WRITE)
kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, NOTE_EOF);
}
static void
kqueue_poll (EV_P_ ev_tstamp timeout)
{
int res, i;
struct timespec ts;
/* need to resize so there is enough space for errors */
if (kqueue_changecnt > kqueue_eventmax)
{
ev_free (kqueue_events);
kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_changecnt);
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
}
EV_RELEASE_CB;
EV_TS_SET (ts, timeout);
res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts);
EV_ACQUIRE_CB;
kqueue_changecnt = 0;
if (expect_false (res < 0))
{
if (errno != EINTR)
ev_syserr ("(libev) kevent");
return;
}
for (i = 0; i < res; ++i)
{
int fd = kqueue_events [i].ident;
if (expect_false (kqueue_events [i].flags & EV_ERROR))
{
int err = kqueue_events [i].data;
/* we are only interested in errors for fds that we are interested in :) */
if (anfds [fd].events)
{
if (err == ENOENT) /* resubmit changes on ENOENT */
kqueue_modify (EV_A_ fd, 0, anfds [fd].events);
else if (err == EBADF) /* on EBADF, we re-check the fd */
{
if (fd_valid (fd))
kqueue_modify (EV_A_ fd, 0, anfds [fd].events);
else
fd_kill (EV_A_ fd);
}
else /* on all other errors, we error out on the fd */
fd_kill (EV_A_ fd);
}
}
else
fd_event (
EV_A_
fd,
kqueue_events [i].filter == EVFILT_READ ? EV_READ
: kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE
: 0
);
}
if (expect_false (res == kqueue_eventmax))
{
ev_free (kqueue_events);
kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_eventmax + 1);
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
}
}
inline_size
int
kqueue_init (EV_P_ int flags)
{
/* initialize the kernel queue */
kqueue_fd_pid = getpid ();
if ((backend_fd = kqueue ()) < 0)
return 0;
fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
backend_mintime = 1e-9; /* apparently, they did the right thing in freebsd */
backend_modify = kqueue_modify;
backend_poll = kqueue_poll;
kqueue_eventmax = 64; /* initial number of events receivable per poll */
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
kqueue_changes = 0;
kqueue_changemax = 0;
kqueue_changecnt = 0;
return EVBACKEND_KQUEUE;
}
inline_size
void
kqueue_destroy (EV_P)
{
ev_free (kqueue_events);
ev_free (kqueue_changes);
}
inline_size
void
kqueue_fork (EV_P)
{
/* some BSD kernels don't just destroy the kqueue itself,
* but also close the fd, which isn't documented, and
* impossible to support properly.
* we remember the pid of the kqueue call and only close
* the fd if the pid is still the same.
* this leaks fds on sane kernels, but BSD interfaces are
* notoriously buggy and rarely get fixed.
*/
pid_t newpid = getpid ();
if (newpid == kqueue_fd_pid)
close (backend_fd);
kqueue_fd_pid = newpid;
while ((backend_fd = kqueue ()) < 0)
ev_syserr ("(libev) kqueue");
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
/* re-register interest in fds */
fd_rearm_all (EV_A);
}
/* sys/event.h defines EV_ERROR */
#undef EV_ERROR

151
libev/ev_poll.c Normal file
View File

@ -0,0 +1,151 @@
/*
* libev poll fd activity backend
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#include <poll.h>
inline_size
void
pollidx_init (int *base, int count)
{
/* consider using memset (.., -1, ...), which is practically guaranteed
* to work on all systems implementing poll */
while (count--)
*base++ = -1;
}
static void
poll_modify (EV_P_ int fd, int oev, int nev)
{
int idx;
if (oev == nev)
return;
array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init);
idx = pollidxs [fd];
if (idx < 0) /* need to allocate a new pollfd */
{
pollidxs [fd] = idx = pollcnt++;
array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2);
polls [idx].fd = fd;
}
assert (polls [idx].fd == fd);
if (nev)
polls [idx].events =
(nev & EV_READ ? POLLIN : 0)
| (nev & EV_WRITE ? POLLOUT : 0);
else /* remove pollfd */
{
pollidxs [fd] = -1;
if (expect_true (idx < --pollcnt))
{
polls [idx] = polls [pollcnt];
pollidxs [polls [idx].fd] = idx;
}
}
}
static void
poll_poll (EV_P_ ev_tstamp timeout)
{
struct pollfd *p;
int res;
EV_RELEASE_CB;
res = poll (polls, pollcnt, timeout * 1e3);
EV_ACQUIRE_CB;
if (expect_false (res < 0))
{
if (errno == EBADF)
fd_ebadf (EV_A);
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
ev_syserr ("(libev) poll");
}
else
for (p = polls; res; ++p)
{
assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt));
if (expect_false (p->revents)) /* this expect is debatable */
{
--res;
if (expect_false (p->revents & POLLNVAL))
fd_kill (EV_A_ p->fd);
else
fd_event (
EV_A_
p->fd,
(p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
| (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
);
}
}
}
inline_size
int
poll_init (EV_P_ int flags)
{
backend_mintime = 1e-3;
backend_modify = poll_modify;
backend_poll = poll_poll;
pollidxs = 0; pollidxmax = 0;
polls = 0; pollmax = 0; pollcnt = 0;
return EVBACKEND_POLL;
}
inline_size
void
poll_destroy (EV_P)
{
ev_free (pollidxs);
ev_free (polls);
}

189
libev/ev_port.c Normal file
View File

@ -0,0 +1,189 @@
/*
* libev solaris event port backend
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
/* useful reading:
*
* http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME)
* http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget
* http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc)
* http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel)
*/
#include <sys/types.h>
#include <sys/time.h>
#include <poll.h>
#include <port.h>
#include <string.h>
#include <errno.h>
inline_speed
void
port_associate_and_check (EV_P_ int fd, int ev)
{
if (0 >
port_associate (
backend_fd, PORT_SOURCE_FD, fd,
(ev & EV_READ ? POLLIN : 0)
| (ev & EV_WRITE ? POLLOUT : 0),
0
)
)
{
if (errno == EBADFD)
fd_kill (EV_A_ fd);
else
ev_syserr ("(libev) port_associate");
}
}
static void
port_modify (EV_P_ int fd, int oev, int nev)
{
/* we need to reassociate no matter what, as closes are
* once more silently being discarded.
*/
if (!nev)
{
if (oev)
port_dissociate (backend_fd, PORT_SOURCE_FD, fd);
}
else
port_associate_and_check (EV_A_ fd, nev);
}
static void
port_poll (EV_P_ ev_tstamp timeout)
{
int res, i;
struct timespec ts;
uint_t nget = 1;
/* we initialise this to something we will skip in the loop, as */
/* port_getn can return with nget unchanged, but no indication */
/* whether it was the original value or has been updated :/ */
port_events [0].portev_source = 0;
EV_RELEASE_CB;
EV_TS_SET (ts, timeout);
res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
EV_ACQUIRE_CB;
/* port_getn may or may not set nget on error */
/* so we rely on port_events [0].portev_source not being updated */
if (res == -1 && errno != ETIME && errno != EINTR)
ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)");
for (i = 0; i < nget; ++i)
{
if (port_events [i].portev_source == PORT_SOURCE_FD)
{
int fd = port_events [i].portev_object;
fd_event (
EV_A_
fd,
(port_events [i].portev_events & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
| (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
);
fd_change (EV_A_ fd, EV__IOFDSET);
}
}
if (expect_false (nget == port_eventmax))
{
ev_free (port_events);
port_eventmax = array_nextsize (sizeof (port_event_t), port_eventmax, port_eventmax + 1);
port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
}
}
inline_size
int
port_init (EV_P_ int flags)
{
/* Initialize the kernel queue */
if ((backend_fd = port_create ()) < 0)
return 0;
assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD));
fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
/* if my reading of the opensolaris kernel sources are correct, then
* opensolaris does something very stupid: it checks if the time has already
* elapsed and doesn't round up if that is the case,m otherwise it DOES round
* up. Since we can't know what the case is, we need to guess by using a
* "large enough" timeout. Normally, 1e-9 would be correct.
*/
backend_mintime = 1e-3; /* needed to compensate for port_getn returning early */
backend_modify = port_modify;
backend_poll = port_poll;
port_eventmax = 64; /* initial number of events receivable per poll */
port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
return EVBACKEND_PORT;
}
inline_size
void
port_destroy (EV_P)
{
ev_free (port_events);
}
inline_size
void
port_fork (EV_P)
{
close (backend_fd);
while ((backend_fd = port_create ()) < 0)
ev_syserr ("(libev) port");
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
/* re-register interest in fds */
fd_rearm_all (EV_A);
}

316
libev/ev_select.c Normal file
View File

@ -0,0 +1,316 @@
/*
* libev select fd activity backend
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef _WIN32
/* for unix systems */
# include <inttypes.h>
# ifndef __hpux
/* for REAL unix systems */
# include <sys/select.h>
# endif
#endif
#ifndef EV_SELECT_USE_FD_SET
# ifdef NFDBITS
# define EV_SELECT_USE_FD_SET 0
# else
# define EV_SELECT_USE_FD_SET 1
# endif
#endif
#if EV_SELECT_IS_WINSOCKET
# undef EV_SELECT_USE_FD_SET
# define EV_SELECT_USE_FD_SET 1
# undef NFDBITS
# define NFDBITS 0
#endif
#if !EV_SELECT_USE_FD_SET
# define NFDBYTES (NFDBITS / 8)
#endif
#include <string.h>
static void
select_modify (EV_P_ int fd, int oev, int nev)
{
if (oev == nev)
return;
{
#if EV_SELECT_USE_FD_SET
#if EV_SELECT_IS_WINSOCKET
SOCKET handle = anfds [fd].handle;
#else
int handle = fd;
#endif
assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE));
/* FD_SET is broken on windows (it adds the fd to a set twice or more,
* which eventually leads to overflows). Need to call it only on changes.
*/
#if EV_SELECT_IS_WINSOCKET
if ((oev ^ nev) & EV_READ)
#endif
if (nev & EV_READ)
FD_SET (handle, (fd_set *)vec_ri);
else
FD_CLR (handle, (fd_set *)vec_ri);
#if EV_SELECT_IS_WINSOCKET
if ((oev ^ nev) & EV_WRITE)
#endif
if (nev & EV_WRITE)
FD_SET (handle, (fd_set *)vec_wi);
else
FD_CLR (handle, (fd_set *)vec_wi);
#else
int word = fd / NFDBITS;
fd_mask mask = 1UL << (fd % NFDBITS);
if (expect_false (vec_max <= word))
{
int new_max = word + 1;
vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES);
vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */
vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES);
vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */
#ifdef _WIN32
vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */
#endif
for (; vec_max < new_max; ++vec_max)
((fd_mask *)vec_ri) [vec_max] =
((fd_mask *)vec_wi) [vec_max] = 0;
}
((fd_mask *)vec_ri) [word] |= mask;
if (!(nev & EV_READ))
((fd_mask *)vec_ri) [word] &= ~mask;
((fd_mask *)vec_wi) [word] |= mask;
if (!(nev & EV_WRITE))
((fd_mask *)vec_wi) [word] &= ~mask;
#endif
}
}
static void
select_poll (EV_P_ ev_tstamp timeout)
{
struct timeval tv;
int res;
int fd_setsize;
EV_RELEASE_CB;
EV_TV_SET (tv, timeout);
#if EV_SELECT_USE_FD_SET
fd_setsize = sizeof (fd_set);
#else
fd_setsize = vec_max * NFDBYTES;
#endif
memcpy (vec_ro, vec_ri, fd_setsize);
memcpy (vec_wo, vec_wi, fd_setsize);
#ifdef _WIN32
/* pass in the write set as except set.
* the idea behind this is to work around a windows bug that causes
* errors to be reported as an exception and not by setting
* the writable bit. this is so uncontrollably lame.
*/
memcpy (vec_eo, vec_wi, fd_setsize);
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv);
#elif EV_SELECT_USE_FD_SET
fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE;
res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
#else
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
#endif
EV_ACQUIRE_CB;
if (expect_false (res < 0))
{
#if EV_SELECT_IS_WINSOCKET
errno = WSAGetLastError ();
#endif
#ifdef WSABASEERR
/* on windows, select returns incompatible error codes, fix this */
if (errno >= WSABASEERR && errno < WSABASEERR + 1000)
if (errno == WSAENOTSOCK)
errno = EBADF;
else
errno -= WSABASEERR;
#endif
#ifdef _WIN32
/* select on windows erroneously returns EINVAL when no fd sets have been
* provided (this is documented). what microsoft doesn't tell you that this bug
* exists even when the fd sets _are_ provided, so we have to check for this bug
* here and emulate by sleeping manually.
* we also get EINVAL when the timeout is invalid, but we ignore this case here
* and assume that EINVAL always means: you have to wait manually.
*/
if (errno == EINVAL)
{
if (timeout)
{
unsigned long ms = timeout * 1e3;
Sleep (ms ? ms : 1);
}
return;
}
#endif
if (errno == EBADF)
fd_ebadf (EV_A);
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
ev_syserr ("(libev) select");
return;
}
#if EV_SELECT_USE_FD_SET
{
int fd;
for (fd = 0; fd < anfdmax; ++fd)
if (anfds [fd].events)
{
int events = 0;
#if EV_SELECT_IS_WINSOCKET
SOCKET handle = anfds [fd].handle;
#else
int handle = fd;
#endif
if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
#ifdef _WIN32
if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;
#endif
if (expect_true (events))
fd_event (EV_A_ fd, events);
}
}
#else
{
int word, bit;
for (word = vec_max; word--; )
{
fd_mask word_r = ((fd_mask *)vec_ro) [word];
fd_mask word_w = ((fd_mask *)vec_wo) [word];
#ifdef _WIN32
word_w |= ((fd_mask *)vec_eo) [word];
#endif
if (word_r || word_w)
for (bit = NFDBITS; bit--; )
{
fd_mask mask = 1UL << bit;
int events = 0;
events |= word_r & mask ? EV_READ : 0;
events |= word_w & mask ? EV_WRITE : 0;
if (expect_true (events))
fd_event (EV_A_ word * NFDBITS + bit, events);
}
}
}
#endif
}
inline_size
int
select_init (EV_P_ int flags)
{
backend_mintime = 1e-6;
backend_modify = select_modify;
backend_poll = select_poll;
#if EV_SELECT_USE_FD_SET
vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);
vec_ro = ev_malloc (sizeof (fd_set));
vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi);
vec_wo = ev_malloc (sizeof (fd_set));
#ifdef _WIN32
vec_eo = ev_malloc (sizeof (fd_set));
#endif
#else
vec_max = 0;
vec_ri = 0;
vec_ro = 0;
vec_wi = 0;
vec_wo = 0;
#ifdef _WIN32
vec_eo = 0;
#endif
#endif
return EVBACKEND_SELECT;
}
inline_size
void
select_destroy (EV_P)
{
ev_free (vec_ri);
ev_free (vec_ro);
ev_free (vec_wi);
ev_free (vec_wo);
#ifdef _WIN32
ev_free (vec_eo);
#endif
}

204
libev/ev_vars.h Normal file
View File

@ -0,0 +1,204 @@
/*
* loop member variable declarations
*
* Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#define VARx(type,name) VAR(name, type name)
VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */
VARx(ev_tstamp, mn_now) /* monotonic clock "now" */
VARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */
/* for reverse feeding of events */
VARx(W *, rfeeds)
VARx(int, rfeedmax)
VARx(int, rfeedcnt)
VAR (pendings, ANPENDING *pendings [NUMPRI])
VAR (pendingmax, int pendingmax [NUMPRI])
VAR (pendingcnt, int pendingcnt [NUMPRI])
VARx(int, pendingpri) /* highest priority currently pending */
VARx(ev_prepare, pending_w) /* dummy pending watcher */
VARx(ev_tstamp, io_blocktime)
VARx(ev_tstamp, timeout_blocktime)
VARx(int, backend)
VARx(int, activecnt) /* total number of active events ("refcount") */
VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */
VARx(int, backend_fd)
VARx(ev_tstamp, backend_mintime) /* assumed typical timer resolution */
VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))
VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout))
VARx(ANFD *, anfds)
VARx(int, anfdmax)
VAR (evpipe, int evpipe [2])
VARx(ev_io, pipe_w)
VARx(EV_ATOMIC_T, pipe_write_wanted)
VARx(EV_ATOMIC_T, pipe_write_skipped)
#if !defined(_WIN32) || EV_GENWRAP
VARx(pid_t, curpid)
#endif
VARx(char, postfork) /* true if we need to recreate kernel state after fork */
#if EV_USE_SELECT || EV_GENWRAP
VARx(void *, vec_ri)
VARx(void *, vec_ro)
VARx(void *, vec_wi)
VARx(void *, vec_wo)
#if defined(_WIN32) || EV_GENWRAP
VARx(void *, vec_eo)
#endif
VARx(int, vec_max)
#endif
#if EV_USE_POLL || EV_GENWRAP
VARx(struct pollfd *, polls)
VARx(int, pollmax)
VARx(int, pollcnt)
VARx(int *, pollidxs) /* maps fds into structure indices */
VARx(int, pollidxmax)
#endif
#if EV_USE_EPOLL || EV_GENWRAP
VARx(struct epoll_event *, epoll_events)
VARx(int, epoll_eventmax)
VARx(int *, epoll_eperms)
VARx(int, epoll_epermcnt)
VARx(int, epoll_epermmax)
#endif
#if EV_USE_KQUEUE || EV_GENWRAP
VARx(pid_t, kqueue_fd_pid)
VARx(struct kevent *, kqueue_changes)
VARx(int, kqueue_changemax)
VARx(int, kqueue_changecnt)
VARx(struct kevent *, kqueue_events)
VARx(int, kqueue_eventmax)
#endif
#if EV_USE_PORT || EV_GENWRAP
VARx(struct port_event *, port_events)
VARx(int, port_eventmax)
#endif
#if EV_USE_IOCP || EV_GENWRAP
VARx(HANDLE, iocp)
#endif
VARx(int *, fdchanges)
VARx(int, fdchangemax)
VARx(int, fdchangecnt)
VARx(ANHE *, timers)
VARx(int, timermax)
VARx(int, timercnt)
#if EV_PERIODIC_ENABLE || EV_GENWRAP
VARx(ANHE *, periodics)
VARx(int, periodicmax)
VARx(int, periodiccnt)
#endif
#if EV_IDLE_ENABLE || EV_GENWRAP
VAR (idles, ev_idle **idles [NUMPRI])
VAR (idlemax, int idlemax [NUMPRI])
VAR (idlecnt, int idlecnt [NUMPRI])
#endif
VARx(int, idleall) /* total number */
VARx(struct ev_prepare **, prepares)
VARx(int, preparemax)
VARx(int, preparecnt)
VARx(struct ev_check **, checks)
VARx(int, checkmax)
VARx(int, checkcnt)
#if EV_FORK_ENABLE || EV_GENWRAP
VARx(struct ev_fork **, forks)
VARx(int, forkmax)
VARx(int, forkcnt)
#endif
#if EV_CLEANUP_ENABLE || EV_GENWRAP
VARx(struct ev_cleanup **, cleanups)
VARx(int, cleanupmax)
VARx(int, cleanupcnt)
#endif
#if EV_ASYNC_ENABLE || EV_GENWRAP
VARx(EV_ATOMIC_T, async_pending)
VARx(struct ev_async **, asyncs)
VARx(int, asyncmax)
VARx(int, asynccnt)
#endif
#if EV_USE_INOTIFY || EV_GENWRAP
VARx(int, fs_fd)
VARx(ev_io, fs_w)
VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */
VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
#endif
VARx(EV_ATOMIC_T, sig_pending)
#if EV_USE_SIGNALFD || EV_GENWRAP
VARx(int, sigfd)
VARx(ev_io, sigfd_w)
VARx(sigset_t, sigfd_set)
#endif
VARx(unsigned int, origflags) /* original loop flags */
#if EV_FEATURE_API || EV_GENWRAP
VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */
VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */
VARx(void *, userdata)
/* C++ doesn't support the ev_loop_callback typedef here. stinks. */
VAR (release_cb, void (*release_cb)(EV_P) EV_THROW)
VAR (acquire_cb, void (*acquire_cb)(EV_P) EV_THROW)
VAR (invoke_cb , ev_loop_callback invoke_cb)
#endif
#undef VARx

162
libev/ev_win32.c Normal file
View File

@ -0,0 +1,162 @@
/*
* libev win32 compatibility cruft (_not_ a backend)
*
* Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifdef _WIN32
/* 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 */
/* for the crt to do something about it */
volatile double SIGFPE_REQ = 0.0f;
static SOCKET
ev_tcp_socket (void)
{
#if EV_USE_WSASOCKET
return WSASocket (AF_INET, SOCK_STREAM, 0, 0, 0, 0);
#else
return socket (AF_INET, SOCK_STREAM, 0);
#endif
}
/* oh, the humanity! */
static int
ev_pipe (int filedes [2])
{
struct sockaddr_in addr = { 0 };
int addr_size = sizeof (addr);
struct sockaddr_in adr2;
int adr2_size = sizeof (adr2);
SOCKET listener;
SOCKET sock [2] = { -1, -1 };
if ((listener = ev_tcp_socket ()) == INVALID_SOCKET)
return -1;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
addr.sin_port = 0;
if (bind (listener, (struct sockaddr *)&addr, addr_size))
goto fail;
if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
goto fail;
if (listen (listener, 1))
goto fail;
if ((sock [0] = ev_tcp_socket ()) == INVALID_SOCKET)
goto fail;
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;
/* windows vista returns fantasy port numbers for sockets:
* example for two interconnected tcp sockets:
*
* (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
* (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
* (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
* (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
*
* wow! tridirectional sockets!
*
* this way of checking ports seems to work:
*/
if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
goto fail;
if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
goto fail;
errno = WSAEINVAL;
if (addr_size != adr2_size
|| addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
|| addr.sin_port != adr2.sin_port)
goto fail;
closesocket (listener);
#if EV_SELECT_IS_WINSOCKET
filedes [0] = EV_WIN32_HANDLE_TO_FD (sock [0]);
filedes [1] = EV_WIN32_HANDLE_TO_FD (sock [1]);
#else
/* when select isn't winsocket, we also expect socket, connect, accept etc.
* to work on fds */
filedes [0] = sock [0];
filedes [1] = sock [1];
#endif
return 0;
fail:
closesocket (listener);
if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
return -1;
}
#undef pipe
#define pipe(filedes) ev_pipe (filedes)
#define EV_HAVE_EV_TIME 1
ev_tstamp
ev_time (void)
{
FILETIME ft;
ULARGE_INTEGER ui;
GetSystemTimeAsFileTime (&ft);
ui.u.LowPart = ft.dwLowDateTime;
ui.u.HighPart = ft.dwHighDateTime;
/* msvc cannot convert ulonglong to double... yes, it is that sucky */
return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7;
}
#endif

200
libev/ev_wrap.h Normal file
View File

@ -0,0 +1,200 @@
/* DO NOT EDIT, automatically generated by update_ev_wrap */
#ifndef EV_WRAP_H
#define EV_WRAP_H
#define acquire_cb ((loop)->acquire_cb)
#define activecnt ((loop)->activecnt)
#define anfdmax ((loop)->anfdmax)
#define anfds ((loop)->anfds)
#define async_pending ((loop)->async_pending)
#define asynccnt ((loop)->asynccnt)
#define asyncmax ((loop)->asyncmax)
#define asyncs ((loop)->asyncs)
#define backend ((loop)->backend)
#define backend_fd ((loop)->backend_fd)
#define backend_mintime ((loop)->backend_mintime)
#define backend_modify ((loop)->backend_modify)
#define backend_poll ((loop)->backend_poll)
#define checkcnt ((loop)->checkcnt)
#define checkmax ((loop)->checkmax)
#define checks ((loop)->checks)
#define cleanupcnt ((loop)->cleanupcnt)
#define cleanupmax ((loop)->cleanupmax)
#define cleanups ((loop)->cleanups)
#define curpid ((loop)->curpid)
#define epoll_epermcnt ((loop)->epoll_epermcnt)
#define epoll_epermmax ((loop)->epoll_epermmax)
#define epoll_eperms ((loop)->epoll_eperms)
#define epoll_eventmax ((loop)->epoll_eventmax)
#define epoll_events ((loop)->epoll_events)
#define evpipe ((loop)->evpipe)
#define fdchangecnt ((loop)->fdchangecnt)
#define fdchangemax ((loop)->fdchangemax)
#define fdchanges ((loop)->fdchanges)
#define forkcnt ((loop)->forkcnt)
#define forkmax ((loop)->forkmax)
#define forks ((loop)->forks)
#define fs_2625 ((loop)->fs_2625)
#define fs_fd ((loop)->fs_fd)
#define fs_hash ((loop)->fs_hash)
#define fs_w ((loop)->fs_w)
#define idleall ((loop)->idleall)
#define idlecnt ((loop)->idlecnt)
#define idlemax ((loop)->idlemax)
#define idles ((loop)->idles)
#define invoke_cb ((loop)->invoke_cb)
#define io_blocktime ((loop)->io_blocktime)
#define iocp ((loop)->iocp)
#define kqueue_changecnt ((loop)->kqueue_changecnt)
#define kqueue_changemax ((loop)->kqueue_changemax)
#define kqueue_changes ((loop)->kqueue_changes)
#define kqueue_eventmax ((loop)->kqueue_eventmax)
#define kqueue_events ((loop)->kqueue_events)
#define kqueue_fd_pid ((loop)->kqueue_fd_pid)
#define loop_count ((loop)->loop_count)
#define loop_depth ((loop)->loop_depth)
#define loop_done ((loop)->loop_done)
#define mn_now ((loop)->mn_now)
#define now_floor ((loop)->now_floor)
#define origflags ((loop)->origflags)
#define pending_w ((loop)->pending_w)
#define pendingcnt ((loop)->pendingcnt)
#define pendingmax ((loop)->pendingmax)
#define pendingpri ((loop)->pendingpri)
#define pendings ((loop)->pendings)
#define periodiccnt ((loop)->periodiccnt)
#define periodicmax ((loop)->periodicmax)
#define periodics ((loop)->periodics)
#define pipe_w ((loop)->pipe_w)
#define pipe_write_skipped ((loop)->pipe_write_skipped)
#define pipe_write_wanted ((loop)->pipe_write_wanted)
#define pollcnt ((loop)->pollcnt)
#define pollidxmax ((loop)->pollidxmax)
#define pollidxs ((loop)->pollidxs)
#define pollmax ((loop)->pollmax)
#define polls ((loop)->polls)
#define port_eventmax ((loop)->port_eventmax)
#define port_events ((loop)->port_events)
#define postfork ((loop)->postfork)
#define preparecnt ((loop)->preparecnt)
#define preparemax ((loop)->preparemax)
#define prepares ((loop)->prepares)
#define release_cb ((loop)->release_cb)
#define rfeedcnt ((loop)->rfeedcnt)
#define rfeedmax ((loop)->rfeedmax)
#define rfeeds ((loop)->rfeeds)
#define rtmn_diff ((loop)->rtmn_diff)
#define sig_pending ((loop)->sig_pending)
#define sigfd ((loop)->sigfd)
#define sigfd_set ((loop)->sigfd_set)
#define sigfd_w ((loop)->sigfd_w)
#define timeout_blocktime ((loop)->timeout_blocktime)
#define timercnt ((loop)->timercnt)
#define timermax ((loop)->timermax)
#define timers ((loop)->timers)
#define userdata ((loop)->userdata)
#define vec_eo ((loop)->vec_eo)
#define vec_max ((loop)->vec_max)
#define vec_ri ((loop)->vec_ri)
#define vec_ro ((loop)->vec_ro)
#define vec_wi ((loop)->vec_wi)
#define vec_wo ((loop)->vec_wo)
#else
#undef EV_WRAP_H
#undef acquire_cb
#undef activecnt
#undef anfdmax
#undef anfds
#undef async_pending
#undef asynccnt
#undef asyncmax
#undef asyncs
#undef backend
#undef backend_fd
#undef backend_mintime
#undef backend_modify
#undef backend_poll
#undef checkcnt
#undef checkmax
#undef checks
#undef cleanupcnt
#undef cleanupmax
#undef cleanups
#undef curpid
#undef epoll_epermcnt
#undef epoll_epermmax
#undef epoll_eperms
#undef epoll_eventmax
#undef epoll_events
#undef evpipe
#undef fdchangecnt
#undef fdchangemax
#undef fdchanges
#undef forkcnt
#undef forkmax
#undef forks
#undef fs_2625
#undef fs_fd
#undef fs_hash
#undef fs_w
#undef idleall
#undef idlecnt
#undef idlemax
#undef idles
#undef invoke_cb
#undef io_blocktime
#undef iocp
#undef kqueue_changecnt
#undef kqueue_changemax
#undef kqueue_changes
#undef kqueue_eventmax
#undef kqueue_events
#undef kqueue_fd_pid
#undef loop_count
#undef loop_depth
#undef loop_done
#undef mn_now
#undef now_floor
#undef origflags
#undef pending_w
#undef pendingcnt
#undef pendingmax
#undef pendingpri
#undef pendings
#undef periodiccnt
#undef periodicmax
#undef periodics
#undef pipe_w
#undef pipe_write_skipped
#undef pipe_write_wanted
#undef pollcnt
#undef pollidxmax
#undef pollidxs
#undef pollmax
#undef polls
#undef port_eventmax
#undef port_events
#undef postfork
#undef preparecnt
#undef preparemax
#undef prepares
#undef release_cb
#undef rfeedcnt
#undef rfeedmax
#undef rfeeds
#undef rtmn_diff
#undef sig_pending
#undef sigfd
#undef sigfd_set
#undef sigfd_w
#undef timeout_blocktime
#undef timercnt
#undef timermax
#undef timers
#undef userdata
#undef vec_eo
#undef vec_max
#undef vec_ri
#undef vec_ro
#undef vec_wi
#undef vec_wo
#endif

425
libev/event.c Normal file
View File

@ -0,0 +1,425 @@
/*
* libevent compatibility layer
*
* Copyright (c) 2007,2008,2009,2010,2012 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#ifdef EV_EVENT_H
# include EV_EVENT_H
#else
# include "event.h"
#endif
#if EV_MULTIPLICITY
# define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
# define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
#else
# define dLOOPev
# define dLOOPbase
#endif
/* never accessed, will always be cast from/to ev_loop */
struct event_base
{
int dummy;
};
static struct event_base *ev_x_cur;
static ev_tstamp
ev_tv_get (struct timeval *tv)
{
if (tv)
{
ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6;
return after ? after : 1e-6;
}
else
return -1.;
}
#define EVENT_STRINGIFY(s) # s
#define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b)
const char *
event_get_version (void)
{
/* returns ABI, not API or library, version */
return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
}
const char *
event_get_method (void)
{
return "libev";
}
void *event_init (void)
{
#if EV_MULTIPLICITY
if (ev_x_cur)
ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
else
ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
#else
assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur));
ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
#endif
return ev_x_cur;
}
const char *
event_base_get_method (const struct event_base *base)
{
return "libev";
}
struct event_base *
event_base_new (void)
{
#if EV_MULTIPLICITY
return (struct event_base *)ev_loop_new (EVFLAG_AUTO);
#else
assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY"));
return NULL;
#endif
}
void event_base_free (struct event_base *base)
{
dLOOPbase;
#if EV_MULTIPLICITY
if (!ev_is_default_loop (loop))
ev_loop_destroy (loop);
#endif
}
int event_dispatch (void)
{
return event_base_dispatch (ev_x_cur);
}
#ifdef EV_STANDALONE
void event_set_log_callback (event_log_cb cb)
{
/* nop */
}
#endif
int event_loop (int flags)
{
return event_base_loop (ev_x_cur, flags);
}
int event_loopexit (struct timeval *tv)
{
return event_base_loopexit (ev_x_cur, tv);
}
event_callback_fn event_get_callback
(const struct event *ev)
{
return ev->ev_callback;
}
static void
ev_x_cb (struct event *ev, int revents)
{
revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL;
ev->ev_res = revents;
ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
}
static void
ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents)
{
struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
if (revents & EV_ERROR)
event_del (ev);
ev_x_cb (ev, revents);
}
static void
ev_x_cb_io (EV_P_ struct ev_io *w, int revents)
{
struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
event_del (ev);
ev_x_cb (ev, revents);
}
static void
ev_x_cb_to (EV_P_ struct ev_timer *w, int revents)
{
struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
event_del (ev);
ev_x_cb (ev, revents);
}
void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
{
if (events & EV_SIGNAL)
ev_init (&ev->iosig.sig, ev_x_cb_sig);
else
ev_init (&ev->iosig.io, ev_x_cb_io);
ev_init (&ev->to, ev_x_cb_to);
ev->ev_base = ev_x_cur; /* not threadsafe, but it's how libevent works */
ev->ev_fd = fd;
ev->ev_events = events;
ev->ev_pri = 0;
ev->ev_callback = cb;
ev->ev_arg = arg;
ev->ev_res = 0;
ev->ev_flags = EVLIST_INIT;
}
int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
{
return event_base_once (ev_x_cur, fd, events, cb, arg, tv);
}
int event_add (struct event *ev, struct timeval *tv)
{
dLOOPev;
if (ev->ev_events & EV_SIGNAL)
{
if (!ev_is_active (&ev->iosig.sig))
{
ev_signal_set (&ev->iosig.sig, ev->ev_fd);
ev_signal_start (EV_A_ &ev->iosig.sig);
ev->ev_flags |= EVLIST_SIGNAL;
}
}
else if (ev->ev_events & (EV_READ | EV_WRITE))
{
if (!ev_is_active (&ev->iosig.io))
{
ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
ev_io_start (EV_A_ &ev->iosig.io);
ev->ev_flags |= EVLIST_INSERTED;
}
}
if (tv)
{
ev->to.repeat = ev_tv_get (tv);
ev_timer_again (EV_A_ &ev->to);
ev->ev_flags |= EVLIST_TIMEOUT;
}
else
{
ev_timer_stop (EV_A_ &ev->to);
ev->ev_flags &= ~EVLIST_TIMEOUT;
}
ev->ev_flags |= EVLIST_ACTIVE;
return 0;
}
int event_del (struct event *ev)
{
dLOOPev;
if (ev->ev_events & EV_SIGNAL)
ev_signal_stop (EV_A_ &ev->iosig.sig);
else if (ev->ev_events & (EV_READ | EV_WRITE))
ev_io_stop (EV_A_ &ev->iosig.io);
if (ev_is_active (&ev->to))
ev_timer_stop (EV_A_ &ev->to);
ev->ev_flags = EVLIST_INIT;
return 0;
}
void event_active (struct event *ev, int res, short ncalls)
{
dLOOPev;
if (res & EV_TIMEOUT)
ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
if (res & EV_SIGNAL)
ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
if (res & (EV_READ | EV_WRITE))
ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
}
int event_pending (struct event *ev, short events, struct timeval *tv)
{
short revents = 0;
dLOOPev;
if (ev->ev_events & EV_SIGNAL)
{
/* sig */
if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
revents |= EV_SIGNAL;
}
else if (ev->ev_events & (EV_READ | EV_WRITE))
{
/* io */
if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
revents |= ev->ev_events & (EV_READ | EV_WRITE);
}
if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
{
revents |= EV_TIMEOUT;
if (tv)
{
ev_tstamp at = ev_now (EV_A);
tv->tv_sec = (long)at;
tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
}
}
return events & revents;
}
int event_priority_init (int npri)
{
return event_base_priority_init (ev_x_cur, npri);
}
int event_priority_set (struct event *ev, int pri)
{
ev->ev_pri = pri;
return 0;
}
int event_base_set (struct event_base *base, struct event *ev)
{
ev->ev_base = base;
return 0;
}
int event_base_loop (struct event_base *base, int flags)
{
dLOOPbase;
return !ev_run (EV_A_ flags);
}
int event_base_dispatch (struct event_base *base)
{
return event_base_loop (base, 0);
}
static void
ev_x_loopexit_cb (int revents, void *base)
{
dLOOPbase;
ev_break (EV_A_ EVBREAK_ONE);
}
int event_base_loopexit (struct event_base *base, struct timeval *tv)
{
ev_tstamp after = ev_tv_get (tv);
dLOOPbase;
ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base);
return 0;
}
struct ev_x_once
{
int fd;
void (*cb)(int, short, void *);
void *arg;
};
static void
ev_x_once_cb (int revents, void *arg)
{
struct ev_x_once *once = (struct ev_x_once *)arg;
once->cb (once->fd, (short)revents, once->arg);
free (once);
}
int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
{
struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once));
dLOOPbase;
if (!once)
return -1;
once->fd = fd;
once->cb = cb;
once->arg = arg;
ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once);
return 0;
}
int event_base_priority_init (struct event_base *base, int npri)
{
/*dLOOPbase;*/
return 0;
}

177
libev/event.h Normal file
View File

@ -0,0 +1,177 @@
/*
* libevent compatibility header, only core events supported
*
* Copyright (c) 2007,2008,2010,2012 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef EVENT_H_
#define EVENT_H_
#ifdef EV_H
# include EV_H
#else
# include "ev.h"
#endif
#ifndef EVLOOP_NONBLOCK
# define EVLOOP_NONBLOCK EVRUN_NOWAIT
#endif
#ifndef EVLOOP_ONESHOT
# define EVLOOP_ONESHOT EVRUN_ONCE
#endif
#ifndef EV_TIMEOUT
# define EV_TIMEOUT EV_TIMER
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* we need sys/time.h for struct timeval only */
#if !defined (WIN32) || defined (__MINGW32__)
# include <time.h> /* mingw seems to need this, for whatever reason */
# include <sys/time.h>
#endif
struct event_base;
#define EVLIST_TIMEOUT 0x01
#define EVLIST_INSERTED 0x02
#define EVLIST_SIGNAL 0x04
#define EVLIST_ACTIVE 0x08
#define EVLIST_INTERNAL 0x10
#define EVLIST_INIT 0x80
typedef void (*event_callback_fn)(int, short, void *);
struct event
{
/* libev watchers we map onto */
union {
struct ev_io io;
struct ev_signal sig;
} iosig;
struct ev_timer to;
/* compatibility slots */
struct event_base *ev_base;
event_callback_fn ev_callback;
void *ev_arg;
int ev_fd;
int ev_pri;
int ev_res;
int ev_flags;
short ev_events;
};
event_callback_fn event_get_callback (const struct event *ev);
#define EV_READ EV_READ
#define EV_WRITE EV_WRITE
#define EV_PERSIST 0x10
#define EV_ET 0x20 /* nop */
#define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd)
#define EVENT_FD(ev) ((int) (ev)->ev_fd)
#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
#define evtimer_add(ev,tv) event_add (ev, tv)
#define evtimer_set(ev,cb,data) event_set (ev, -1, 0, cb, data)
#define evtimer_del(ev) event_del (ev)
#define evtimer_pending(ev,tv) event_pending (ev, EV_TIMEOUT, tv)
#define evtimer_initialized(ev) event_initialized (ev)
#define timeout_add(ev,tv) evtimer_add (ev, tv)
#define timeout_set(ev,cb,data) evtimer_set (ev, cb, data)
#define timeout_del(ev) evtimer_del (ev)
#define timeout_pending(ev,tv) evtimer_pending (ev, tv)
#define timeout_initialized(ev) evtimer_initialized (ev)
#define signal_add(ev,tv) event_add (ev, tv)
#define signal_set(ev,sig,cb,data) event_set (ev, sig, EV_SIGNAL | EV_PERSIST, cb, data)
#define signal_del(ev) event_del (ev)
#define signal_pending(ev,tv) event_pending (ev, EV_SIGNAL, tv)
#define signal_initialized(ev) event_initialized (ev)
const char *event_get_version (void);
const char *event_get_method (void);
void *event_init (void);
void event_base_free (struct event_base *base);
#define EVLOOP_ONCE EVLOOP_ONESHOT
int event_loop (int);
int event_loopexit (struct timeval *tv);
int event_dispatch (void);
#define _EVENT_LOG_DEBUG 0
#define _EVENT_LOG_MSG 1
#define _EVENT_LOG_WARN 2
#define _EVENT_LOG_ERR 3
typedef void (*event_log_cb)(int severity, const char *msg);
void event_set_log_callback(event_log_cb cb);
void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg);
int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv);
int event_add (struct event *ev, struct timeval *tv);
int event_del (struct event *ev);
void event_active (struct event *ev, int res, short ncalls); /* ncalls is being ignored */
int event_pending (struct event *ev, short, struct timeval *tv);
int event_priority_init (int npri);
int event_priority_set (struct event *ev, int pri);
struct event_base *event_base_new (void);
const char *event_base_get_method (const struct event_base *);
int event_base_set (struct event_base *base, struct event *ev);
int event_base_loop (struct event_base *base, int);
int event_base_loopexit (struct event_base *base, struct timeval *tv);
int event_base_dispatch (struct event_base *base);
int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv);
int event_base_priority_init (struct event_base *base, int fd);
/* next line is different in the libevent+libev version */
/*libevent-include*/
#ifdef __cplusplus
}
#endif
#endif

226
libev/event_compat.h Normal file
View File

@ -0,0 +1,226 @@
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2008 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
typedef unsigned char u_char;
typedef unsigned short u_short;
#else
# include <sys/types.h>
# include <sys/time.h>
# include <inttypes.h>
#endif
#include <stdarg.h>
/* Fix so that ppl dont have to run with <sys/queue.h> */
#ifndef TAILQ_ENTRY
#define _EVENT_DEFINED_TQENTRY
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
#endif /* !TAILQ_ENTRY */
#ifndef RB_ENTRY
#define _EVENT_DEFINED_RBENTRY
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
int rbe_color; /* node color */ \
}
#endif /* !RB_ENTRY */
/*
* Key-Value pairs. Can be used for HTTP headers but also for
* query argument parsing.
*/
struct evkeyval {
TAILQ_ENTRY(evkeyval) next;
char *key;
char *value;
};
#ifdef _EVENT_DEFINED_TQENTRY
#undef TAILQ_ENTRY
struct event_list;
struct evkeyvalq;
#undef _EVENT_DEFINED_TQENTRY
#else
TAILQ_HEAD (event_list, event);
TAILQ_HEAD (evkeyvalq, evkeyval);
#endif /* _EVENT_DEFINED_TQENTRY */
#ifdef _EVENT_DEFINED_RBENTRY
#undef RB_ENTRY
#undef _EVENT_DEFINED_RBENTRY
#endif /* _EVENT_DEFINED_RBENTRY */
struct eventop {
char *name;
void *(*init)(struct event_base *);
int (*add)(void *, struct event *);
int (*del)(void *, struct event *);
int (*recalc)(struct event_base *, void *, int);
int (*dispatch)(struct event_base *, void *, struct timeval *);
void (*dealloc)(struct event_base *, void *);
};
/* These functions deal with buffering input and output */
struct evbuffer {
u_char *buffer;
u_char *orig_buffer;
size_t misalign;
size_t totallen;
size_t off;
void (*cb)(struct evbuffer *, size_t, size_t, void *);
void *cbarg;
};
/* Just for error reporting - use other constants otherwise */
#define EVBUFFER_READ 0x01
#define EVBUFFER_WRITE 0x02
#define EVBUFFER_EOF 0x10
#define EVBUFFER_ERROR 0x20
#define EVBUFFER_TIMEOUT 0x40
struct bufferevent;
typedef void (*evbuffercb)(struct bufferevent *, void *);
typedef void (*everrorcb)(struct bufferevent *, short what, void *);
struct event_watermark {
size_t low;
size_t high;
};
struct bufferevent {
struct event ev_read;
struct event ev_write;
struct evbuffer *input;
struct evbuffer *output;
struct event_watermark wm_read;
struct event_watermark wm_write;
evbuffercb readcb;
evbuffercb writecb;
everrorcb errorcb;
void *cbarg;
int timeout_read; /* in seconds */
int timeout_write; /* in seconds */
short enabled; /* events that are currently enabled */
};
struct bufferevent *bufferevent_new(int fd,
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev);
int bufferevent_priority_set(struct bufferevent *bufev, int pri);
void bufferevent_free(struct bufferevent *bufev);
int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
int bufferevent_enable(struct bufferevent *bufev, short event);
int bufferevent_disable(struct bufferevent *bufev, short event);
void bufferevent_settimeout(struct bufferevent *bufev,
int timeout_read, int timeout_write);
#define EVBUFFER_LENGTH(x) (x)->off
#define EVBUFFER_DATA(x) (x)->buffer
#define EVBUFFER_INPUT(x) (x)->input
#define EVBUFFER_OUTPUT(x) (x)->output
struct evbuffer *evbuffer_new(void);
void evbuffer_free(struct evbuffer *);
int evbuffer_expand(struct evbuffer *, size_t);
int evbuffer_add(struct evbuffer *, const void *, size_t);
int evbuffer_remove(struct evbuffer *, void *, size_t);
char *evbuffer_readline(struct evbuffer *);
int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
int evbuffer_add_printf(struct evbuffer *, const char *fmt, ...);
int evbuffer_add_vprintf(struct evbuffer *, const char *fmt, va_list ap);
void evbuffer_drain(struct evbuffer *, size_t);
int evbuffer_write(struct evbuffer *, int);
int evbuffer_read(struct evbuffer *, int, int);
u_char *evbuffer_find(struct evbuffer *, const u_char *, size_t);
void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *);
/*
* Marshaling tagged data - We assume that all tags are inserted in their
* numeric order - so that unknown tags will always be higher than the
* known ones - and we can just ignore the end of an event buffer.
*/
void evtag_init(void);
void evtag_marshal(struct evbuffer *evbuf, uint32_t tag, const void *data,
uint32_t len);
void encode_int(struct evbuffer *evbuf, uint32_t number);
void evtag_marshal_int(struct evbuffer *evbuf, uint32_t tag, uint32_t integer);
void evtag_marshal_string(struct evbuffer *buf, uint32_t tag,
const char *string);
void evtag_marshal_timeval(struct evbuffer *evbuf, uint32_t tag,
struct timeval *tv);
int evtag_unmarshal(struct evbuffer *src, uint32_t *ptag, struct evbuffer *dst);
int evtag_peek(struct evbuffer *evbuf, uint32_t *ptag);
int evtag_peek_length(struct evbuffer *evbuf, uint32_t *plength);
int evtag_payload_length(struct evbuffer *evbuf, uint32_t *plength);
int evtag_consume(struct evbuffer *evbuf);
int evtag_unmarshal_int(struct evbuffer *evbuf, uint32_t need_tag,
uint32_t *pinteger);
int evtag_unmarshal_fixed(struct evbuffer *src, uint32_t need_tag, void *data,
size_t len);
int evtag_unmarshal_string(struct evbuffer *evbuf, uint32_t need_tag,
char **pstring);
int evtag_unmarshal_timeval(struct evbuffer *evbuf, uint32_t need_tag,
struct timeval *ptv);
#ifdef __cplusplus
}
#endif

131
libev/import_libevent Executable file
View File

@ -0,0 +1,131 @@
#!/bin/sh
LE=../libevent-1.4.3-stable
if ! [ -e evbuffer.c ]; then
echo do not run this programm unless you know what you are doing
exit 1
fi
# this program combines libev and libevent into a single package
cvs update -AdP libev
rsync -avP libev/. . --exclude CVS
rm -f configure.ac
cp $LE/evdns.h .
perl -i -pe 's%^/.libevent-include./%#include "event_compat.h"%' event.h
perl -ne '
s/\s+char buf\[64\];/\tchar buf[96];/;
if (/#include "event.h"/) {
print "#ifndef EV_STANDALONE\n$_#endif\n";
next;
}
if (/#include "misc.h"/) {
print "#ifndef EV_STANDALONE\n$_#endif\n";
next;
}
if (/#include "(unistd.h|sys\/time.h)"/) {
print "#ifndef WIN32\n$_#endif\n";
next;
}
next if /#include "log.h"/;
print;
' <$LE/evdns.c >evdns.c
cp $LE/autogen.sh .
cp $LE/epoll_sub.c .
cp $LE/evbuffer.c .
cp $LE/buffer.c .
cp $LE/evhttp.h .
cp $LE/evutil.h .
cp $LE/evutil.c .
cp $LE/event-config.h .
cp $LE/event-internal.h .
cp $LE/evrpc.h .
cp $LE/evrpc.c .
cp $LE/evrpc-internal.h .
cp $LE/http.c .
cp $LE/event_tagging.c .
cp $LE/http-internal.h .
cp $LE/strlcpy-internal.h .
cp $LE/log.c .
cp $LE/log.h .
cp $LE/strlcpy.c .
rsync -a $LE/WIN32* $LE/sample $LE/test $LE/compat . --del
#rename 's/libevent/libev/' WIN32-Prj/lib*
cp $LE/aclocal.m4 .
#cp $LE/acconfig.h .
cp $LE/config.h.in .
cp $LE/event_rpcgen.py .
cp $LE/*.3 .
#perl -i -pe 's/libevent/libev/g' sample/Makefile.am
#perl -i -pe 's/libevent/libev/g' test/Makefile.am
perl -i -pe 's/#include <event.h>$/#include "event.h"/' test/*.c
perl -i -ne '
next if /"event-internal.h"/;
s/base\d?->sig.ev_signal_added/0/;
s/base\d?->sig.ev_signal_pair\[0\]/-1/;
s/base->sig.evsignal_caught/0/;
next if /^\ttest_signal_(dealloc|pipeloss|switchbase|assert|restore)\(\)/;
next if /^\ttest_simplesignal\(\)/; # non-default-loop
next if /^\ttest_immediatesignal\(\)/; # non-default-loop
next if /test_priorities\(\d\)/;
print;
' test/regress.c
perl -ne '
s/\bmin_heap.h\b//g;
s/\bsignal.c\b//g;
s/\bevport.c\b//g;
s/\bkqueue.c\b//g;
s/\bdevpoll.c\b//g;
s/\brtsig.c\b//g;
s/\bselect.c\b//g;
s/\bpoll.c\b//g;
s/\bepoll.c\b//g;
s/\bepoll_sub.c\b//g;
s/\bevent-internal.h\b//g;
s/\bevsignal.h\b//g;
s/^(man_MANS\s*=)/$1 ev.3 /;
s/^(EXTRA_DIST\s*=)/$1 libev.m4 ev.h ev_vars.h ev_wrap.h event_compat.h ev++.h ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c ev.3 ev.pod /;
s/^(include_HEADERS\s*=)/$1 ev.h event_compat.h ev++.h /;
s/^(CORE_SRC\s*=)/$1 ev.c /;
s/^(SYS_LIBS\s*=)/$1 -lm /;
#s/libevent/libev/g;
print;
' <$LE/Makefile.am >Makefile.am
perl -ne '
#s/-Wall/-Wall -Wno-comment -Wunused-function -Wno-unused-value/;
s/-Wall//g;
#s/libevent/libev/g;
#VERSION
s/AM_INIT_AUTOMAKE\s*\(.*,(.*)\)/AM_INIT_AUTOMAKE(libevent-$1+libev,3.1)/;
s/AC_LIBOBJ\(select\)/: ;/g;
s/AC_LIBOBJ\(poll\)/: ;/g;
s/AC_LIBOBJ\(kqueue\)/: ;/g;
s/AC_LIBOBJ\(epoll\)/: ;/g;
s/AC_LIBOBJ\(devpoll\)/: ;/g;
s/AC_LIBOBJ\(evport\)/: ;/g;
s/AC_LIBOBJ\(signal\)/: ;/g;
s/AC_LIBOBJ\(rtsig\)/: ;/g;
print "m4_include([libev.m4])\n" if /^AC_OUTPUT/;
print;
' <$LE/configure.in >configure.in
aclocal-1.7
automake-1.7 --add-missing
autoconf
autoheader
libtoolize
CC="ccache gcc" ./configure --prefix=/opt/libev --disable-shared "$@"

42
libev/libev.m4 Normal file
View File

@ -0,0 +1,42 @@
dnl this file is part of libev, do not make local modifications
dnl http://software.schmorp.de/pkg/libev
dnl libev support
AC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h port.h poll.h sys/select.h sys/eventfd.h sys/signalfd.h)
AC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd signalfd)
AC_CHECK_FUNCS(clock_gettime, [], [
dnl on linux, try syscall wrapper first
if test $(uname) = Linux; then
AC_MSG_CHECKING(for clock_gettime syscall)
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[#include <unistd.h>
#include <sys/syscall.h>
#include <time.h>],
[struct timespec ts; int status = syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts)])],
[ac_have_clock_syscall=1
AC_DEFINE(HAVE_CLOCK_SYSCALL, 1, Define to 1 to use the syscall interface for clock_gettime)
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)])
fi
if test -z "$LIBEV_M4_AVOID_LIBRT" && test -z "$ac_have_clock_syscall"; then
AC_CHECK_LIB(rt, clock_gettime)
unset ac_cv_func_clock_gettime
AC_CHECK_FUNCS(clock_gettime)
fi
])
AC_CHECK_FUNCS(nanosleep, [], [
if test -z "$LIBEV_M4_AVOID_LIBRT"; then
AC_CHECK_LIB(rt, nanosleep)
unset ac_cv_func_nanosleep
AC_CHECK_FUNCS(nanosleep)
fi
])
if test -z "$LIBEV_M4_AVOID_LIBM"; then
LIBM=m
fi
AC_SEARCH_LIBS(floor, $LIBM, [AC_DEFINE(HAVE_FLOOR, 1, Define to 1 if the floor function is available)])

8
libev/update_ev_c Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh -e
(
sed -ne '1,\%/\* ECB.H BEGIN \*/%p' ev.c
cat ~/src/libecb/ecb.h
sed -ne '\%/\* ECB.H END \*/%,$p' ev.c
) >ev.c~ && mv ev.c~ ev.c

19
libev/update_ev_wrap Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
(
echo '#define VAR(name,decl) name'
echo '#define EV_GENWRAP 1'
cat ev_vars.h
) | cc -E -o - - | perl -ne '
while (<>) {
push @syms, $1 if /(^\w+)/;
}
print "/* DO NOT EDIT, automatically generated by update_ev_wrap */\n",
"#ifndef EV_WRAP_H\n",
"#define EV_WRAP_H\n",
(map "#define $_ ((loop)->$_)\n", sort @syms),
"#else\n",
"#undef EV_WRAP_H\n",
(map "#undef $_\n", sort @syms),
"#endif\n";
' >ev_wrap.h

7
libev/update_symbols Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
make ev.o event.o || exit
nm ev.o | perl -ne 'print "$1\n" if /\S+ [A-Z] (\S+)/' > Symbols.ev
nm event.o | perl -ne 'print "$1\n" if /\S+ [A-Z] (\S+)/' > Symbols.event

View File

@ -10,7 +10,7 @@ cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT}
COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread
COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread my_ev.cpp -isystem libev
SOURCES= $(COMMON) lib/aes_faster_c/aes.cpp lib/aes_faster_c/wrapper.cpp
SOURCES_TINY_AES= $(COMMON) lib/aes.c
SOURCES_AES_ACC=$(COMMON) $(wildcard lib/aes_acc/aes*.c)

16
my_ev.cpp Normal file
View File

@ -0,0 +1,16 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wcomment"
#pragma GCC diagnostic ignored "-Wparentheses"
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#pragma GCC diagnostic ignored "-Wunused-value"
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-W"
#include "my_ev_common.h"
#include "ev.c"
#pragma GCC diagnostic pop

5
my_ev.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "my_ev_common.h"
#include "ev.h"

18
my_ev_common.h Normal file
View File

@ -0,0 +1,18 @@
#define EV_STANDALONE 1
#define EV_COMMON void *data; unsigned long long u64;
#define EV_COMPAT3 0
//#include <wepoll.h>
#if defined(__MINGW32__)
//#define EV_USE_SELECT 1
//#define EV_SELECT_IS_WINSOCKET 1
# define EV_FD_TO_WIN32_HANDLE(fd) (fd)
# define EV_WIN32_HANDLE_TO_FD(handle) (handle)
# define EV_WIN32_CLOSE_FD(fd) closesocket (fd)
# define FD_SETSIZE 4096
#endif
//#define EV_VERIFY 2