diff --git a/Makefile b/Makefile index 094b510..99e7ec5 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,23 @@ +include cflags.mk SUBDIRS=lib bin +config all clean install maintainer-clean: + for d in $(SUBDIRS); do ( cd $$d && $(MAKE) $@) || exit 1 ; done + if [ "$@" = "all" -o "$@" = "install" ] ; then $(MAKE) $@-extra ; fi + #if [ "$@" = "all" ] ; then rm -f version.extended ; $(MAKE) version.extended ; fi easy_start: config all -config: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) config ) ; done +.PHONY: version.extended -all: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done +all-extra: version.extended -clean: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) clean ) ; done - -install: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) install ) ; done +install-extra: + mkdir -p ${UINET_DESTDIR}/etc/libuinet + cp version.extended ${UINET_DESTDIR}/etc/libuinet/version.extended +version.extended: + echo "buildroot: ${CURDIR}" > $@ + echo "date: `date`" >> $@ + echo "git-sha: `git rev-parse --short HEAD`" >> $@ + echo "git-branch: `git rev-parse --abbrev-ref HEAD`" >> $@ diff --git a/bin/Makefile b/bin/Makefile index 955c4fd..f898b66 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -6,15 +6,5 @@ ifeq (${HOST_OS},FreeBSD) SUBDIRS+=sysctl vmstat endif -config: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) config ) ; done - -all: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done - -clean: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) clean ) ; done - -install: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) install ) ; done - +config all clean install maintainer-clean: + for d in $(SUBDIRS); do ( cd $$d && $(MAKE) $@) || exit 1 ; done diff --git a/bin/echo/Makefile b/bin/echo/Makefile index db95d9f..c610a8b 100644 --- a/bin/echo/Makefile +++ b/bin/echo/Makefile @@ -2,10 +2,9 @@ TOPDIR?=${CURDIR}/../.. include ${TOPDIR}/cflags.mk PROG=echo - UINET_LIBS=uinet - CFLAGS= -I${TOPDIR}/lib/libev + LDADD= -L${UINET_DESTDIR}/lib/ ${TOPDIR}/lib/libev/.libs/libev.a -lm -lpcap include ${TOPDIR}/mk/prog.mk diff --git a/bin/passive/Makefile b/bin/passive/Makefile index 9d5281f..7e26e97 100644 --- a/bin/passive/Makefile +++ b/bin/passive/Makefile @@ -11,15 +11,15 @@ UINET_LIBES+=uinetnv endif -CFLAGS= -I${TOPDIR}/lib/libev -ifeq (${HOST_OS},FreeBSD) -CFLAGS+= -I${TOPDIR}/lib/libnv -endif -LDADD= -L${UINET_DESTDIR}/lib/ ${TOPDIR}/lib/libev/.libs/libev.a -lm -lpcap +CFLAGS+= -I${TOPDIR}/lib/libuinetnv -I${TOPDIR}/lib/libev +LDADD= -L${UINET_DESTDIR}/lib/ ${TOPDIR}/lib/libev/.libs/libev.a ${TOPDIR}/lib/libuinetnv/libuinetnv.a -lm -lpcap ifndef NO_EXTRACT CFLAGS+= -I${TOPDIR}/lib/libhttp_parser -DENABLE_EXTRACT LDADD+= -L${TOPDIR}/lib/libhttp_parser -lhttp_parser -lz endif +maintainer-clean: + $(MAKE) clean + include ${TOPDIR}/mk/prog.mk diff --git a/bin/passive/passive.c b/bin/passive/passive.c index 9b0aaad..c78fd58 100644 --- a/bin/passive/passive.c +++ b/bin/passive/passive.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef ENABLE_EXTRACT #include #endif @@ -39,6 +40,8 @@ #include #include "uinet_api.h" +#include "uinet_host_sysctl_api.h" +#include "uinet_host_sysctl_api_priv.h" #ifdef ENABLE_EXTRACT #include "http_parser.h" @@ -1250,6 +1253,7 @@ int main (int argc, char **argv) struct uinet_in_addr tmpinaddr; int ifnetmap_count = 0; int ifpcap_count = 0; + pthread_t sysctl_thr; struct content_type *contype; memset(interfaces, 0, sizeof(interfaces)); @@ -1517,6 +1521,12 @@ int main (int argc, char **argv) interface_thread_start, &interfaces[i]); } + error = pthread_create(&sysctl_thr, NULL, + uinet_host_sysctl_listener_thread, NULL); + if (error != 0) { + printf("Failed to bring up sysctl thread: %d\n", errno); + } + for (i = 0; i < num_interfaces; i++) { if (0 == interfaces[i].thread_create_result) pthread_join(interfaces[i].thread, NULL); @@ -1524,5 +1534,8 @@ int main (int argc, char **argv) uinet_shutdown(0); + /* XXX only do this if we successfully started the thread! */ + pthread_join(sysctl_thr, NULL); + return (0); } diff --git a/bin/sysctl/Makefile b/bin/sysctl/Makefile index b06f101..f48decf 100644 --- a/bin/sysctl/Makefile +++ b/bin/sysctl/Makefile @@ -1,4 +1,5 @@ TOPDIR?=${CURDIR}/../.. +include ${TOPDIR}/cflags.mk PROG=sysctl diff --git a/bin/vmstat/Makefile b/bin/vmstat/Makefile index 168d718..a1407df 100644 --- a/bin/vmstat/Makefile +++ b/bin/vmstat/Makefile @@ -1,4 +1,5 @@ TOPDIR?=${CURDIR}/../.. +include ${TOPDIR}/cflags.mk PROG=vmstat diff --git a/cflags.mk b/cflags.mk index df91959..b1bead8 100644 --- a/cflags.mk +++ b/cflags.mk @@ -4,6 +4,9 @@ DEBUG_FLAGS ?= -O -gdwarf-2 UINET_DESTDIR ?= /usr/local/ +#CFLAGS+= -fPIC +#LDFLAGS+= -fPIC + UINET_INSTALL ?= install UINET_INSTALL_DIR ?= $(UINET_INSTALL) -m 0755 UINET_INSTALL_LIB ?= $(UINET_INSTALL) -m 0644 diff --git a/lib.mk b/lib.mk index b930e1a..8fe71f5 100644 --- a/lib.mk +++ b/lib.mk @@ -9,3 +9,6 @@ LDADD+= -lcrypto else LDADD+= -lssl endif +ifeq "${OSNAME}" "FreeBSD" +LDADD+= -lcrypto +endif diff --git a/lib/Makefile b/lib/Makefile index e6a4a07..f0bac97 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,13 +11,7 @@ default: all config: (cd libev ; env CFLAGS="${DEBUG_FLAGS}" ./configure --with-uinet=../libuinet/api_include --prefix="${UINET_DESTDIR}" --includedir="${UINET_DESTDIR}/include/libev" --enable-shared=no ) -all: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done - -clean: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) clean ) ; done - -install: - for d in $(SUBDIRS); do ( cd $$d; $(MAKE) install ) ; done +all clean install maintainer-clean: + for d in $(SUBDIRS); do ( cd $$d && $(MAKE) $@ ) || exit 1 ; done default: config all diff --git a/lib/libev/ev.3 b/lib/libev/ev.3 deleted file mode 100644 index bb8501b..0000000 --- a/lib/libev/ev.3 +++ /dev/null @@ -1,5626 +0,0 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LIBEV 3" -.TH LIBEV 3 "2013-02-28" "libev-4.11" "libev - high performance full featured event loop" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -libev \- a high performance full\-featured event loop written in C -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -.Vb 1 -\& #include -.Ve -.SS "\s-1EXAMPLE\s0 \s-1PROGRAM\s0" -.IX Subsection "EXAMPLE PROGRAM" -.Vb 2 -\& // a single header file is required -\& #include -\& -\& #include // for puts -\& -\& // every watcher type has its own typedef\*(Aqd struct -\& // with the name ev_TYPE -\& ev_io stdin_watcher; -\& ev_timer timeout_watcher; -\& -\& // all watcher callbacks have a similar signature -\& // this callback is called when data is readable on stdin -\& static void -\& stdin_cb (EV_P_ ev_io *w, int revents) -\& { -\& puts ("stdin ready"); -\& // for one\-shot events, one must manually stop the watcher -\& // with its corresponding stop function. -\& ev_io_stop (EV_A_ w); -\& -\& // this causes all nested ev_run\*(Aqs to stop iterating -\& ev_break (EV_A_ EVBREAK_ALL); -\& } -\& -\& // another callback, this time for a time\-out -\& static void -\& timeout_cb (EV_P_ ev_timer *w, int revents) -\& { -\& puts ("timeout"); -\& // this causes the innermost ev_run to stop iterating -\& ev_break (EV_A_ EVBREAK_ONE); -\& } -\& -\& int -\& main (void) -\& { -\& // use the default event loop unless you have special needs -\& struct ev_loop *loop = EV_DEFAULT; -\& -\& // initialise an io watcher, then start it -\& // this one will watch for stdin to become readable -\& ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); -\& ev_io_start (loop, &stdin_watcher); -\& -\& // initialise a timer watcher, then start it -\& // simple non\-repeating 5.5 second timeout -\& ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); -\& ev_timer_start (loop, &timeout_watcher); -\& -\& // now wait for events to arrive -\& ev_run (loop, 0); -\& -\& // break was called, so exit -\& return 0; -\& } -.Ve -.SH "ABOUT THIS DOCUMENT" -.IX Header "ABOUT THIS DOCUMENT" -This document documents the libev software package. -.PP -The newest version of this document is also available as an html-formatted -web page you might find easier to navigate when reading it for the first -time: . -.PP -While this document tries to be as complete as possible in documenting -libev, its usage and the rationale behind its design, it is not a tutorial -on event-based programming, nor will it introduce event-based programming -with libev. -.PP -Familiarity with event based programming techniques in general is assumed -throughout this document. -.SH "WHAT TO READ WHEN IN A HURRY" -.IX Header "WHAT TO READ WHEN IN A HURRY" -This manual tries to be very detailed, but unfortunately, this also makes -it very long. If you just want to know the basics of libev, I suggest -reading \*(L"\s-1ANATOMY\s0 \s-1OF\s0 A \s-1WATCHER\s0\*(R", then the \*(L"\s-1EXAMPLE\s0 \s-1PROGRAM\s0\*(R" above and -look up the missing functions in \*(L"\s-1GLOBAL\s0 \s-1FUNCTIONS\s0\*(R" and the \f(CW\*(C`ev_io\*(C'\fR and -\&\f(CW\*(C`ev_timer\*(C'\fR sections in \*(L"\s-1WATCHER\s0 \s-1TYPES\s0\*(R". -.SH "ABOUT LIBEV" -.IX Header "ABOUT LIBEV" -Libev is an event loop: you register interest in certain events (such as a -file descriptor being readable or a timeout occurring), and it will manage -these event sources and provide your program with events. -.PP -To do this, it must take more or less complete control over your process -(or thread) by executing the \fIevent loop\fR handler, and will then -communicate events via a callback mechanism. -.PP -You register interest in certain events by registering so-called \fIevent -watchers\fR, which are relatively small C structures you initialise with the -details of the event, and then hand it over to libev by \fIstarting\fR the -watcher. -.SS "\s-1FEATURES\s0" -.IX Subsection "FEATURES" -Libev supports \f(CW\*(C`select\*(C'\fR, \f(CW\*(C`poll\*(C'\fR, the Linux-specific \f(CW\*(C`epoll\*(C'\fR, the -BSD-specific \f(CW\*(C`kqueue\*(C'\fR and the Solaris-specific event port mechanisms -for file descriptor events (\f(CW\*(C`ev_io\*(C'\fR), the Linux \f(CW\*(C`inotify\*(C'\fR interface -(for \f(CW\*(C`ev_stat\*(C'\fR), Linux eventfd/signalfd (for faster and cleaner -inter-thread wakeup (\f(CW\*(C`ev_async\*(C'\fR)/signal handling (\f(CW\*(C`ev_signal\*(C'\fR)) relative -timers (\f(CW\*(C`ev_timer\*(C'\fR), absolute timers with customised rescheduling -(\f(CW\*(C`ev_periodic\*(C'\fR), synchronous signals (\f(CW\*(C`ev_signal\*(C'\fR), process status -change events (\f(CW\*(C`ev_child\*(C'\fR), and event watchers dealing with the event -loop mechanism itself (\f(CW\*(C`ev_idle\*(C'\fR, \f(CW\*(C`ev_embed\*(C'\fR, \f(CW\*(C`ev_prepare\*(C'\fR and -\&\f(CW\*(C`ev_check\*(C'\fR watchers) as well as file watchers (\f(CW\*(C`ev_stat\*(C'\fR) and even -limited support for fork events (\f(CW\*(C`ev_fork\*(C'\fR). -.PP -It also is quite fast (see this -benchmark comparing it to libevent -for example). -.SS "\s-1CONVENTIONS\s0" -.IX Subsection "CONVENTIONS" -Libev is very configurable. In this manual the default (and most common) -configuration will be described, which supports multiple event loops. For -more info about various configuration options please have a look at -\&\fB\s-1EMBED\s0\fR section in this manual. If libev was configured without support -for multiple event loops, then all functions taking an initial argument of -name \f(CW\*(C`loop\*(C'\fR (which is always of type \f(CW\*(C`struct ev_loop *\*(C'\fR) will not have -this argument. -.SS "\s-1TIME\s0 \s-1REPRESENTATION\s0" -.IX Subsection "TIME REPRESENTATION" -Libev represents time as a single floating point number, representing -the (fractional) number of seconds since the (\s-1POSIX\s0) epoch (in practice -somewhere near the beginning of 1970, details are complicated, don't -ask). This type is called \f(CW\*(C`ev_tstamp\*(C'\fR, which is what you should use -too. It usually aliases to the \f(CW\*(C`double\*(C'\fR type in C. When you need to do -any calculations on it, you should treat it as some floating point value. -.PP -Unlike the name component \f(CW\*(C`stamp\*(C'\fR might indicate, it is also used for -time differences (e.g. delays) throughout libev. -.SH "ERROR HANDLING" -.IX Header "ERROR HANDLING" -Libev knows three classes of errors: operating system errors, usage errors -and internal errors (bugs). -.PP -When libev catches an operating system error it cannot handle (for example -a system call indicating a condition libev cannot fix), it calls the callback -set via \f(CW\*(C`ev_set_syserr_cb\*(C'\fR, which is supposed to fix the problem or -abort. The default is to print a diagnostic message and to call \f(CW\*(C`abort -()\*(C'\fR. -.PP -When libev detects a usage error such as a negative timer interval, then -it will print a diagnostic message and abort (via the \f(CW\*(C`assert\*(C'\fR mechanism, -so \f(CW\*(C`NDEBUG\*(C'\fR will disable this checking): these are programming errors in -the libev caller and need to be fixed there. -.PP -Libev also has a few internal error-checking \f(CW\*(C`assert\*(C'\fRions, and also has -extensive consistency checking code. These do not trigger under normal -circumstances, as they indicate either a bug in libev or worse. -.SH "GLOBAL FUNCTIONS" -.IX Header "GLOBAL FUNCTIONS" -These functions can be called anytime, even before initialising the -library in any way. -.IP "ev_tstamp ev_time ()" 4 -.IX Item "ev_tstamp ev_time ()" -Returns the current time as libev would use it. Please note that the -\&\f(CW\*(C`ev_now\*(C'\fR function is usually faster and also often returns the timestamp -you actually want to know. Also interesting is the combination of -\&\f(CW\*(C`ev_now_update\*(C'\fR and \f(CW\*(C`ev_now\*(C'\fR. -.IP "ev_sleep (ev_tstamp interval)" 4 -.IX Item "ev_sleep (ev_tstamp interval)" -Sleep for the given interval: The current thread will be blocked -until either it is interrupted or the given time interval has -passed (approximately \- it might return a bit earlier even if not -interrupted). Returns immediately if \f(CW\*(C`interval <= 0\*(C'\fR. -.Sp -Basically this is a sub-second-resolution \f(CW\*(C`sleep ()\*(C'\fR. -.Sp -The range of the \f(CW\*(C`interval\*(C'\fR is limited \- libev only guarantees to work -with sleep times of up to one day (\f(CW\*(C`interval <= 86400\*(C'\fR). -.IP "int ev_version_major ()" 4 -.IX Item "int ev_version_major ()" -.PD 0 -.IP "int ev_version_minor ()" 4 -.IX Item "int ev_version_minor ()" -.PD -You can find out the major and minor \s-1ABI\s0 version numbers of the library -you linked against by calling the functions \f(CW\*(C`ev_version_major\*(C'\fR and -\&\f(CW\*(C`ev_version_minor\*(C'\fR. If you want, you can compare against the global -symbols \f(CW\*(C`EV_VERSION_MAJOR\*(C'\fR and \f(CW\*(C`EV_VERSION_MINOR\*(C'\fR, which specify the -version of the library your program was compiled against. -.Sp -These version numbers refer to the \s-1ABI\s0 version of the library, not the -release version. -.Sp -Usually, it's a good idea to terminate if the major versions mismatch, -as this indicates an incompatible change. Minor versions are usually -compatible to older versions, so a larger minor version alone is usually -not a problem. -.Sp -Example: Make sure we haven't accidentally been linked against the wrong -version (note, however, that this will not detect other \s-1ABI\s0 mismatches, -such as \s-1LFS\s0 or reentrancy). -.Sp -.Vb 3 -\& assert (("libev version mismatch", -\& ev_version_major () == EV_VERSION_MAJOR -\& && ev_version_minor () >= EV_VERSION_MINOR)); -.Ve -.IP "unsigned int ev_supported_backends ()" 4 -.IX Item "unsigned int ev_supported_backends ()" -Return the set of all backends (i.e. their corresponding \f(CW\*(C`EV_BACKEND_*\*(C'\fR -value) compiled into this binary of libev (independent of their -availability on the system you are running on). See \f(CW\*(C`ev_default_loop\*(C'\fR for -a description of the set values. -.Sp -Example: make sure we have the epoll method, because yeah this is cool and -a must have and can we have a torrent of it please!!!11 -.Sp -.Vb 2 -\& assert (("sorry, no epoll, no sex", -\& ev_supported_backends () & EVBACKEND_EPOLL)); -.Ve -.IP "unsigned int ev_recommended_backends ()" 4 -.IX Item "unsigned int ev_recommended_backends ()" -Return the set of all backends compiled into this binary of libev and -also recommended for this platform, meaning it will work for most file -descriptor types. This set is often smaller than the one returned by -\&\f(CW\*(C`ev_supported_backends\*(C'\fR, as for example kqueue is broken on most BSDs -and will not be auto-detected unless you explicitly request it (assuming -you know what you are doing). This is the set of backends that libev will -probe for if you specify no backends explicitly. -.IP "unsigned int ev_embeddable_backends ()" 4 -.IX Item "unsigned int ev_embeddable_backends ()" -Returns the set of backends that are embeddable in other event loops. This -value is platform-specific but can include backends not available on the -current system. To find which embeddable backends might be supported on -the current system, you would need to look at \f(CW\*(C`ev_embeddable_backends () -& ev_supported_backends ()\*(C'\fR, likewise for recommended ones. -.Sp -See the description of \f(CW\*(C`ev_embed\*(C'\fR watchers for more info. -.IP "ev_set_allocator (void *(*cb)(void *ptr, long size) throw ())" 4 -.IX Item "ev_set_allocator (void *(*cb)(void *ptr, long size) throw ())" -Sets the allocation function to use (the prototype is similar \- the -semantics are identical to the \f(CW\*(C`realloc\*(C'\fR C89/SuS/POSIX function). It is -used to allocate and free memory (no surprises here). If it returns zero -when memory needs to be allocated (\f(CW\*(C`size != 0\*(C'\fR), the library might abort -or take some potentially destructive action. -.Sp -Since some systems (at least OpenBSD and Darwin) fail to implement -correct \f(CW\*(C`realloc\*(C'\fR semantics, libev will use a wrapper around the system -\&\f(CW\*(C`realloc\*(C'\fR and \f(CW\*(C`free\*(C'\fR functions by default. -.Sp -You could override this function in high-availability programs to, say, -free some memory if it cannot allocate memory, to use a special allocator, -or even to sleep a while and retry until some memory is available. -.Sp -Example: Replace the libev allocator with one that waits a bit and then -retries (example requires a standards-compliant \f(CW\*(C`realloc\*(C'\fR). -.Sp -.Vb 6 -\& static void * -\& persistent_realloc (void *ptr, size_t size) -\& { -\& for (;;) -\& { -\& void *newptr = realloc (ptr, size); -\& -\& if (newptr) -\& return newptr; -\& -\& sleep (60); -\& } -\& } -\& -\& ... -\& ev_set_allocator (persistent_realloc); -.Ve -.IP "ev_set_syserr_cb (void (*cb)(const char *msg) throw ())" 4 -.IX Item "ev_set_syserr_cb (void (*cb)(const char *msg) throw ())" -Set the callback function to call on a retryable system call error (such -as failed select, poll, epoll_wait). The message is a printable string -indicating the system call or subsystem causing the problem. If this -callback is set, then libev will expect it to remedy the situation, no -matter what, when it returns. That is, libev will generally retry the -requested operation, or, if the condition doesn't go away, do bad stuff -(such as abort). -.Sp -Example: This is basically the same thing that libev does internally, too. -.Sp -.Vb 6 -\& static void -\& fatal_error (const char *msg) -\& { -\& perror (msg); -\& abort (); -\& } -\& -\& ... -\& ev_set_syserr_cb (fatal_error); -.Ve -.IP "ev_feed_signal (int signum)" 4 -.IX Item "ev_feed_signal (int signum)" -This function can be used to \*(L"simulate\*(R" a signal receive. It is completely -safe to call this function at any time, from any context, including signal -handlers or random threads. -.Sp -Its main use is to customise signal handling in your process, especially -in the presence of threads. For example, you could block signals -by default in all threads (and specifying \f(CW\*(C`EVFLAG_NOSIGMASK\*(C'\fR when -creating any loops), and in one thread, use \f(CW\*(C`sigwait\*(C'\fR or any other -mechanism to wait for signals, then \*(L"deliver\*(R" them to libev by calling -\&\f(CW\*(C`ev_feed_signal\*(C'\fR. -.SH "FUNCTIONS CONTROLLING EVENT LOOPS" -.IX Header "FUNCTIONS CONTROLLING EVENT LOOPS" -An event loop is described by a \f(CW\*(C`struct ev_loop *\*(C'\fR (the \f(CW\*(C`struct\*(C'\fR is -\&\fInot\fR optional in this case unless libev 3 compatibility is disabled, as -libev 3 had an \f(CW\*(C`ev_loop\*(C'\fR function colliding with the struct name). -.PP -The library knows two types of such loops, the \fIdefault\fR loop, which -supports child process events, and dynamically created event loops which -do not. -.IP "struct ev_loop *ev_default_loop (unsigned int flags)" 4 -.IX Item "struct ev_loop *ev_default_loop (unsigned int flags)" -This returns the \*(L"default\*(R" event loop object, which is what you should -normally use when you just need \*(L"the event loop\*(R". Event loop objects and -the \f(CW\*(C`flags\*(C'\fR parameter are described in more detail in the entry for -\&\f(CW\*(C`ev_loop_new\*(C'\fR. -.Sp -If the default loop is already initialised then this function simply -returns it (and ignores the flags. If that is troubling you, check -\&\f(CW\*(C`ev_backend ()\*(C'\fR afterwards). Otherwise it will create it with the given -flags, which should almost always be \f(CW0\fR, unless the caller is also the -one calling \f(CW\*(C`ev_run\*(C'\fR or otherwise qualifies as \*(L"the main program\*(R". -.Sp -If you don't know what event loop to use, use the one returned from this -function (or via the \f(CW\*(C`EV_DEFAULT\*(C'\fR macro). -.Sp -Note that this function is \fInot\fR thread-safe, so if you want to use it -from multiple threads, you have to employ some kind of mutex (note also -that this case is unlikely, as loops cannot be shared easily between -threads anyway). -.Sp -The default loop is the only loop that can handle \f(CW\*(C`ev_child\*(C'\fR watchers, -and to do this, it always registers a handler for \f(CW\*(C`SIGCHLD\*(C'\fR. If this is -a problem for your application you can either create a dynamic loop with -\&\f(CW\*(C`ev_loop_new\*(C'\fR which doesn't do that, or you can simply overwrite the -\&\f(CW\*(C`SIGCHLD\*(C'\fR signal handler \fIafter\fR calling \f(CW\*(C`ev_default_init\*(C'\fR. -.Sp -Example: This is the most typical usage. -.Sp -.Vb 2 -\& if (!ev_default_loop (0)) -\& fatal ("could not initialise libev, bad $LIBEV_FLAGS in environment?"); -.Ve -.Sp -Example: Restrict libev to the select and poll backends, and do not allow -environment settings to be taken into account: -.Sp -.Vb 1 -\& ev_default_loop (EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV); -.Ve -.IP "struct ev_loop *ev_loop_new (unsigned int flags)" 4 -.IX Item "struct ev_loop *ev_loop_new (unsigned int flags)" -This will create and initialise a new event loop object. If the loop -could not be initialised, returns false. -.Sp -This function is thread-safe, and one common way to use libev with -threads is indeed to create one loop per thread, and using the default -loop in the \*(L"main\*(R" or \*(L"initial\*(R" thread. -.Sp -The flags argument can be used to specify special behaviour or specific -backends to use, and is usually specified as \f(CW0\fR (or \f(CW\*(C`EVFLAG_AUTO\*(C'\fR). -.Sp -The following flags are supported: -.RS 4 -.ie n .IP """EVFLAG_AUTO""" 4 -.el .IP "\f(CWEVFLAG_AUTO\fR" 4 -.IX Item "EVFLAG_AUTO" -The default flags value. Use this if you have no clue (it's the right -thing, believe me). -.ie n .IP """EVFLAG_NOENV""" 4 -.el .IP "\f(CWEVFLAG_NOENV\fR" 4 -.IX Item "EVFLAG_NOENV" -If this flag bit is or'ed into the flag value (or the program runs setuid -or setgid) then libev will \fInot\fR look at the environment variable -\&\f(CW\*(C`LIBEV_FLAGS\*(C'\fR. Otherwise (the default), this environment variable will -override the flags completely if it is found in the environment. This is -useful to try out specific backends to test their performance, or to work -around bugs. -.ie n .IP """EVFLAG_FORKCHECK""" 4 -.el .IP "\f(CWEVFLAG_FORKCHECK\fR" 4 -.IX Item "EVFLAG_FORKCHECK" -Instead of calling \f(CW\*(C`ev_loop_fork\*(C'\fR manually after a fork, you can also -make libev check for a fork in each iteration by enabling this flag. -.Sp -This works by calling \f(CW\*(C`getpid ()\*(C'\fR on every iteration of the loop, -and thus this might slow down your event loop if you do a lot of loop -iterations and little real work, but is usually not noticeable (on my -GNU/Linux system for example, \f(CW\*(C`getpid\*(C'\fR is actually a simple 5\-insn sequence -without a system call and thus \fIvery\fR fast, but my GNU/Linux system also has -\&\f(CW\*(C`pthread_atfork\*(C'\fR which is even faster). -.Sp -The big advantage of this flag is that you can forget about fork (and -forget about forgetting to tell libev about forking) when you use this -flag. -.Sp -This flag setting cannot be overridden or specified in the \f(CW\*(C`LIBEV_FLAGS\*(C'\fR -environment variable. -.ie n .IP """EVFLAG_NOINOTIFY""" 4 -.el .IP "\f(CWEVFLAG_NOINOTIFY\fR" 4 -.IX Item "EVFLAG_NOINOTIFY" -When this flag is specified, then libev will not attempt to use the -\&\fIinotify\fR \s-1API\s0 for its \f(CW\*(C`ev_stat\*(C'\fR watchers. Apart from debugging and -testing, this flag can be useful to conserve inotify file descriptors, as -otherwise each loop using \f(CW\*(C`ev_stat\*(C'\fR watchers consumes one inotify handle. -.ie n .IP """EVFLAG_SIGNALFD""" 4 -.el .IP "\f(CWEVFLAG_SIGNALFD\fR" 4 -.IX Item "EVFLAG_SIGNALFD" -When this flag is specified, then libev will attempt to use the -\&\fIsignalfd\fR \s-1API\s0 for its \f(CW\*(C`ev_signal\*(C'\fR (and \f(CW\*(C`ev_child\*(C'\fR) watchers. This \s-1API\s0 -delivers signals synchronously, which makes it both faster and might make -it possible to get the queued signal data. It can also simplify signal -handling with threads, as long as you properly block signals in your -threads that are not interested in handling them. -.Sp -Signalfd will not be used by default as this changes your signal mask, and -there are a lot of shoddy libraries and programs (glib's threadpool for -example) that can't properly initialise their signal masks. -.ie n .IP """EVFLAG_NOSIGMASK""" 4 -.el .IP "\f(CWEVFLAG_NOSIGMASK\fR" 4 -.IX Item "EVFLAG_NOSIGMASK" -When this flag is specified, then libev will avoid to modify the signal -mask. Specifically, this means you have to make sure signals are unblocked -when you want to receive them. -.Sp -This behaviour is useful when you want to do your own signal handling, or -want to handle signals only in specific threads and want to avoid libev -unblocking the signals. -.Sp -It's also required by \s-1POSIX\s0 in a threaded program, as libev calls -\&\f(CW\*(C`sigprocmask\*(C'\fR, whose behaviour is officially unspecified. -.Sp -This flag's behaviour will become the default in future versions of libev. -.ie n .IP """EVBACKEND_SELECT"" (value 1, portable select backend)" 4 -.el .IP "\f(CWEVBACKEND_SELECT\fR (value 1, portable select backend)" 4 -.IX Item "EVBACKEND_SELECT (value 1, portable select backend)" -This is your standard \fIselect\fR\|(2) backend. Not \fIcompletely\fR standard, as -libev tries to roll its own fd_set with no limits on the number of fds, -but if that fails, expect a fairly low limit on the number of fds when -using this backend. It doesn't scale too well (O(highest_fd)), but its -usually the fastest backend for a low number of (low-numbered :) fds. -.Sp -To get good performance out of this backend you need a high amount of -parallelism (most of the file descriptors should be busy). If you are -writing a server, you should \f(CW\*(C`accept ()\*(C'\fR in a loop to accept as many -connections as possible during one iteration. You might also want to have -a look at \f(CW\*(C`ev_set_io_collect_interval ()\*(C'\fR to increase the amount of -readiness notifications you get per iteration. -.Sp -This backend maps \f(CW\*(C`EV_READ\*(C'\fR to the \f(CW\*(C`readfds\*(C'\fR set and \f(CW\*(C`EV_WRITE\*(C'\fR to the -\&\f(CW\*(C`writefds\*(C'\fR set (and to work around Microsoft Windows bugs, also onto the -\&\f(CW\*(C`exceptfds\*(C'\fR set on that platform). -.ie n .IP """EVBACKEND_POLL"" (value 2, poll backend, available everywhere except on windows)" 4 -.el .IP "\f(CWEVBACKEND_POLL\fR (value 2, poll backend, available everywhere except on windows)" 4 -.IX Item "EVBACKEND_POLL (value 2, poll backend, available everywhere except on windows)" -And this is your standard \fIpoll\fR\|(2) backend. It's more complicated -than select, but handles sparse fds better and has no artificial -limit on the number of fds you can use (except it will slow down -considerably with a lot of inactive fds). It scales similarly to select, -i.e. O(total_fds). See the entry for \f(CW\*(C`EVBACKEND_SELECT\*(C'\fR, above, for -performance tips. -.Sp -This backend maps \f(CW\*(C`EV_READ\*(C'\fR to \f(CW\*(C`POLLIN | POLLERR | POLLHUP\*(C'\fR, and -\&\f(CW\*(C`EV_WRITE\*(C'\fR to \f(CW\*(C`POLLOUT | POLLERR | POLLHUP\*(C'\fR. -.ie n .IP """EVBACKEND_EPOLL"" (value 4, Linux)" 4 -.el .IP "\f(CWEVBACKEND_EPOLL\fR (value 4, Linux)" 4 -.IX Item "EVBACKEND_EPOLL (value 4, Linux)" -Use the linux-specific \fIepoll\fR\|(7) interface (for both pre\- and post\-2.6.9 -kernels). -.Sp -For few fds, this backend is a bit little slower than poll and select, but -it scales phenomenally better. While poll and select usually scale like -O(total_fds) where total_fds is the total number of fds (or the highest -fd), epoll scales either O(1) or O(active_fds). -.Sp -The epoll mechanism deserves honorable mention as the most misdesigned -of the more advanced event mechanisms: mere annoyances include silently -dropping file descriptors, requiring a system call per change per file -descriptor (and unnecessary guessing of parameters), problems with dup, -returning before the timeout value, resulting in additional iterations -(and only giving 5ms accuracy while select on the same platform gives -0.1ms) and so on. The biggest issue is fork races, however \- if a program -forks then \fIboth\fR parent and child process have to recreate the epoll -set, which can take considerable time (one syscall per file descriptor) -and is of course hard to detect. -.Sp -Epoll is also notoriously buggy \- embedding epoll fds \fIshould\fR work, -but of course \fIdoesn't\fR, and epoll just loves to report events for -totally \fIdifferent\fR file descriptors (even already closed ones, so -one cannot even remove them from the set) than registered in the set -(especially on \s-1SMP\s0 systems). Libev tries to counter these spurious -notifications by employing an additional generation counter and comparing -that against the events to filter out spurious ones, recreating the set -when required. Epoll also erroneously rounds down timeouts, but gives you -no way to know when and by how much, so sometimes you have to busy-wait -because epoll returns immediately despite a nonzero timeout. And last -not least, it also refuses to work with some file descriptors which work -perfectly fine with \f(CW\*(C`select\*(C'\fR (files, many character devices...). -.Sp -Epoll is truly the train wreck among event poll mechanisms, a frankenpoll, -cobbled together in a hurry, no thought to design or interaction with -others. Oh, the pain, will it ever stop... -.Sp -While stopping, setting and starting an I/O watcher in the same iteration -will result in some caching, there is still a system call per such -incident (because the same \fIfile descriptor\fR could point to a different -\&\fIfile description\fR now), so its best to avoid that. Also, \f(CW\*(C`dup ()\*(C'\fR'ed -file descriptors might not work very well if you register events for both -file descriptors. -.Sp -Best performance from this backend is achieved by not unregistering all -watchers for a file descriptor until it has been closed, if possible, -i.e. keep at least one watcher active per fd at all times. Stopping and -starting a watcher (without re-setting it) also usually doesn't cause -extra overhead. A fork can both result in spurious notifications as well -as in libev having to destroy and recreate the epoll object, which can -take considerable time and thus should be avoided. -.Sp -All this means that, in practice, \f(CW\*(C`EVBACKEND_SELECT\*(C'\fR can be as fast or -faster than epoll for maybe up to a hundred file descriptors, depending on -the usage. So sad. -.Sp -While nominally embeddable in other event loops, this feature is broken in -all kernel versions tested so far. -.Sp -This backend maps \f(CW\*(C`EV_READ\*(C'\fR and \f(CW\*(C`EV_WRITE\*(C'\fR in the same way as -\&\f(CW\*(C`EVBACKEND_POLL\*(C'\fR. -.ie n .IP """EVBACKEND_KQUEUE"" (value 8, most \s-1BSD\s0 clones)" 4 -.el .IP "\f(CWEVBACKEND_KQUEUE\fR (value 8, most \s-1BSD\s0 clones)" 4 -.IX Item "EVBACKEND_KQUEUE (value 8, most BSD clones)" -Kqueue deserves special mention, as at the time of this writing, it -was broken on all BSDs except NetBSD (usually it doesn't work reliably -with anything but sockets and pipes, except on Darwin, where of course -it's completely useless). Unlike epoll, however, whose brokenness -is by design, these kqueue bugs can (and eventually will) be fixed -without \s-1API\s0 changes to existing programs. For this reason it's not being -\&\*(L"auto-detected\*(R" unless you explicitly specify it in the flags (i.e. using -\&\f(CW\*(C`EVBACKEND_KQUEUE\*(C'\fR) or libev was compiled on a known-to-be-good (\-enough) -system like NetBSD. -.Sp -You still can embed kqueue into a normal poll or select backend and use it -only for sockets (after having made sure that sockets work with kqueue on -the target platform). See \f(CW\*(C`ev_embed\*(C'\fR watchers for more info. -.Sp -It scales in the same way as the epoll backend, but the interface to the -kernel is more efficient (which says nothing about its actual speed, of -course). While stopping, setting and starting an I/O watcher does never -cause an extra system call as with \f(CW\*(C`EVBACKEND_EPOLL\*(C'\fR, it still adds up to -two event changes per incident. Support for \f(CW\*(C`fork ()\*(C'\fR is very bad (you -might have to leak fd's on fork, but it's more sane than epoll) and it -drops fds silently in similarly hard-to-detect cases. -.Sp -This backend usually performs well under most conditions. -.Sp -While nominally embeddable in other event loops, this doesn't work -everywhere, so you might need to test for this. And since it is broken -almost everywhere, you should only use it when you have a lot of sockets -(for which it usually works), by embedding it into another event loop -(e.g. \f(CW\*(C`EVBACKEND_SELECT\*(C'\fR or \f(CW\*(C`EVBACKEND_POLL\*(C'\fR (but \f(CW\*(C`poll\*(C'\fR is of course -also broken on \s-1OS\s0 X)) and, did I mention it, using it only for sockets. -.Sp -This backend maps \f(CW\*(C`EV_READ\*(C'\fR into an \f(CW\*(C`EVFILT_READ\*(C'\fR kevent with -\&\f(CW\*(C`NOTE_EOF\*(C'\fR, and \f(CW\*(C`EV_WRITE\*(C'\fR into an \f(CW\*(C`EVFILT_WRITE\*(C'\fR kevent with -\&\f(CW\*(C`NOTE_EOF\*(C'\fR. -.ie n .IP """EVBACKEND_DEVPOLL"" (value 16, Solaris 8)" 4 -.el .IP "\f(CWEVBACKEND_DEVPOLL\fR (value 16, Solaris 8)" 4 -.IX Item "EVBACKEND_DEVPOLL (value 16, Solaris 8)" -This is not implemented yet (and might never be, unless you send me an -implementation). According to reports, \f(CW\*(C`/dev/poll\*(C'\fR only supports sockets -and is not embeddable, which would limit the usefulness of this backend -immensely. -.ie n .IP """EVBACKEND_PORT"" (value 32, Solaris 10)" 4 -.el .IP "\f(CWEVBACKEND_PORT\fR (value 32, Solaris 10)" 4 -.IX Item "EVBACKEND_PORT (value 32, Solaris 10)" -This uses the Solaris 10 event port mechanism. As with everything on Solaris, -it's really slow, but it still scales very well (O(active_fds)). -.Sp -While this backend scales well, it requires one system call per active -file descriptor per loop iteration. For small and medium numbers of file -descriptors a \*(L"slow\*(R" \f(CW\*(C`EVBACKEND_SELECT\*(C'\fR or \f(CW\*(C`EVBACKEND_POLL\*(C'\fR backend -might perform better. -.Sp -On the positive side, this backend actually performed fully to -specification in all tests and is fully embeddable, which is a rare feat -among the OS-specific backends (I vastly prefer correctness over speed -hacks). -.Sp -On the negative side, the interface is \fIbizarre\fR \- so bizarre that -even sun itself gets it wrong in their code examples: The event polling -function sometimes returns events to the caller even though an error -occurred, but with no indication whether it has done so or not (yes, it's -even documented that way) \- deadly for edge-triggered interfaces where you -absolutely have to know whether an event occurred or not because you have -to re-arm the watcher. -.Sp -Fortunately libev seems to be able to work around these idiocies. -.Sp -This backend maps \f(CW\*(C`EV_READ\*(C'\fR and \f(CW\*(C`EV_WRITE\*(C'\fR in the same way as -\&\f(CW\*(C`EVBACKEND_POLL\*(C'\fR. -.ie n .IP """EVBACKEND_ALL""" 4 -.el .IP "\f(CWEVBACKEND_ALL\fR" 4 -.IX Item "EVBACKEND_ALL" -Try all backends (even potentially broken ones that wouldn't be tried -with \f(CW\*(C`EVFLAG_AUTO\*(C'\fR). Since this is a mask, you can do stuff such as -\&\f(CW\*(C`EVBACKEND_ALL & ~EVBACKEND_KQUEUE\*(C'\fR. -.Sp -It is definitely not recommended to use this flag, use whatever -\&\f(CW\*(C`ev_recommended_backends ()\*(C'\fR returns, or simply do not specify a backend -at all. -.ie n .IP """EVBACKEND_MASK""" 4 -.el .IP "\f(CWEVBACKEND_MASK\fR" 4 -.IX Item "EVBACKEND_MASK" -Not a backend at all, but a mask to select all backend bits from a -\&\f(CW\*(C`flags\*(C'\fR value, in case you want to mask out any backends from a flags -value (e.g. when modifying the \f(CW\*(C`LIBEV_FLAGS\*(C'\fR environment variable). -.RE -.RS 4 -.Sp -If one or more of the backend flags are or'ed into the flags value, -then only these backends will be tried (in the reverse order as listed -here). If none are specified, all backends in \f(CW\*(C`ev_recommended_backends -()\*(C'\fR will be tried. -.Sp -Example: Try to create a event loop that uses epoll and nothing else. -.Sp -.Vb 3 -\& struct ev_loop *epoller = ev_loop_new (EVBACKEND_EPOLL | EVFLAG_NOENV); -\& if (!epoller) -\& fatal ("no epoll found here, maybe it hides under your chair"); -.Ve -.Sp -Example: Use whatever libev has to offer, but make sure that kqueue is -used if available. -.Sp -.Vb 1 -\& struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_KQUEUE); -.Ve -.RE -.IP "ev_loop_destroy (loop)" 4 -.IX Item "ev_loop_destroy (loop)" -Destroys an event loop object (frees all memory and kernel state -etc.). None of the active event watchers will be stopped in the normal -sense, so e.g. \f(CW\*(C`ev_is_active\*(C'\fR might still return true. It is your -responsibility to either stop all watchers cleanly yourself \fIbefore\fR -calling this function, or cope with the fact afterwards (which is usually -the easiest thing, you can just ignore the watchers and/or \f(CW\*(C`free ()\*(C'\fR them -for example). -.Sp -Note that certain global state, such as signal state (and installed signal -handlers), will not be freed by this function, and related watchers (such -as signal and child watchers) would need to be stopped manually. -.Sp -This function is normally used on loop objects allocated by -\&\f(CW\*(C`ev_loop_new\*(C'\fR, but it can also be used on the default loop returned by -\&\f(CW\*(C`ev_default_loop\*(C'\fR, in which case it is not thread-safe. -.Sp -Note that it is not advisable to call this function on the default loop -except in the rare occasion where you really need to free its resources. -If you need dynamically allocated loops it is better to use \f(CW\*(C`ev_loop_new\*(C'\fR -and \f(CW\*(C`ev_loop_destroy\*(C'\fR. -.IP "ev_loop_fork (loop)" 4 -.IX Item "ev_loop_fork (loop)" -This function sets a flag that causes subsequent \f(CW\*(C`ev_run\*(C'\fR iterations to -reinitialise the kernel state for backends that have one. Despite the -name, you can call it anytime, but it makes most sense after forking, in -the child process. You \fImust\fR call it (or use \f(CW\*(C`EVFLAG_FORKCHECK\*(C'\fR) in the -child before resuming or calling \f(CW\*(C`ev_run\*(C'\fR. -.Sp -Again, you \fIhave\fR to call it on \fIany\fR loop that you want to re-use after -a fork, \fIeven if you do not plan to use the loop in the parent\fR. This is -because some kernel interfaces *cough* \fIkqueue\fR *cough* do funny things -during fork. -.Sp -On the other hand, you only need to call this function in the child -process if and only if you want to use the event loop in the child. If -you just fork+exec or create a new loop in the child, you don't have to -call it at all (in fact, \f(CW\*(C`epoll\*(C'\fR is so badly broken that it makes a -difference, but libev will usually detect this case on its own and do a -costly reset of the backend). -.Sp -The function itself is quite fast and it's usually not a problem to call -it just in case after a fork. -.Sp -Example: Automate calling \f(CW\*(C`ev_loop_fork\*(C'\fR on the default loop when -using pthreads. -.Sp -.Vb 5 -\& static void -\& post_fork_child (void) -\& { -\& ev_loop_fork (EV_DEFAULT); -\& } -\& -\& ... -\& pthread_atfork (0, 0, post_fork_child); -.Ve -.IP "int ev_is_default_loop (loop)" 4 -.IX Item "int ev_is_default_loop (loop)" -Returns true when the given loop is, in fact, the default loop, and false -otherwise. -.IP "unsigned int ev_iteration (loop)" 4 -.IX Item "unsigned int ev_iteration (loop)" -Returns the current iteration count for the event loop, which is identical -to the number of times libev did poll for new events. It starts at \f(CW0\fR -and happily wraps around with enough iterations. -.Sp -This value can sometimes be useful as a generation counter of sorts (it -\&\*(L"ticks\*(R" the number of loop iterations), as it roughly corresponds with -\&\f(CW\*(C`ev_prepare\*(C'\fR and \f(CW\*(C`ev_check\*(C'\fR calls \- and is incremented between the -prepare and check phases. -.IP "unsigned int ev_depth (loop)" 4 -.IX Item "unsigned int ev_depth (loop)" -Returns the number of times \f(CW\*(C`ev_run\*(C'\fR was entered minus the number of -times \f(CW\*(C`ev_run\*(C'\fR was exited normally, in other words, the recursion depth. -.Sp -Outside \f(CW\*(C`ev_run\*(C'\fR, this number is zero. In a callback, this number is -\&\f(CW1\fR, unless \f(CW\*(C`ev_run\*(C'\fR was invoked recursively (or from another thread), -in which case it is higher. -.Sp -Leaving \f(CW\*(C`ev_run\*(C'\fR abnormally (setjmp/longjmp, cancelling the thread, -throwing an exception etc.), doesn't count as \*(L"exit\*(R" \- consider this -as a hint to avoid such ungentleman-like behaviour unless it's really -convenient, in which case it is fully supported. -.IP "unsigned int ev_backend (loop)" 4 -.IX Item "unsigned int ev_backend (loop)" -Returns one of the \f(CW\*(C`EVBACKEND_*\*(C'\fR flags indicating the event backend in -use. -.IP "ev_tstamp ev_now (loop)" 4 -.IX Item "ev_tstamp ev_now (loop)" -Returns the current \*(L"event loop time\*(R", which is the time the event loop -received events and started processing them. This timestamp does not -change as long as callbacks are being processed, and this is also the base -time used for relative timers. You can treat it as the timestamp of the -event occurring (or more correctly, libev finding out about it). -.IP "ev_now_update (loop)" 4 -.IX Item "ev_now_update (loop)" -Establishes the current time by querying the kernel, updating the time -returned by \f(CW\*(C`ev_now ()\*(C'\fR in the progress. This is a costly operation and -is usually done automatically within \f(CW\*(C`ev_run ()\*(C'\fR. -.Sp -This function is rarely useful, but when some event callback runs for a -very long time without entering the event loop, updating libev's idea of -the current time is a good idea. -.Sp -See also \*(L"The special problem of time updates\*(R" in the \f(CW\*(C`ev_timer\*(C'\fR section. -.IP "ev_suspend (loop)" 4 -.IX Item "ev_suspend (loop)" -.PD 0 -.IP "ev_resume (loop)" 4 -.IX Item "ev_resume (loop)" -.PD -These two functions suspend and resume an event loop, for use when the -loop is not used for a while and timeouts should not be processed. -.Sp -A typical use case would be an interactive program such as a game: When -the user presses \f(CW\*(C`^Z\*(C'\fR to suspend the game and resumes it an hour later it -would be best to handle timeouts as if no time had actually passed while -the program was suspended. This can be achieved by calling \f(CW\*(C`ev_suspend\*(C'\fR -in your \f(CW\*(C`SIGTSTP\*(C'\fR handler, sending yourself a \f(CW\*(C`SIGSTOP\*(C'\fR and calling -\&\f(CW\*(C`ev_resume\*(C'\fR directly afterwards to resume timer processing. -.Sp -Effectively, all \f(CW\*(C`ev_timer\*(C'\fR watchers will be delayed by the time spend -between \f(CW\*(C`ev_suspend\*(C'\fR and \f(CW\*(C`ev_resume\*(C'\fR, and all \f(CW\*(C`ev_periodic\*(C'\fR watchers -will be rescheduled (that is, they will lose any events that would have -occurred while suspended). -.Sp -After calling \f(CW\*(C`ev_suspend\*(C'\fR you \fBmust not\fR call \fIany\fR function on the -given loop other than \f(CW\*(C`ev_resume\*(C'\fR, and you \fBmust not\fR call \f(CW\*(C`ev_resume\*(C'\fR -without a previous call to \f(CW\*(C`ev_suspend\*(C'\fR. -.Sp -Calling \f(CW\*(C`ev_suspend\*(C'\fR/\f(CW\*(C`ev_resume\*(C'\fR has the side effect of updating the -event loop time (see \f(CW\*(C`ev_now_update\*(C'\fR). -.IP "bool ev_run (loop, int flags)" 4 -.IX Item "bool ev_run (loop, int flags)" -Finally, this is it, the event handler. This function usually is called -after you have initialised all your watchers and you want to start -handling events. It will ask the operating system for any new events, call -the watcher callbacks, and then repeat the whole process indefinitely: This -is why event loops are called \fIloops\fR. -.Sp -If the flags argument is specified as \f(CW0\fR, it will keep handling events -until either no event watchers are active anymore or \f(CW\*(C`ev_break\*(C'\fR was -called. -.Sp -The return value is false if there are no more active watchers (which -usually means \*(L"all jobs done\*(R" or \*(L"deadlock\*(R"), and true in all other cases -(which usually means " you should call \f(CW\*(C`ev_run\*(C'\fR again"). -.Sp -Please note that an explicit \f(CW\*(C`ev_break\*(C'\fR is usually better than -relying on all watchers to be stopped when deciding when a program has -finished (especially in interactive programs), but having a program -that automatically loops as long as it has to and no longer by virtue -of relying on its watchers stopping correctly, that is truly a thing of -beauty. -.Sp -This function is \fImostly\fR exception-safe \- you can break out of a -\&\f(CW\*(C`ev_run\*(C'\fR call by calling \f(CW\*(C`longjmp\*(C'\fR in a callback, throwing a \*(C+ -exception and so on. This does not decrement the \f(CW\*(C`ev_depth\*(C'\fR value, nor -will it clear any outstanding \f(CW\*(C`EVBREAK_ONE\*(C'\fR breaks. -.Sp -A flags value of \f(CW\*(C`EVRUN_NOWAIT\*(C'\fR will look for new events, will handle -those events and any already outstanding ones, but will not wait and -block your process in case there are no events and will return after one -iteration of the loop. This is sometimes useful to poll and handle new -events while doing lengthy calculations, to keep the program responsive. -.Sp -A flags value of \f(CW\*(C`EVRUN_ONCE\*(C'\fR will look for new events (waiting if -necessary) and will handle those and any already outstanding ones. It -will block your process until at least one new event arrives (which could -be an event internal to libev itself, so there is no guarantee that a -user-registered callback will be called), and will return after one -iteration of the loop. -.Sp -This is useful if you are waiting for some external event in conjunction -with something not expressible using other libev watchers (i.e. "roll your -own \f(CW\*(C`ev_run\*(C'\fR"). However, a pair of \f(CW\*(C`ev_prepare\*(C'\fR/\f(CW\*(C`ev_check\*(C'\fR watchers is -usually a better approach for this kind of thing. -.Sp -Here are the gory details of what \f(CW\*(C`ev_run\*(C'\fR does (this is for your -understanding, not a guarantee that things will work exactly like this in -future versions): -.Sp -.Vb 10 -\& \- Increment loop depth. -\& \- Reset the ev_break status. -\& \- Before the first iteration, call any pending watchers. -\& LOOP: -\& \- If EVFLAG_FORKCHECK was used, check for a fork. -\& \- If a fork was detected (by any means), queue and call all fork watchers. -\& \- Queue and call all prepare watchers. -\& \- If ev_break was called, goto FINISH. -\& \- If we have been forked, detach and recreate the kernel state -\& as to not disturb the other process. -\& \- Update the kernel state with all outstanding changes. -\& \- Update the "event loop time" (ev_now ()). -\& \- Calculate for how long to sleep or block, if at all -\& (active idle watchers, EVRUN_NOWAIT or not having -\& any active watchers at all will result in not sleeping). -\& \- Sleep if the I/O and timer collect interval say so. -\& \- Increment loop iteration counter. -\& \- Block the process, waiting for any events. -\& \- Queue all outstanding I/O (fd) events. -\& \- Update the "event loop time" (ev_now ()), and do time jump adjustments. -\& \- Queue all expired timers. -\& \- Queue all expired periodics. -\& \- Queue all idle watchers with priority higher than that of pending events. -\& \- Queue all check watchers. -\& \- Call all queued watchers in reverse order (i.e. check watchers first). -\& Signals and child watchers are implemented as I/O watchers, and will -\& be handled here by queueing them when their watcher gets executed. -\& \- If ev_break has been called, or EVRUN_ONCE or EVRUN_NOWAIT -\& were used, or there are no active watchers, goto FINISH, otherwise -\& continue with step LOOP. -\& FINISH: -\& \- Reset the ev_break status iff it was EVBREAK_ONE. -\& \- Decrement the loop depth. -\& \- Return. -.Ve -.Sp -Example: Queue some jobs and then loop until no events are outstanding -anymore. -.Sp -.Vb 4 -\& ... queue jobs here, make sure they register event watchers as long -\& ... as they still have work to do (even an idle watcher will do..) -\& ev_run (my_loop, 0); -\& ... jobs done or somebody called break. yeah! -.Ve -.IP "ev_break (loop, how)" 4 -.IX Item "ev_break (loop, how)" -Can be used to make a call to \f(CW\*(C`ev_run\*(C'\fR return early (but only after it -has processed all outstanding events). The \f(CW\*(C`how\*(C'\fR argument must be either -\&\f(CW\*(C`EVBREAK_ONE\*(C'\fR, which will make the innermost \f(CW\*(C`ev_run\*(C'\fR call return, or -\&\f(CW\*(C`EVBREAK_ALL\*(C'\fR, which will make all nested \f(CW\*(C`ev_run\*(C'\fR calls return. -.Sp -This \*(L"break state\*(R" will be cleared on the next call to \f(CW\*(C`ev_run\*(C'\fR. -.Sp -It is safe to call \f(CW\*(C`ev_break\*(C'\fR from outside any \f(CW\*(C`ev_run\*(C'\fR calls, too, in -which case it will have no effect. -.IP "ev_ref (loop)" 4 -.IX Item "ev_ref (loop)" -.PD 0 -.IP "ev_unref (loop)" 4 -.IX Item "ev_unref (loop)" -.PD -Ref/unref can be used to add or remove a reference count on the event -loop: Every watcher keeps one reference, and as long as the reference -count is nonzero, \f(CW\*(C`ev_run\*(C'\fR will not return on its own. -.Sp -This is useful when you have a watcher that you never intend to -unregister, but that nevertheless should not keep \f(CW\*(C`ev_run\*(C'\fR from -returning. In such a case, call \f(CW\*(C`ev_unref\*(C'\fR after starting, and \f(CW\*(C`ev_ref\*(C'\fR -before stopping it. -.Sp -As an example, libev itself uses this for its internal signal pipe: It -is not visible to the libev user and should not keep \f(CW\*(C`ev_run\*(C'\fR from -exiting if no event watchers registered by it are active. It is also an -excellent way to do this for generic recurring timers or from within -third-party libraries. Just remember to \fIunref after start\fR and \fIref -before stop\fR (but only if the watcher wasn't active before, or was active -before, respectively. Note also that libev might stop watchers itself -(e.g. non-repeating timers) in which case you have to \f(CW\*(C`ev_ref\*(C'\fR -in the callback). -.Sp -Example: Create a signal watcher, but keep it from keeping \f(CW\*(C`ev_run\*(C'\fR -running when nothing else is active. -.Sp -.Vb 4 -\& ev_signal exitsig; -\& ev_signal_init (&exitsig, sig_cb, SIGINT); -\& ev_signal_start (loop, &exitsig); -\& ev_unref (loop); -.Ve -.Sp -Example: For some weird reason, unregister the above signal handler again. -.Sp -.Vb 2 -\& ev_ref (loop); -\& ev_signal_stop (loop, &exitsig); -.Ve -.IP "ev_set_io_collect_interval (loop, ev_tstamp interval)" 4 -.IX Item "ev_set_io_collect_interval (loop, ev_tstamp interval)" -.PD 0 -.IP "ev_set_timeout_collect_interval (loop, ev_tstamp interval)" 4 -.IX Item "ev_set_timeout_collect_interval (loop, ev_tstamp interval)" -.PD -These advanced functions influence the time that libev will spend waiting -for events. Both time intervals are by default \f(CW0\fR, meaning that libev -will try to invoke timer/periodic callbacks and I/O callbacks with minimum -latency. -.Sp -Setting these to a higher value (the \f(CW\*(C`interval\*(C'\fR \fImust\fR be >= \f(CW0\fR) -allows libev to delay invocation of I/O and timer/periodic callbacks -to increase efficiency of loop iterations (or to increase power-saving -opportunities). -.Sp -The idea is that sometimes your program runs just fast enough to handle -one (or very few) event(s) per loop iteration. While this makes the -program responsive, it also wastes a lot of \s-1CPU\s0 time to poll for new -events, especially with backends like \f(CW\*(C`select ()\*(C'\fR which have a high -overhead for the actual polling but can deliver many events at once. -.Sp -By setting a higher \fIio collect interval\fR you allow libev to spend more -time collecting I/O events, so you can handle more events per iteration, -at the cost of increasing latency. Timeouts (both \f(CW\*(C`ev_periodic\*(C'\fR and -\&\f(CW\*(C`ev_timer\*(C'\fR) will not be affected. Setting this to a non-null value will -introduce an additional \f(CW\*(C`ev_sleep ()\*(C'\fR call into most loop iterations. The -sleep time ensures that libev will not poll for I/O events more often then -once per this interval, on average (as long as the host time resolution is -good enough). -.Sp -Likewise, by setting a higher \fItimeout collect interval\fR you allow libev -to spend more time collecting timeouts, at the expense of increased -latency/jitter/inexactness (the watcher callback will be called -later). \f(CW\*(C`ev_io\*(C'\fR watchers will not be affected. Setting this to a non-null -value will not introduce any overhead in libev. -.Sp -Many (busy) programs can usually benefit by setting the I/O collect -interval to a value near \f(CW0.1\fR or so, which is often enough for -interactive servers (of course not for games), likewise for timeouts. It -usually doesn't make much sense to set it to a lower value than \f(CW0.01\fR, -as this approaches the timing granularity of most systems. Note that if -you do transactions with the outside world and you can't increase the -parallelity, then this setting will limit your transaction rate (if you -need to poll once per transaction and the I/O collect interval is 0.01, -then you can't do more than 100 transactions per second). -.Sp -Setting the \fItimeout collect interval\fR can improve the opportunity for -saving power, as the program will \*(L"bundle\*(R" timer callback invocations that -are \*(L"near\*(R" in time together, by delaying some, thus reducing the number of -times the process sleeps and wakes up again. Another useful technique to -reduce iterations/wake\-ups is to use \f(CW\*(C`ev_periodic\*(C'\fR watchers and make sure -they fire on, say, one-second boundaries only. -.Sp -Example: we only need 0.1s timeout granularity, and we wish not to poll -more often than 100 times per second: -.Sp -.Vb 2 -\& ev_set_timeout_collect_interval (EV_DEFAULT_UC_ 0.1); -\& ev_set_io_collect_interval (EV_DEFAULT_UC_ 0.01); -.Ve -.IP "ev_invoke_pending (loop)" 4 -.IX Item "ev_invoke_pending (loop)" -This call will simply invoke all pending watchers while resetting their -pending state. Normally, \f(CW\*(C`ev_run\*(C'\fR does this automatically when required, -but when overriding the invoke callback this call comes handy. This -function can be invoked from a watcher \- this can be useful for example -when you want to do some lengthy calculation and want to pass further -event handling to another thread (you still have to make sure only one -thread executes within \f(CW\*(C`ev_invoke_pending\*(C'\fR or \f(CW\*(C`ev_run\*(C'\fR of course). -.IP "int ev_pending_count (loop)" 4 -.IX Item "int ev_pending_count (loop)" -Returns the number of pending watchers \- zero indicates that no watchers -are pending. -.IP "ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(\s-1EV_P\s0))" 4 -.IX Item "ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(EV_P))" -This overrides the invoke pending functionality of the loop: Instead of -invoking all pending watchers when there are any, \f(CW\*(C`ev_run\*(C'\fR will call -this callback instead. This is useful, for example, when you want to -invoke the actual watchers inside another context (another thread etc.). -.Sp -If you want to reset the callback, use \f(CW\*(C`ev_invoke_pending\*(C'\fR as new -callback. -.IP "ev_set_loop_release_cb (loop, void (*release)(\s-1EV_P\s0) throw (), void (*acquire)(\s-1EV_P\s0) throw ())" 4 -.IX Item "ev_set_loop_release_cb (loop, void (*release)(EV_P) throw (), void (*acquire)(EV_P) throw ())" -Sometimes you want to share the same loop between multiple threads. This -can be done relatively simply by putting mutex_lock/unlock calls around -each call to a libev function. -.Sp -However, \f(CW\*(C`ev_run\*(C'\fR can run an indefinite time, so it is not feasible -to wait for it to return. One way around this is to wake up the event -loop via \f(CW\*(C`ev_break\*(C'\fR and \f(CW\*(C`ev_async_send\*(C'\fR, another way is to set these -\&\fIrelease\fR and \fIacquire\fR callbacks on the loop. -.Sp -When set, then \f(CW\*(C`release\*(C'\fR will be called just before the thread is -suspended waiting for new events, and \f(CW\*(C`acquire\*(C'\fR is called just -afterwards. -.Sp -Ideally, \f(CW\*(C`release\*(C'\fR will just call your mutex_unlock function, and -\&\f(CW\*(C`acquire\*(C'\fR will just call the mutex_lock function again. -.Sp -While event loop modifications are allowed between invocations of -\&\f(CW\*(C`release\*(C'\fR and \f(CW\*(C`acquire\*(C'\fR (that's their only purpose after all), no -modifications done will affect the event loop, i.e. adding watchers will -have no effect on the set of file descriptors being watched, or the time -waited. Use an \f(CW\*(C`ev_async\*(C'\fR watcher to wake up \f(CW\*(C`ev_run\*(C'\fR when you want it -to take note of any changes you made. -.Sp -In theory, threads executing \f(CW\*(C`ev_run\*(C'\fR will be async-cancel safe between -invocations of \f(CW\*(C`release\*(C'\fR and \f(CW\*(C`acquire\*(C'\fR. -.Sp -See also the locking example in the \f(CW\*(C`THREADS\*(C'\fR section later in this -document. -.IP "ev_set_userdata (loop, void *data)" 4 -.IX Item "ev_set_userdata (loop, void *data)" -.PD 0 -.IP "void *ev_userdata (loop)" 4 -.IX Item "void *ev_userdata (loop)" -.PD -Set and retrieve a single \f(CW\*(C`void *\*(C'\fR associated with a loop. When -\&\f(CW\*(C`ev_set_userdata\*(C'\fR has never been called, then \f(CW\*(C`ev_userdata\*(C'\fR returns -\&\f(CW0\fR. -.Sp -These two functions can be used to associate arbitrary data with a loop, -and are intended solely for the \f(CW\*(C`invoke_pending_cb\*(C'\fR, \f(CW\*(C`release\*(C'\fR and -\&\f(CW\*(C`acquire\*(C'\fR callbacks described above, but of course can be (ab\-)used for -any other purpose as well. -.IP "ev_verify (loop)" 4 -.IX Item "ev_verify (loop)" -This function only does something when \f(CW\*(C`EV_VERIFY\*(C'\fR support has been -compiled in, which is the default for non-minimal builds. It tries to go -through all internal structures and checks them for validity. If anything -is found to be inconsistent, it will print an error message to standard -error and call \f(CW\*(C`abort ()\*(C'\fR. -.Sp -This can be used to catch bugs inside libev itself: under normal -circumstances, this function will never abort as of course libev keeps its -data structures consistent. -.SH "ANATOMY OF A WATCHER" -.IX Header "ANATOMY OF A WATCHER" -In the following description, uppercase \f(CW\*(C`TYPE\*(C'\fR in names stands for the -watcher type, e.g. \f(CW\*(C`ev_TYPE_start\*(C'\fR can mean \f(CW\*(C`ev_timer_start\*(C'\fR for timer -watchers and \f(CW\*(C`ev_io_start\*(C'\fR for I/O watchers. -.PP -A watcher is an opaque structure that you allocate and register to record -your interest in some event. To make a concrete example, imagine you want -to wait for \s-1STDIN\s0 to become readable, you would create an \f(CW\*(C`ev_io\*(C'\fR watcher -for that: -.PP -.Vb 5 -\& static void my_cb (struct ev_loop *loop, ev_io *w, int revents) -\& { -\& ev_io_stop (w); -\& ev_break (loop, EVBREAK_ALL); -\& } -\& -\& struct ev_loop *loop = ev_default_loop (0); -\& -\& ev_io stdin_watcher; -\& -\& ev_init (&stdin_watcher, my_cb); -\& ev_io_set (&stdin_watcher, STDIN_FILENO, EV_READ); -\& ev_io_start (loop, &stdin_watcher); -\& -\& ev_run (loop, 0); -.Ve -.PP -As you can see, you are responsible for allocating the memory for your -watcher structures (and it is \fIusually\fR a bad idea to do this on the -stack). -.PP -Each watcher has an associated watcher structure (called \f(CW\*(C`struct ev_TYPE\*(C'\fR -or simply \f(CW\*(C`ev_TYPE\*(C'\fR, as typedefs are provided for all watcher structs). -.PP -Each watcher structure must be initialised by a call to \f(CW\*(C`ev_init (watcher -*, callback)\*(C'\fR, which expects a callback to be provided. This callback is -invoked each time the event occurs (or, in the case of I/O watchers, each -time the event loop detects that the file descriptor given is readable -and/or writable). -.PP -Each watcher type further has its own \f(CW\*(C`ev_TYPE_set (watcher *, ...)\*(C'\fR -macro to configure it, with arguments specific to the watcher type. There -is also a macro to combine initialisation and setting in one call: \f(CW\*(C`ev_TYPE_init (watcher *, callback, ...)\*(C'\fR. -.PP -To make the watcher actually watch out for events, you have to start it -with a watcher-specific start function (\f(CW\*(C`ev_TYPE_start (loop, watcher -*)\*(C'\fR), and you can stop watching for events at any time by calling the -corresponding stop function (\f(CW\*(C`ev_TYPE_stop (loop, watcher *)\*(C'\fR. -.PP -As long as your watcher is active (has been started but not stopped) you -must not touch the values stored in it. Most specifically you must never -reinitialise it or call its \f(CW\*(C`ev_TYPE_set\*(C'\fR macro. -.PP -Each and every callback receives the event loop pointer as first, the -registered watcher structure as second, and a bitset of received events as -third argument. -.PP -The received events usually include a single bit per event type received -(you can receive multiple events at the same time). The possible bit masks -are: -.ie n .IP """EV_READ""" 4 -.el .IP "\f(CWEV_READ\fR" 4 -.IX Item "EV_READ" -.PD 0 -.ie n .IP """EV_WRITE""" 4 -.el .IP "\f(CWEV_WRITE\fR" 4 -.IX Item "EV_WRITE" -.PD -The file descriptor in the \f(CW\*(C`ev_io\*(C'\fR watcher has become readable and/or -writable. -.ie n .IP """EV_TIMER""" 4 -.el .IP "\f(CWEV_TIMER\fR" 4 -.IX Item "EV_TIMER" -The \f(CW\*(C`ev_timer\*(C'\fR watcher has timed out. -.ie n .IP """EV_PERIODIC""" 4 -.el .IP "\f(CWEV_PERIODIC\fR" 4 -.IX Item "EV_PERIODIC" -The \f(CW\*(C`ev_periodic\*(C'\fR watcher has timed out. -.ie n .IP """EV_SIGNAL""" 4 -.el .IP "\f(CWEV_SIGNAL\fR" 4 -.IX Item "EV_SIGNAL" -The signal specified in the \f(CW\*(C`ev_signal\*(C'\fR watcher has been received by a thread. -.ie n .IP """EV_CHILD""" 4 -.el .IP "\f(CWEV_CHILD\fR" 4 -.IX Item "EV_CHILD" -The pid specified in the \f(CW\*(C`ev_child\*(C'\fR watcher has received a status change. -.ie n .IP """EV_STAT""" 4 -.el .IP "\f(CWEV_STAT\fR" 4 -.IX Item "EV_STAT" -The path specified in the \f(CW\*(C`ev_stat\*(C'\fR watcher changed its attributes somehow. -.ie n .IP """EV_IDLE""" 4 -.el .IP "\f(CWEV_IDLE\fR" 4 -.IX Item "EV_IDLE" -The \f(CW\*(C`ev_idle\*(C'\fR watcher has determined that you have nothing better to do. -.ie n .IP """EV_PREPARE""" 4 -.el .IP "\f(CWEV_PREPARE\fR" 4 -.IX Item "EV_PREPARE" -.PD 0 -.ie n .IP """EV_CHECK""" 4 -.el .IP "\f(CWEV_CHECK\fR" 4 -.IX Item "EV_CHECK" -.PD -All \f(CW\*(C`ev_prepare\*(C'\fR watchers are invoked just \fIbefore\fR \f(CW\*(C`ev_run\*(C'\fR starts to -gather new events, and all \f(CW\*(C`ev_check\*(C'\fR watchers are queued (not invoked) -just after \f(CW\*(C`ev_run\*(C'\fR has gathered them, but before it queues any callbacks -for any received events. That means \f(CW\*(C`ev_prepare\*(C'\fR watchers are the last -watchers invoked before the event loop sleeps or polls for new events, and -\&\f(CW\*(C`ev_check\*(C'\fR watchers will be invoked before any other watchers of the same -or lower priority within an event loop iteration. -.Sp -Callbacks of both watcher types can start and stop as many watchers as -they want, and all of them will be taken into account (for example, a -\&\f(CW\*(C`ev_prepare\*(C'\fR watcher might start an idle watcher to keep \f(CW\*(C`ev_run\*(C'\fR from -blocking). -.ie n .IP """EV_EMBED""" 4 -.el .IP "\f(CWEV_EMBED\fR" 4 -.IX Item "EV_EMBED" -The embedded event loop specified in the \f(CW\*(C`ev_embed\*(C'\fR watcher needs attention. -.ie n .IP """EV_FORK""" 4 -.el .IP "\f(CWEV_FORK\fR" 4 -.IX Item "EV_FORK" -The event loop has been resumed in the child process after fork (see -\&\f(CW\*(C`ev_fork\*(C'\fR). -.ie n .IP """EV_CLEANUP""" 4 -.el .IP "\f(CWEV_CLEANUP\fR" 4 -.IX Item "EV_CLEANUP" -The event loop is about to be destroyed (see \f(CW\*(C`ev_cleanup\*(C'\fR). -.ie n .IP """EV_ASYNC""" 4 -.el .IP "\f(CWEV_ASYNC\fR" 4 -.IX Item "EV_ASYNC" -The given async watcher has been asynchronously notified (see \f(CW\*(C`ev_async\*(C'\fR). -.ie n .IP """EV_CUSTOM""" 4 -.el .IP "\f(CWEV_CUSTOM\fR" 4 -.IX Item "EV_CUSTOM" -Not ever sent (or otherwise used) by libev itself, but can be freely used -by libev users to signal watchers (e.g. via \f(CW\*(C`ev_feed_event\*(C'\fR). -.ie n .IP """EV_ERROR""" 4 -.el .IP "\f(CWEV_ERROR\fR" 4 -.IX Item "EV_ERROR" -An unspecified error has occurred, the watcher has been stopped. This might -happen because the watcher could not be properly started because libev -ran out of memory, a file descriptor was found to be closed or any other -problem. Libev considers these application bugs. -.Sp -You best act on it by reporting the problem and somehow coping with the -watcher being stopped. Note that well-written programs should not receive -an error ever, so when your watcher receives it, this usually indicates a -bug in your program. -.Sp -Libev will usually signal a few \*(L"dummy\*(R" events together with an error, for -example it might indicate that a fd is readable or writable, and if your -callbacks is well-written it can just attempt the operation and cope with -the error from \fIread()\fR or \fIwrite()\fR. This will not work in multi-threaded -programs, though, as the fd could already be closed and reused for another -thing, so beware. -.SS "\s-1GENERIC\s0 \s-1WATCHER\s0 \s-1FUNCTIONS\s0" -.IX Subsection "GENERIC WATCHER FUNCTIONS" -.ie n .IP """ev_init"" (ev_TYPE *watcher, callback)" 4 -.el .IP "\f(CWev_init\fR (ev_TYPE *watcher, callback)" 4 -.IX Item "ev_init (ev_TYPE *watcher, callback)" -This macro initialises the generic portion of a watcher. The contents -of the watcher object can be arbitrary (so \f(CW\*(C`malloc\*(C'\fR will do). Only -the generic parts of the watcher are initialised, you \fIneed\fR to call -the type-specific \f(CW\*(C`ev_TYPE_set\*(C'\fR macro afterwards to initialise the -type-specific parts. For each type there is also a \f(CW\*(C`ev_TYPE_init\*(C'\fR macro -which rolls both calls into one. -.Sp -You can reinitialise a watcher at any time as long as it has been stopped -(or never started) and there are no pending events outstanding. -.Sp -The callback is always of type \f(CW\*(C`void (*)(struct ev_loop *loop, ev_TYPE *watcher, -int revents)\*(C'\fR. -.Sp -Example: Initialise an \f(CW\*(C`ev_io\*(C'\fR watcher in two steps. -.Sp -.Vb 3 -\& ev_io w; -\& ev_init (&w, my_cb); -\& ev_io_set (&w, STDIN_FILENO, EV_READ); -.Ve -.ie n .IP """ev_TYPE_set"" (ev_TYPE *watcher, [args])" 4 -.el .IP "\f(CWev_TYPE_set\fR (ev_TYPE *watcher, [args])" 4 -.IX Item "ev_TYPE_set (ev_TYPE *watcher, [args])" -This macro initialises the type-specific parts of a watcher. You need to -call \f(CW\*(C`ev_init\*(C'\fR at least once before you call this macro, but you can -call \f(CW\*(C`ev_TYPE_set\*(C'\fR any number of times. You must not, however, call this -macro on a watcher that is active (it can be pending, however, which is a -difference to the \f(CW\*(C`ev_init\*(C'\fR macro). -.Sp -Although some watcher types do not have type-specific arguments -(e.g. \f(CW\*(C`ev_prepare\*(C'\fR) you still need to call its \f(CW\*(C`set\*(C'\fR macro. -.Sp -See \f(CW\*(C`ev_init\*(C'\fR, above, for an example. -.ie n .IP """ev_TYPE_init"" (ev_TYPE *watcher, callback, [args])" 4 -.el .IP "\f(CWev_TYPE_init\fR (ev_TYPE *watcher, callback, [args])" 4 -.IX Item "ev_TYPE_init (ev_TYPE *watcher, callback, [args])" -This convenience macro rolls both \f(CW\*(C`ev_init\*(C'\fR and \f(CW\*(C`ev_TYPE_set\*(C'\fR macro -calls into a single call. This is the most convenient method to initialise -a watcher. The same limitations apply, of course. -.Sp -Example: Initialise and set an \f(CW\*(C`ev_io\*(C'\fR watcher in one step. -.Sp -.Vb 1 -\& ev_io_init (&w, my_cb, STDIN_FILENO, EV_READ); -.Ve -.ie n .IP """ev_TYPE_start"" (loop, ev_TYPE *watcher)" 4 -.el .IP "\f(CWev_TYPE_start\fR (loop, ev_TYPE *watcher)" 4 -.IX Item "ev_TYPE_start (loop, ev_TYPE *watcher)" -Starts (activates) the given watcher. Only active watchers will receive -events. If the watcher is already active nothing will happen. -.Sp -Example: Start the \f(CW\*(C`ev_io\*(C'\fR watcher that is being abused as example in this -whole section. -.Sp -.Vb 1 -\& ev_io_start (EV_DEFAULT_UC, &w); -.Ve -.ie n .IP """ev_TYPE_stop"" (loop, ev_TYPE *watcher)" 4 -.el .IP "\f(CWev_TYPE_stop\fR (loop, ev_TYPE *watcher)" 4 -.IX Item "ev_TYPE_stop (loop, ev_TYPE *watcher)" -Stops the given watcher if active, and clears the pending status (whether -the watcher was active or not). -.Sp -It is possible that stopped watchers are pending \- for example, -non-repeating timers are being stopped when they become pending \- but -calling \f(CW\*(C`ev_TYPE_stop\*(C'\fR ensures that the watcher is neither active nor -pending. If you want to free or reuse the memory used by the watcher it is -therefore a good idea to always call its \f(CW\*(C`ev_TYPE_stop\*(C'\fR function. -.IP "bool ev_is_active (ev_TYPE *watcher)" 4 -.IX Item "bool ev_is_active (ev_TYPE *watcher)" -Returns a true value iff the watcher is active (i.e. it has been started -and not yet been stopped). As long as a watcher is active you must not modify -it. -.IP "bool ev_is_pending (ev_TYPE *watcher)" 4 -.IX Item "bool ev_is_pending (ev_TYPE *watcher)" -Returns a true value iff the watcher is pending, (i.e. it has outstanding -events but its callback has not yet been invoked). As long as a watcher -is pending (but not active) you must not call an init function on it (but -\&\f(CW\*(C`ev_TYPE_set\*(C'\fR is safe), you must not change its priority, and you must -make sure the watcher is available to libev (e.g. you cannot \f(CW\*(C`free ()\*(C'\fR -it). -.IP "callback ev_cb (ev_TYPE *watcher)" 4 -.IX Item "callback ev_cb (ev_TYPE *watcher)" -Returns the callback currently set on the watcher. -.IP "ev_set_cb (ev_TYPE *watcher, callback)" 4 -.IX Item "ev_set_cb (ev_TYPE *watcher, callback)" -Change the callback. You can change the callback at virtually any time -(modulo threads). -.IP "ev_set_priority (ev_TYPE *watcher, int priority)" 4 -.IX Item "ev_set_priority (ev_TYPE *watcher, int priority)" -.PD 0 -.IP "int ev_priority (ev_TYPE *watcher)" 4 -.IX Item "int ev_priority (ev_TYPE *watcher)" -.PD -Set and query the priority of the watcher. The priority is a small -integer between \f(CW\*(C`EV_MAXPRI\*(C'\fR (default: \f(CW2\fR) and \f(CW\*(C`EV_MINPRI\*(C'\fR -(default: \f(CW\*(C`\-2\*(C'\fR). Pending watchers with higher priority will be invoked -before watchers with lower priority, but priority will not keep watchers -from being executed (except for \f(CW\*(C`ev_idle\*(C'\fR watchers). -.Sp -If you need to suppress invocation when higher priority events are pending -you need to look at \f(CW\*(C`ev_idle\*(C'\fR watchers, which provide this functionality. -.Sp -You \fImust not\fR change the priority of a watcher as long as it is active or -pending. -.Sp -Setting a priority outside the range of \f(CW\*(C`EV_MINPRI\*(C'\fR to \f(CW\*(C`EV_MAXPRI\*(C'\fR is -fine, as long as you do not mind that the priority value you query might -or might not have been clamped to the valid range. -.Sp -The default priority used by watchers when no priority has been set is -always \f(CW0\fR, which is supposed to not be too high and not be too low :). -.Sp -See \*(L"\s-1WATCHER\s0 \s-1PRIORITY\s0 \s-1MODELS\s0\*(R", below, for a more thorough treatment of -priorities. -.IP "ev_invoke (loop, ev_TYPE *watcher, int revents)" 4 -.IX Item "ev_invoke (loop, ev_TYPE *watcher, int revents)" -Invoke the \f(CW\*(C`watcher\*(C'\fR with the given \f(CW\*(C`loop\*(C'\fR and \f(CW\*(C`revents\*(C'\fR. Neither -\&\f(CW\*(C`loop\*(C'\fR nor \f(CW\*(C`revents\*(C'\fR need to be valid as long as the watcher callback -can deal with that fact, as both are simply passed through to the -callback. -.IP "int ev_clear_pending (loop, ev_TYPE *watcher)" 4 -.IX Item "int ev_clear_pending (loop, ev_TYPE *watcher)" -If the watcher is pending, this function clears its pending status and -returns its \f(CW\*(C`revents\*(C'\fR bitset (as if its callback was invoked). If the -watcher isn't pending it does nothing and returns \f(CW0\fR. -.Sp -Sometimes it can be useful to \*(L"poll\*(R" a watcher instead of waiting for its -callback to be invoked, which can be accomplished with this function. -.IP "ev_feed_event (loop, ev_TYPE *watcher, int revents)" 4 -.IX Item "ev_feed_event (loop, ev_TYPE *watcher, int revents)" -Feeds the given event set into the event loop, as if the specified event -had happened for the specified watcher (which must be a pointer to an -initialised but not necessarily started event watcher). Obviously you must -not free the watcher as long as it has pending events. -.Sp -Stopping the watcher, letting libev invoke it, or calling -\&\f(CW\*(C`ev_clear_pending\*(C'\fR will clear the pending event, even if the watcher was -not started in the first place. -.Sp -See also \f(CW\*(C`ev_feed_fd_event\*(C'\fR and \f(CW\*(C`ev_feed_signal_event\*(C'\fR for related -functions that do not need a watcher. -.PP -See also the \*(L"\s-1ASSOCIATING\s0 \s-1CUSTOM\s0 \s-1DATA\s0 \s-1WITH\s0 A \s-1WATCHER\s0\*(R" and \*(L"\s-1BUILDING\s0 \s-1YOUR\s0 -\&\s-1OWN\s0 \s-1COMPOSITE\s0 \s-1WATCHERS\s0\*(R" idioms. -.SS "\s-1WATCHER\s0 \s-1STATES\s0" -.IX Subsection "WATCHER STATES" -There are various watcher states mentioned throughout this manual \- -active, pending and so on. In this section these states and the rules to -transition between them will be described in more detail \- and while these -rules might look complicated, they usually do \*(L"the right thing\*(R". -.IP "initialised" 4 -.IX Item "initialised" -Before a watcher can be registered with the event loop it has to be -initialised. This can be done with a call to \f(CW\*(C`ev_TYPE_init\*(C'\fR, or calls to -\&\f(CW\*(C`ev_init\*(C'\fR followed by the watcher-specific \f(CW\*(C`ev_TYPE_set\*(C'\fR function. -.Sp -In this state it is simply some block of memory that is suitable for -use in an event loop. It can be moved around, freed, reused etc. at -will \- as long as you either keep the memory contents intact, or call -\&\f(CW\*(C`ev_TYPE_init\*(C'\fR again. -.IP "started/running/active" 4 -.IX Item "started/running/active" -Once a watcher has been started with a call to \f(CW\*(C`ev_TYPE_start\*(C'\fR it becomes -property of the event loop, and is actively waiting for events. While in -this state it cannot be accessed (except in a few documented ways), moved, -freed or anything else \- the only legal thing is to keep a pointer to it, -and call libev functions on it that are documented to work on active watchers. -.IP "pending" 4 -.IX Item "pending" -If a watcher is active and libev determines that an event it is interested -in has occurred (such as a timer expiring), it will become pending. It will -stay in this pending state until either it is stopped or its callback is -about to be invoked, so it is not normally pending inside the watcher -callback. -.Sp -The watcher might or might not be active while it is pending (for example, -an expired non-repeating timer can be pending but no longer active). If it -is stopped, it can be freely accessed (e.g. by calling \f(CW\*(C`ev_TYPE_set\*(C'\fR), -but it is still property of the event loop at this time, so cannot be -moved, freed or reused. And if it is active the rules described in the -previous item still apply. -.Sp -It is also possible to feed an event on a watcher that is not active (e.g. -via \f(CW\*(C`ev_feed_event\*(C'\fR), in which case it becomes pending without being -active. -.IP "stopped" 4 -.IX Item "stopped" -A watcher can be stopped implicitly by libev (in which case it might still -be pending), or explicitly by calling its \f(CW\*(C`ev_TYPE_stop\*(C'\fR function. The -latter will clear any pending state the watcher might be in, regardless -of whether it was active or not, so stopping a watcher explicitly before -freeing it is often a good idea. -.Sp -While stopped (and not pending) the watcher is essentially in the -initialised state, that is, it can be reused, moved, modified in any way -you wish (but when you trash the memory block, you need to \f(CW\*(C`ev_TYPE_init\*(C'\fR -it again). -.SS "\s-1WATCHER\s0 \s-1PRIORITY\s0 \s-1MODELS\s0" -.IX Subsection "WATCHER PRIORITY MODELS" -Many event loops support \fIwatcher priorities\fR, which are usually small -integers that influence the ordering of event callback invocation -between watchers in some way, all else being equal. -.PP -In libev, Watcher priorities can be set using \f(CW\*(C`ev_set_priority\*(C'\fR. See its -description for the more technical details such as the actual priority -range. -.PP -There are two common ways how these these priorities are being interpreted -by event loops: -.PP -In the more common lock-out model, higher priorities \*(L"lock out\*(R" invocation -of lower priority watchers, which means as long as higher priority -watchers receive events, lower priority watchers are not being invoked. -.PP -The less common only-for-ordering model uses priorities solely to order -callback invocation within a single event loop iteration: Higher priority -watchers are invoked before lower priority ones, but they all get invoked -before polling for new events. -.PP -Libev uses the second (only-for-ordering) model for all its watchers -except for idle watchers (which use the lock-out model). -.PP -The rationale behind this is that implementing the lock-out model for -watchers is not well supported by most kernel interfaces, and most event -libraries will just poll for the same events again and again as long as -their callbacks have not been executed, which is very inefficient in the -common case of one high-priority watcher locking out a mass of lower -priority ones. -.PP -Static (ordering) priorities are most useful when you have two or more -watchers handling the same resource: a typical usage example is having an -\&\f(CW\*(C`ev_io\*(C'\fR watcher to receive data, and an associated \f(CW\*(C`ev_timer\*(C'\fR to handle -timeouts. Under load, data might be received while the program handles -other jobs, but since timers normally get invoked first, the timeout -handler will be executed before checking for data. In that case, giving -the timer a lower priority than the I/O watcher ensures that I/O will be -handled first even under adverse conditions (which is usually, but not -always, what you want). -.PP -Since idle watchers use the \*(L"lock-out\*(R" model, meaning that idle watchers -will only be executed when no same or higher priority watchers have -received events, they can be used to implement the \*(L"lock-out\*(R" model when -required. -.PP -For example, to emulate how many other event libraries handle priorities, -you can associate an \f(CW\*(C`ev_idle\*(C'\fR watcher to each such watcher, and in -the normal watcher callback, you just start the idle watcher. The real -processing is done in the idle watcher callback. This causes libev to -continuously poll and process kernel event data for the watcher, but when -the lock-out case is known to be rare (which in turn is rare :), this is -workable. -.PP -Usually, however, the lock-out model implemented that way will perform -miserably under the type of load it was designed to handle. In that case, -it might be preferable to stop the real watcher before starting the -idle watcher, so the kernel will not have to process the event in case -the actual processing will be delayed for considerable time. -.PP -Here is an example of an I/O watcher that should run at a strictly lower -priority than the default, and which should only process data when no -other events are pending: -.PP -.Vb 2 -\& ev_idle idle; // actual processing watcher -\& ev_io io; // actual event watcher -\& -\& static void -\& io_cb (EV_P_ ev_io *w, int revents) -\& { -\& // stop the I/O watcher, we received the event, but -\& // are not yet ready to handle it. -\& ev_io_stop (EV_A_ w); -\& -\& // start the idle watcher to handle the actual event. -\& // it will not be executed as long as other watchers -\& // with the default priority are receiving events. -\& ev_idle_start (EV_A_ &idle); -\& } -\& -\& static void -\& idle_cb (EV_P_ ev_idle *w, int revents) -\& { -\& // actual processing -\& read (STDIN_FILENO, ...); -\& -\& // have to start the I/O watcher again, as -\& // we have handled the event -\& ev_io_start (EV_P_ &io); -\& } -\& -\& // initialisation -\& ev_idle_init (&idle, idle_cb); -\& ev_io_init (&io, io_cb, STDIN_FILENO, EV_READ); -\& ev_io_start (EV_DEFAULT_ &io); -.Ve -.PP -In the \*(L"real\*(R" world, it might also be beneficial to start a timer, so that -low-priority connections can not be locked out forever under load. This -enables your program to keep a lower latency for important connections -during short periods of high load, while not completely locking out less -important ones. -.SH "WATCHER TYPES" -.IX Header "WATCHER TYPES" -This section describes each watcher in detail, but will not repeat -information given in the last section. Any initialisation/set macros, -functions and members specific to the watcher type are explained. -.PP -Members are additionally marked with either \fI[read\-only]\fR, meaning that, -while the watcher is active, you can look at the member and expect some -sensible content, but you must not modify it (you can modify it while the -watcher is stopped to your hearts content), or \fI[read\-write]\fR, which -means you can expect it to have some sensible content while the watcher -is active, but you can also modify it. Modifying it may not do something -sensible or take immediate effect (or do anything at all), but libev will -not crash or malfunction in any way. -.ie n .SS """ev_io"" \- is this file descriptor readable or writable?" -.el .SS "\f(CWev_io\fP \- is this file descriptor readable or writable?" -.IX Subsection "ev_io - is this file descriptor readable or writable?" -I/O watchers check whether a file descriptor is readable or writable -in each iteration of the event loop, or, more precisely, when reading -would not block the process and writing would at least be able to write -some data. This behaviour is called level-triggering because you keep -receiving events as long as the condition persists. Remember you can stop -the watcher if you don't want to act on the event and neither want to -receive future events. -.PP -In general you can register as many read and/or write event watchers per -fd as you want (as long as you don't confuse yourself). Setting all file -descriptors to non-blocking mode is also usually a good idea (but not -required if you know what you are doing). -.PP -Another thing you have to watch out for is that it is quite easy to -receive \*(L"spurious\*(R" readiness notifications, that is, your callback might -be called with \f(CW\*(C`EV_READ\*(C'\fR but a subsequent \f(CW\*(C`read\*(C'\fR(2) will actually block -because there is no data. It is very easy to get into this situation even -with a relatively standard program structure. Thus it is best to always -use non-blocking I/O: An extra \f(CW\*(C`read\*(C'\fR(2) returning \f(CW\*(C`EAGAIN\*(C'\fR is far -preferable to a program hanging until some data arrives. -.PP -If you cannot run the fd in non-blocking mode (for example you should -not play around with an Xlib connection), then you have to separately -re-test whether a file descriptor is really ready with a known-to-be good -interface such as poll (fortunately in the case of Xlib, it already does -this on its own, so its quite safe to use). Some people additionally -use \f(CW\*(C`SIGALRM\*(C'\fR and an interval timer, just to be sure you won't block -indefinitely. -.PP -But really, best use non-blocking mode. -.PP -\fIThe special problem of disappearing file descriptors\fR -.IX Subsection "The special problem of disappearing file descriptors" -.PP -Some backends (e.g. kqueue, epoll) need to be told about closing a file -descriptor (either due to calling \f(CW\*(C`close\*(C'\fR explicitly or any other means, -such as \f(CW\*(C`dup2\*(C'\fR). The reason is that you register interest in some file -descriptor, but when it goes away, the operating system will silently drop -this interest. If another file descriptor with the same number then is -registered with libev, there is no efficient way to see that this is, in -fact, a different file descriptor. -.PP -To avoid having to explicitly tell libev about such cases, libev follows -the following policy: Each time \f(CW\*(C`ev_io_set\*(C'\fR is being called, libev -will assume that this is potentially a new file descriptor, otherwise -it is assumed that the file descriptor stays the same. That means that -you \fIhave\fR to call \f(CW\*(C`ev_io_set\*(C'\fR (or \f(CW\*(C`ev_io_init\*(C'\fR) when you change the -descriptor even if the file descriptor number itself did not change. -.PP -This is how one would do it normally anyway, the important point is that -the libev application should not optimise around libev but should leave -optimisations to libev. -.PP -\fIThe special problem of dup'ed file descriptors\fR -.IX Subsection "The special problem of dup'ed file descriptors" -.PP -Some backends (e.g. epoll), cannot register events for file descriptors, -but only events for the underlying file descriptions. That means when you -have \f(CW\*(C`dup ()\*(C'\fR'ed file descriptors or weirder constellations, and register -events for them, only one file descriptor might actually receive events. -.PP -There is no workaround possible except not registering events -for potentially \f(CW\*(C`dup ()\*(C'\fR'ed file descriptors, or to resort to -\&\f(CW\*(C`EVBACKEND_SELECT\*(C'\fR or \f(CW\*(C`EVBACKEND_POLL\*(C'\fR. -.PP -\fIThe special problem of files\fR -.IX Subsection "The special problem of files" -.PP -Many people try to use \f(CW\*(C`select\*(C'\fR (or libev) on file descriptors -representing files, and expect it to become ready when their program -doesn't block on disk accesses (which can take a long time on their own). -.PP -However, this cannot ever work in the \*(L"expected\*(R" way \- you get a readiness -notification as soon as the kernel knows whether and how much data is -there, and in the case of open files, that's always the case, so you -always get a readiness notification instantly, and your read (or possibly -write) will still block on the disk I/O. -.PP -Another way to view it is that in the case of sockets, pipes, character -devices and so on, there is another party (the sender) that delivers data -on its own, but in the case of files, there is no such thing: the disk -will not send data on its own, simply because it doesn't know what you -wish to read \- you would first have to request some data. -.PP -Since files are typically not-so-well supported by advanced notification -mechanism, libev tries hard to emulate \s-1POSIX\s0 behaviour with respect -to files, even though you should not use it. The reason for this is -convenience: sometimes you want to watch \s-1STDIN\s0 or \s-1STDOUT\s0, which is -usually a tty, often a pipe, but also sometimes files or special devices -(for example, \f(CW\*(C`epoll\*(C'\fR on Linux works with \fI/dev/random\fR but not with -\&\fI/dev/urandom\fR), and even though the file might better be served with -asynchronous I/O instead of with non-blocking I/O, it is still useful when -it \*(L"just works\*(R" instead of freezing. -.PP -So avoid file descriptors pointing to files when you know it (e.g. use -libeio), but use them when it is convenient, e.g. for \s-1STDIN/STDOUT\s0, or -when you rarely read from a file instead of from a socket, and want to -reuse the same code path. -.PP -\fIThe special problem of fork\fR -.IX Subsection "The special problem of fork" -.PP -Some backends (epoll, kqueue) do not support \f(CW\*(C`fork ()\*(C'\fR at all or exhibit -useless behaviour. Libev fully supports fork, but needs to be told about -it in the child if you want to continue to use it in the child. -.PP -To support fork in your child processes, you have to call \f(CW\*(C`ev_loop_fork -()\*(C'\fR after a fork in the child, enable \f(CW\*(C`EVFLAG_FORKCHECK\*(C'\fR, or resort to -\&\f(CW\*(C`EVBACKEND_SELECT\*(C'\fR or \f(CW\*(C`EVBACKEND_POLL\*(C'\fR. -.PP -\fIThe special problem of \s-1SIGPIPE\s0\fR -.IX Subsection "The special problem of SIGPIPE" -.PP -While not really specific to libev, it is easy to forget about \f(CW\*(C`SIGPIPE\*(C'\fR: -when writing to a pipe whose other end has been closed, your program gets -sent a \s-1SIGPIPE\s0, which, by default, aborts your program. For most programs -this is sensible behaviour, for daemons, this is usually undesirable. -.PP -So when you encounter spurious, unexplained daemon exits, make sure you -ignore \s-1SIGPIPE\s0 (and maybe make sure you log the exit status of your daemon -somewhere, as that would have given you a big clue). -.PP -\fIThe special problem of \fIaccept()\fIing when you can't\fR -.IX Subsection "The special problem of accept()ing when you can't" -.PP -Many implementations of the \s-1POSIX\s0 \f(CW\*(C`accept\*(C'\fR function (for example, -found in post\-2004 Linux) have the peculiar behaviour of not removing a -connection from the pending queue in all error cases. -.PP -For example, larger servers often run out of file descriptors (because -of resource limits), causing \f(CW\*(C`accept\*(C'\fR to fail with \f(CW\*(C`ENFILE\*(C'\fR but not -rejecting the connection, leading to libev signalling readiness on -the next iteration again (the connection still exists after all), and -typically causing the program to loop at 100% \s-1CPU\s0 usage. -.PP -Unfortunately, the set of errors that cause this issue differs between -operating systems, there is usually little the app can do to remedy the -situation, and no known thread-safe method of removing the connection to -cope with overload is known (to me). -.PP -One of the easiest ways to handle this situation is to just ignore it -\&\- when the program encounters an overload, it will just loop until the -situation is over. While this is a form of busy waiting, no \s-1OS\s0 offers an -event-based way to handle this situation, so it's the best one can do. -.PP -A better way to handle the situation is to log any errors other than -\&\f(CW\*(C`EAGAIN\*(C'\fR and \f(CW\*(C`EWOULDBLOCK\*(C'\fR, making sure not to flood the log with such -messages, and continue as usual, which at least gives the user an idea of -what could be wrong (\*(L"raise the ulimit!\*(R"). For extra points one could stop -the \f(CW\*(C`ev_io\*(C'\fR watcher on the listening fd \*(L"for a while\*(R", which reduces \s-1CPU\s0 -usage. -.PP -If your program is single-threaded, then you could also keep a dummy file -descriptor for overload situations (e.g. by opening \fI/dev/null\fR), and -when you run into \f(CW\*(C`ENFILE\*(C'\fR or \f(CW\*(C`EMFILE\*(C'\fR, close it, run \f(CW\*(C`accept\*(C'\fR, -close that fd, and create a new dummy fd. This will gracefully refuse -clients under typical overload conditions. -.PP -The last way to handle it is to simply log the error and \f(CW\*(C`exit\*(C'\fR, as -is often done with \f(CW\*(C`malloc\*(C'\fR failures, but this results in an easy -opportunity for a DoS attack. -.PP -\fIWatcher-Specific Functions\fR -.IX Subsection "Watcher-Specific Functions" -.IP "ev_io_init (ev_io *, callback, int fd, int events)" 4 -.IX Item "ev_io_init (ev_io *, callback, int fd, int events)" -.PD 0 -.IP "ev_io_set (ev_io *, int fd, int events)" 4 -.IX Item "ev_io_set (ev_io *, int fd, int events)" -.PD -Configures an \f(CW\*(C`ev_io\*(C'\fR watcher. The \f(CW\*(C`fd\*(C'\fR is the file descriptor to -receive events for and \f(CW\*(C`events\*(C'\fR is either \f(CW\*(C`EV_READ\*(C'\fR, \f(CW\*(C`EV_WRITE\*(C'\fR or -\&\f(CW\*(C`EV_READ | EV_WRITE\*(C'\fR, to express the desire to receive the given events. -.IP "int fd [read\-only]" 4 -.IX Item "int fd [read-only]" -The file descriptor being watched. -.IP "int events [read\-only]" 4 -.IX Item "int events [read-only]" -The events being watched. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: Call \f(CW\*(C`stdin_readable_cb\*(C'\fR when \s-1STDIN_FILENO\s0 has become, well -readable, but only once. Since it is likely line-buffered, you could -attempt to read a whole line in the callback. -.PP -.Vb 6 -\& static void -\& stdin_readable_cb (struct ev_loop *loop, ev_io *w, int revents) -\& { -\& ev_io_stop (loop, w); -\& .. read from stdin here (or from w\->fd) and handle any I/O errors -\& } -\& -\& ... -\& struct ev_loop *loop = ev_default_init (0); -\& ev_io stdin_readable; -\& ev_io_init (&stdin_readable, stdin_readable_cb, STDIN_FILENO, EV_READ); -\& ev_io_start (loop, &stdin_readable); -\& ev_run (loop, 0); -.Ve -.ie n .SS """ev_timer"" \- relative and optionally repeating timeouts" -.el .SS "\f(CWev_timer\fP \- relative and optionally repeating timeouts" -.IX Subsection "ev_timer - relative and optionally repeating timeouts" -Timer watchers are simple relative timers that generate an event after a -given time, and optionally repeating in regular intervals after that. -.PP -The timers are based on real time, that is, if you register an event that -times out after an hour and you reset your system clock to January last -year, it will still time out after (roughly) one hour. \*(L"Roughly\*(R" because -detecting time jumps is hard, and some inaccuracies are unavoidable (the -monotonic clock option helps a lot here). -.PP -The callback is guaranteed to be invoked only \fIafter\fR its timeout has -passed (not \fIat\fR, so on systems with very low-resolution clocks this -might introduce a small delay, see \*(L"the special problem of being too -early\*(R", below). If multiple timers become ready during the same loop -iteration then the ones with earlier time-out values are invoked before -ones of the same priority with later time-out values (but this is no -longer true when a callback calls \f(CW\*(C`ev_run\*(C'\fR recursively). -.PP -\fIBe smart about timeouts\fR -.IX Subsection "Be smart about timeouts" -.PP -Many real-world problems involve some kind of timeout, usually for error -recovery. A typical example is an \s-1HTTP\s0 request \- if the other side hangs, -you want to raise some error after a while. -.PP -What follows are some ways to handle this problem, from obvious and -inefficient to smart and efficient. -.PP -In the following, a 60 second activity timeout is assumed \- a timeout that -gets reset to 60 seconds each time there is activity (e.g. each time some -data or other life sign was received). -.IP "1. Use a timer and stop, reinitialise and start it on activity." 4 -.IX Item "1. Use a timer and stop, reinitialise and start it on activity." -This is the most obvious, but not the most simple way: In the beginning, -start the watcher: -.Sp -.Vb 2 -\& ev_timer_init (timer, callback, 60., 0.); -\& ev_timer_start (loop, timer); -.Ve -.Sp -Then, each time there is some activity, \f(CW\*(C`ev_timer_stop\*(C'\fR it, initialise it -and start it again: -.Sp -.Vb 3 -\& ev_timer_stop (loop, timer); -\& ev_timer_set (timer, 60., 0.); -\& ev_timer_start (loop, timer); -.Ve -.Sp -This is relatively simple to implement, but means that each time there is -some activity, libev will first have to remove the timer from its internal -data structure and then add it again. Libev tries to be fast, but it's -still not a constant-time operation. -.ie n .IP "2. Use a timer and re-start it with ""ev_timer_again"" inactivity." 4 -.el .IP "2. Use a timer and re-start it with \f(CWev_timer_again\fR inactivity." 4 -.IX Item "2. Use a timer and re-start it with ev_timer_again inactivity." -This is the easiest way, and involves using \f(CW\*(C`ev_timer_again\*(C'\fR instead of -\&\f(CW\*(C`ev_timer_start\*(C'\fR. -.Sp -To implement this, configure an \f(CW\*(C`ev_timer\*(C'\fR with a \f(CW\*(C`repeat\*(C'\fR value -of \f(CW60\fR and then call \f(CW\*(C`ev_timer_again\*(C'\fR at start and each time you -successfully read or write some data. If you go into an idle state where -you do not expect data to travel on the socket, you can \f(CW\*(C`ev_timer_stop\*(C'\fR -the timer, and \f(CW\*(C`ev_timer_again\*(C'\fR will automatically restart it if need be. -.Sp -That means you can ignore both the \f(CW\*(C`ev_timer_start\*(C'\fR function and the -\&\f(CW\*(C`after\*(C'\fR argument to \f(CW\*(C`ev_timer_set\*(C'\fR, and only ever use the \f(CW\*(C`repeat\*(C'\fR -member and \f(CW\*(C`ev_timer_again\*(C'\fR. -.Sp -At start: -.Sp -.Vb 3 -\& ev_init (timer, callback); -\& timer\->repeat = 60.; -\& ev_timer_again (loop, timer); -.Ve -.Sp -Each time there is some activity: -.Sp -.Vb 1 -\& ev_timer_again (loop, timer); -.Ve -.Sp -It is even possible to change the time-out on the fly, regardless of -whether the watcher is active or not: -.Sp -.Vb 2 -\& timer\->repeat = 30.; -\& ev_timer_again (loop, timer); -.Ve -.Sp -This is slightly more efficient then stopping/starting the timer each time -you want to modify its timeout value, as libev does not have to completely -remove and re-insert the timer from/into its internal data structure. -.Sp -It is, however, even simpler than the \*(L"obvious\*(R" way to do it. -.IP "3. Let the timer time out, but then re-arm it as required." 4 -.IX Item "3. Let the timer time out, but then re-arm it as required." -This method is more tricky, but usually most efficient: Most timeouts are -relatively long compared to the intervals between other activity \- in -our example, within 60 seconds, there are usually many I/O events with -associated activity resets. -.Sp -In this case, it would be more efficient to leave the \f(CW\*(C`ev_timer\*(C'\fR alone, -but remember the time of last activity, and check for a real timeout only -within the callback: -.Sp -.Vb 3 -\& ev_tstamp timeout = 60.; -\& ev_tstamp last_activity; // time of last activity -\& ev_timer timer; -\& -\& static void -\& callback (EV_P_ ev_timer *w, int revents) -\& { -\& // calculate when the timeout would happen -\& ev_tstamp after = last_activity \- ev_now (EV_A) + timeout; -\& -\& // if negative, it means we the timeout already occurred -\& if (after < 0.) -\& { -\& // timeout occurred, take action -\& } -\& else -\& { -\& // callback was invoked, but there was some recent -\& // activity. simply restart the timer to time out -\& // after "after" seconds, which is the earliest time -\& // the timeout can occur. -\& ev_timer_set (w, after, 0.); -\& ev_timer_start (EV_A_ w); -\& } -\& } -.Ve -.Sp -To summarise the callback: first calculate in how many seconds the -timeout will occur (by calculating the absolute time when it would occur, -\&\f(CW\*(C`last_activity + timeout\*(C'\fR, and subtracting the current time, \f(CW\*(C`ev_now -(EV_A)\*(C'\fR from that). -.Sp -If this value is negative, then we are already past the timeout, i.e. we -timed out, and need to do whatever is needed in this case. -.Sp -Otherwise, we now the earliest time at which the timeout would trigger, -and simply start the timer with this timeout value. -.Sp -In other words, each time the callback is invoked it will check whether -the timeout occurred. If not, it will simply reschedule itself to check -again at the earliest time it could time out. Rinse. Repeat. -.Sp -This scheme causes more callback invocations (about one every 60 seconds -minus half the average time between activity), but virtually no calls to -libev to change the timeout. -.Sp -To start the machinery, simply initialise the watcher and set -\&\f(CW\*(C`last_activity\*(C'\fR to the current time (meaning there was some activity just -now), then call the callback, which will \*(L"do the right thing\*(R" and start -the timer: -.Sp -.Vb 3 -\& last_activity = ev_now (EV_A); -\& ev_init (&timer, callback); -\& callback (EV_A_ &timer, 0); -.Ve -.Sp -When there is some activity, simply store the current time in -\&\f(CW\*(C`last_activity\*(C'\fR, no libev calls at all: -.Sp -.Vb 2 -\& if (activity detected) -\& last_activity = ev_now (EV_A); -.Ve -.Sp -When your timeout value changes, then the timeout can be changed by simply -providing a new value, stopping the timer and calling the callback, which -will again do the right thing (for example, time out immediately :). -.Sp -.Vb 3 -\& timeout = new_value; -\& ev_timer_stop (EV_A_ &timer); -\& callback (EV_A_ &timer, 0); -.Ve -.Sp -This technique is slightly more complex, but in most cases where the -time-out is unlikely to be triggered, much more efficient. -.IP "4. Wee, just use a double-linked list for your timeouts." 4 -.IX Item "4. Wee, just use a double-linked list for your timeouts." -If there is not one request, but many thousands (millions...), all -employing some kind of timeout with the same timeout value, then one can -do even better: -.Sp -When starting the timeout, calculate the timeout value and put the timeout -at the \fIend\fR of the list. -.Sp -Then use an \f(CW\*(C`ev_timer\*(C'\fR to fire when the timeout at the \fIbeginning\fR of -the list is expected to fire (for example, using the technique #3). -.Sp -When there is some activity, remove the timer from the list, recalculate -the timeout, append it to the end of the list again, and make sure to -update the \f(CW\*(C`ev_timer\*(C'\fR if it was taken from the beginning of the list. -.Sp -This way, one can manage an unlimited number of timeouts in O(1) time for -starting, stopping and updating the timers, at the expense of a major -complication, and having to use a constant timeout. The constant timeout -ensures that the list stays sorted. -.PP -So which method the best? -.PP -Method #2 is a simple no-brain-required solution that is adequate in most -situations. Method #3 requires a bit more thinking, but handles many cases -better, and isn't very complicated either. In most case, choosing either -one is fine, with #3 being better in typical situations. -.PP -Method #1 is almost always a bad idea, and buys you nothing. Method #4 is -rather complicated, but extremely efficient, something that really pays -off after the first million or so of active timers, i.e. it's usually -overkill :) -.PP -\fIThe special problem of being too early\fR -.IX Subsection "The special problem of being too early" -.PP -If you ask a timer to call your callback after three seconds, then -you expect it to be invoked after three seconds \- but of course, this -cannot be guaranteed to infinite precision. Less obviously, it cannot be -guaranteed to any precision by libev \- imagine somebody suspending the -process with a \s-1STOP\s0 signal for a few hours for example. -.PP -So, libev tries to invoke your callback as soon as possible \fIafter\fR the -delay has occurred, but cannot guarantee this. -.PP -A less obvious failure mode is calling your callback too early: many event -loops compare timestamps with a \*(L"elapsed delay >= requested delay\*(R", but -this can cause your callback to be invoked much earlier than you would -expect. -.PP -To see why, imagine a system with a clock that only offers full second -resolution (think windows if you can't come up with a broken enough \s-1OS\s0 -yourself). If you schedule a one-second timer at the time 500.9, then the -event loop will schedule your timeout to elapse at a system time of 500 -(500.9 truncated to the resolution) + 1, or 501. -.PP -If an event library looks at the timeout 0.1s later, it will see \*(L"501 >= -501\*(R" and invoke the callback 0.1s after it was started, even though a -one-second delay was requested \- this is being \*(L"too early\*(R", despite best -intentions. -.PP -This is the reason why libev will never invoke the callback if the elapsed -delay equals the requested delay, but only when the elapsed delay is -larger than the requested delay. In the example above, libev would only invoke -the callback at system time 502, or 1.1s after the timer was started. -.PP -So, while libev cannot guarantee that your callback will be invoked -exactly when requested, it \fIcan\fR and \fIdoes\fR guarantee that the requested -delay has actually elapsed, or in other words, it always errs on the \*(L"too -late\*(R" side of things. -.PP -\fIThe special problem of time updates\fR -.IX Subsection "The special problem of time updates" -.PP -Establishing the current time is a costly operation (it usually takes -at least one system call): \s-1EV\s0 therefore updates its idea of the current -time only before and after \f(CW\*(C`ev_run\*(C'\fR collects new events, which causes a -growing difference between \f(CW\*(C`ev_now ()\*(C'\fR and \f(CW\*(C`ev_time ()\*(C'\fR when handling -lots of events in one iteration. -.PP -The relative timeouts are calculated relative to the \f(CW\*(C`ev_now ()\*(C'\fR -time. This is usually the right thing as this timestamp refers to the time -of the event triggering whatever timeout you are modifying/starting. If -you suspect event processing to be delayed and you \fIneed\fR to base the -timeout on the current time, use something like this to adjust for this: -.PP -.Vb 1 -\& ev_timer_set (&timer, after + ev_now () \- ev_time (), 0.); -.Ve -.PP -If the event loop is suspended for a long time, you can also force an -update of the time returned by \f(CW\*(C`ev_now ()\*(C'\fR by calling \f(CW\*(C`ev_now_update -()\*(C'\fR. -.PP -\fIThe special problem of unsynchronised clocks\fR -.IX Subsection "The special problem of unsynchronised clocks" -.PP -Modern systems have a variety of clocks \- libev itself uses the normal -\&\*(L"wall clock\*(R" clock and, if available, the monotonic clock (to avoid time -jumps). -.PP -Neither of these clocks is synchronised with each other or any other clock -on the system, so \f(CW\*(C`ev_time ()\*(C'\fR might return a considerably different time -than \f(CW\*(C`gettimeofday ()\*(C'\fR or \f(CW\*(C`time ()\*(C'\fR. On a GNU/Linux system, for example, -a call to \f(CW\*(C`gettimeofday\*(C'\fR might return a second count that is one higher -than a directly following call to \f(CW\*(C`time\*(C'\fR. -.PP -The moral of this is to only compare libev-related timestamps with -\&\f(CW\*(C`ev_time ()\*(C'\fR and \f(CW\*(C`ev_now ()\*(C'\fR, at least if you want better precision than -a second or so. -.PP -One more problem arises due to this lack of synchronisation: if libev uses -the system monotonic clock and you compare timestamps from \f(CW\*(C`ev_time\*(C'\fR -or \f(CW\*(C`ev_now\*(C'\fR from when you started your timer and when your callback is -invoked, you will find that sometimes the callback is a bit \*(L"early\*(R". -.PP -This is because \f(CW\*(C`ev_timer\*(C'\fRs work in real time, not wall clock time, so -libev makes sure your callback is not invoked before the delay happened, -\&\fImeasured according to the real time\fR, not the system clock. -.PP -If your timeouts are based on a physical timescale (e.g. \*(L"time out this -connection after 100 seconds\*(R") then this shouldn't bother you as it is -exactly the right behaviour. -.PP -If you want to compare wall clock/system timestamps to your timers, then -you need to use \f(CW\*(C`ev_periodic\*(C'\fRs, as these are based on the wall clock -time, where your comparisons will always generate correct results. -.PP -\fIThe special problems of suspended animation\fR -.IX Subsection "The special problems of suspended animation" -.PP -When you leave the server world it is quite customary to hit machines that -can suspend/hibernate \- what happens to the clocks during such a suspend? -.PP -Some quick tests made with a Linux 2.6.28 indicate that a suspend freezes -all processes, while the clocks (\f(CW\*(C`times\*(C'\fR, \f(CW\*(C`CLOCK_MONOTONIC\*(C'\fR) continue -to run until the system is suspended, but they will not advance while the -system is suspended. That means, on resume, it will be as if the program -was frozen for a few seconds, but the suspend time will not be counted -towards \f(CW\*(C`ev_timer\*(C'\fR when a monotonic clock source is used. The real time -clock advanced as expected, but if it is used as sole clocksource, then a -long suspend would be detected as a time jump by libev, and timers would -be adjusted accordingly. -.PP -I would not be surprised to see different behaviour in different between -operating systems, \s-1OS\s0 versions or even different hardware. -.PP -The other form of suspend (job control, or sending a \s-1SIGSTOP\s0) will see a -time jump in the monotonic clocks and the realtime clock. If the program -is suspended for a very long time, and monotonic clock sources are in use, -then you can expect \f(CW\*(C`ev_timer\*(C'\fRs to expire as the full suspension time -will be counted towards the timers. When no monotonic clock source is in -use, then libev will again assume a timejump and adjust accordingly. -.PP -It might be beneficial for this latter case to call \f(CW\*(C`ev_suspend\*(C'\fR -and \f(CW\*(C`ev_resume\*(C'\fR in code that handles \f(CW\*(C`SIGTSTP\*(C'\fR, to at least get -deterministic behaviour in this case (you can do nothing against -\&\f(CW\*(C`SIGSTOP\*(C'\fR). -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)" 4 -.IX Item "ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)" -.PD 0 -.IP "ev_timer_set (ev_timer *, ev_tstamp after, ev_tstamp repeat)" 4 -.IX Item "ev_timer_set (ev_timer *, ev_tstamp after, ev_tstamp repeat)" -.PD -Configure the timer to trigger after \f(CW\*(C`after\*(C'\fR seconds. If \f(CW\*(C`repeat\*(C'\fR -is \f(CW0.\fR, then it will automatically be stopped once the timeout is -reached. If it is positive, then the timer will automatically be -configured to trigger again \f(CW\*(C`repeat\*(C'\fR seconds later, again, and again, -until stopped manually. -.Sp -The timer itself will do a best-effort at avoiding drift, that is, if -you configure a timer to trigger every 10 seconds, then it will normally -trigger at exactly 10 second intervals. If, however, your program cannot -keep up with the timer (because it takes longer than those 10 seconds to -do stuff) the timer will not fire more than once per event loop iteration. -.IP "ev_timer_again (loop, ev_timer *)" 4 -.IX Item "ev_timer_again (loop, ev_timer *)" -This will act as if the timer timed out, and restarts it again if it is -repeating. It basically works like calling \f(CW\*(C`ev_timer_stop\*(C'\fR, updating the -timeout to the \f(CW\*(C`repeat\*(C'\fR value and calling \f(CW\*(C`ev_timer_start\*(C'\fR. -.Sp -The exact semantics are as in the following rules, all of which will be -applied to the watcher: -.RS 4 -.IP "If the timer is pending, the pending status is always cleared." 4 -.IX Item "If the timer is pending, the pending status is always cleared." -.PD 0 -.IP "If the timer is started but non-repeating, stop it (as if it timed out, without invoking it)." 4 -.IX Item "If the timer is started but non-repeating, stop it (as if it timed out, without invoking it)." -.ie n .IP "If the timer is repeating, make the ""repeat"" value the new timeout and start the timer, if necessary." 4 -.el .IP "If the timer is repeating, make the \f(CWrepeat\fR value the new timeout and start the timer, if necessary." 4 -.IX Item "If the timer is repeating, make the repeat value the new timeout and start the timer, if necessary." -.RE -.RS 4 -.PD -.Sp -This sounds a bit complicated, see \*(L"Be smart about timeouts\*(R", above, for a -usage example. -.RE -.IP "ev_tstamp ev_timer_remaining (loop, ev_timer *)" 4 -.IX Item "ev_tstamp ev_timer_remaining (loop, ev_timer *)" -Returns the remaining time until a timer fires. If the timer is active, -then this time is relative to the current event loop time, otherwise it's -the timeout value currently configured. -.Sp -That is, after an \f(CW\*(C`ev_timer_set (w, 5, 7)\*(C'\fR, \f(CW\*(C`ev_timer_remaining\*(C'\fR returns -\&\f(CW5\fR. When the timer is started and one second passes, \f(CW\*(C`ev_timer_remaining\*(C'\fR -will return \f(CW4\fR. When the timer expires and is restarted, it will return -roughly \f(CW7\fR (likely slightly less as callback invocation takes some time, -too), and so on. -.IP "ev_tstamp repeat [read\-write]" 4 -.IX Item "ev_tstamp repeat [read-write]" -The current \f(CW\*(C`repeat\*(C'\fR value. Will be used each time the watcher times out -or \f(CW\*(C`ev_timer_again\*(C'\fR is called, and determines the next timeout (if any), -which is also when any modifications are taken into account. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: Create a timer that fires after 60 seconds. -.PP -.Vb 5 -\& static void -\& one_minute_cb (struct ev_loop *loop, ev_timer *w, int revents) -\& { -\& .. one minute over, w is actually stopped right here -\& } -\& -\& ev_timer mytimer; -\& ev_timer_init (&mytimer, one_minute_cb, 60., 0.); -\& ev_timer_start (loop, &mytimer); -.Ve -.PP -Example: Create a timeout timer that times out after 10 seconds of -inactivity. -.PP -.Vb 5 -\& static void -\& timeout_cb (struct ev_loop *loop, ev_timer *w, int revents) -\& { -\& .. ten seconds without any activity -\& } -\& -\& ev_timer mytimer; -\& ev_timer_init (&mytimer, timeout_cb, 0., 10.); /* note, only repeat used */ -\& ev_timer_again (&mytimer); /* start timer */ -\& ev_run (loop, 0); -\& -\& // and in some piece of code that gets executed on any "activity": -\& // reset the timeout to start ticking again at 10 seconds -\& ev_timer_again (&mytimer); -.Ve -.ie n .SS """ev_periodic"" \- to cron or not to cron?" -.el .SS "\f(CWev_periodic\fP \- to cron or not to cron?" -.IX Subsection "ev_periodic - to cron or not to cron?" -Periodic watchers are also timers of a kind, but they are very versatile -(and unfortunately a bit complex). -.PP -Unlike \f(CW\*(C`ev_timer\*(C'\fR, periodic watchers are not based on real time (or -relative time, the physical time that passes) but on wall clock time -(absolute time, the thing you can read on your calender or clock). The -difference is that wall clock time can run faster or slower than real -time, and time jumps are not uncommon (e.g. when you adjust your -wrist-watch). -.PP -You can tell a periodic watcher to trigger after some specific point -in time: for example, if you tell a periodic watcher to trigger \*(L"in 10 -seconds\*(R" (by specifying e.g. \f(CW\*(C`ev_now () + 10.\*(C'\fR, that is, an absolute time -not a delay) and then reset your system clock to January of the previous -year, then it will take a year or more to trigger the event (unlike an -\&\f(CW\*(C`ev_timer\*(C'\fR, which would still trigger roughly 10 seconds after starting -it, as it uses a relative timeout). -.PP -\&\f(CW\*(C`ev_periodic\*(C'\fR watchers can also be used to implement vastly more complex -timers, such as triggering an event on each \*(L"midnight, local time\*(R", or -other complicated rules. This cannot be done with \f(CW\*(C`ev_timer\*(C'\fR watchers, as -those cannot react to time jumps. -.PP -As with timers, the callback is guaranteed to be invoked only when the -point in time where it is supposed to trigger has passed. If multiple -timers become ready during the same loop iteration then the ones with -earlier time-out values are invoked before ones with later time-out values -(but this is no longer true when a callback calls \f(CW\*(C`ev_run\*(C'\fR recursively). -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" 4 -.IX Item "ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" -.PD 0 -.IP "ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" 4 -.IX Item "ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)" -.PD -Lots of arguments, let's sort it out... There are basically three modes of -operation, and we will explain them from simplest to most complex: -.RS 4 -.IP "\(bu" 4 -absolute timer (offset = absolute time, interval = 0, reschedule_cb = 0) -.Sp -In this configuration the watcher triggers an event after the wall clock -time \f(CW\*(C`offset\*(C'\fR has passed. It will not repeat and will not adjust when a -time jump occurs, that is, if it is to be run at January 1st 2011 then it -will be stopped and invoked when the system clock reaches or surpasses -this point in time. -.IP "\(bu" 4 -repeating interval timer (offset = offset within interval, interval > 0, reschedule_cb = 0) -.Sp -In this mode the watcher will always be scheduled to time out at the next -\&\f(CW\*(C`offset + N * interval\*(C'\fR time (for some integer N, which can also be -negative) and then repeat, regardless of any time jumps. The \f(CW\*(C`offset\*(C'\fR -argument is merely an offset into the \f(CW\*(C`interval\*(C'\fR periods. -.Sp -This can be used to create timers that do not drift with respect to the -system clock, for example, here is an \f(CW\*(C`ev_periodic\*(C'\fR that triggers each -hour, on the hour (with respect to \s-1UTC\s0): -.Sp -.Vb 1 -\& ev_periodic_set (&periodic, 0., 3600., 0); -.Ve -.Sp -This doesn't mean there will always be 3600 seconds in between triggers, -but only that the callback will be called when the system time shows a -full hour (\s-1UTC\s0), or more correctly, when the system time is evenly divisible -by 3600. -.Sp -Another way to think about it (for the mathematically inclined) is that -\&\f(CW\*(C`ev_periodic\*(C'\fR will try to run the callback in this mode at the next possible -time where \f(CW\*(C`time = offset (mod interval)\*(C'\fR, regardless of any time jumps. -.Sp -The \f(CW\*(C`interval\*(C'\fR \fI\s-1MUST\s0\fR be positive, and for numerical stability, the -interval value should be higher than \f(CW\*(C`1/8192\*(C'\fR (which is around 100 -microseconds) and \f(CW\*(C`offset\*(C'\fR should be higher than \f(CW0\fR and should have -at most a similar magnitude as the current time (say, within a factor of -ten). Typical values for offset are, in fact, \f(CW0\fR or something between -\&\f(CW0\fR and \f(CW\*(C`interval\*(C'\fR, which is also the recommended range. -.Sp -Note also that there is an upper limit to how often a timer can fire (\s-1CPU\s0 -speed for example), so if \f(CW\*(C`interval\*(C'\fR is very small then timing stability -will of course deteriorate. Libev itself tries to be exact to be about one -millisecond (if the \s-1OS\s0 supports it and the machine is fast enough). -.IP "\(bu" 4 -manual reschedule mode (offset ignored, interval ignored, reschedule_cb = callback) -.Sp -In this mode the values for \f(CW\*(C`interval\*(C'\fR and \f(CW\*(C`offset\*(C'\fR are both being -ignored. Instead, each time the periodic watcher gets scheduled, the -reschedule callback will be called with the watcher as first, and the -current time as second argument. -.Sp -\&\s-1NOTE:\s0 \fIThis callback \s-1MUST\s0 \s-1NOT\s0 stop or destroy any periodic watcher, ever, -or make \s-1ANY\s0 other event loop modifications whatsoever, unless explicitly -allowed by documentation here\fR. -.Sp -If you need to stop it, return \f(CW\*(C`now + 1e30\*(C'\fR (or so, fudge fudge) and stop -it afterwards (e.g. by starting an \f(CW\*(C`ev_prepare\*(C'\fR watcher, which is the -only event loop modification you are allowed to do). -.Sp -The callback prototype is \f(CW\*(C`ev_tstamp (*reschedule_cb)(ev_periodic -*w, ev_tstamp now)\*(C'\fR, e.g.: -.Sp -.Vb 5 -\& static ev_tstamp -\& my_rescheduler (ev_periodic *w, ev_tstamp now) -\& { -\& return now + 60.; -\& } -.Ve -.Sp -It must return the next time to trigger, based on the passed time value -(that is, the lowest time value larger than to the second argument). It -will usually be called just before the callback will be triggered, but -might be called at other times, too. -.Sp -\&\s-1NOTE:\s0 \fIThis callback must always return a time that is higher than or -equal to the passed \f(CI\*(C`now\*(C'\fI value\fR. -.Sp -This can be used to create very complex timers, such as a timer that -triggers on \*(L"next midnight, local time\*(R". To do this, you would calculate the -next midnight after \f(CW\*(C`now\*(C'\fR and return the timestamp value for this. How -you do this is, again, up to you (but it is not trivial, which is the main -reason I omitted it as an example). -.RE -.RS 4 -.RE -.IP "ev_periodic_again (loop, ev_periodic *)" 4 -.IX Item "ev_periodic_again (loop, ev_periodic *)" -Simply stops and restarts the periodic watcher again. This is only useful -when you changed some parameters or the reschedule callback would return -a different time than the last time it was called (e.g. in a crond like -program when the crontabs have changed). -.IP "ev_tstamp ev_periodic_at (ev_periodic *)" 4 -.IX Item "ev_tstamp ev_periodic_at (ev_periodic *)" -When active, returns the absolute time that the watcher is supposed -to trigger next. This is not the same as the \f(CW\*(C`offset\*(C'\fR argument to -\&\f(CW\*(C`ev_periodic_set\*(C'\fR, but indeed works even in interval and manual -rescheduling modes. -.IP "ev_tstamp offset [read\-write]" 4 -.IX Item "ev_tstamp offset [read-write]" -When repeating, this contains the offset value, otherwise this is the -absolute point in time (the \f(CW\*(C`offset\*(C'\fR value passed to \f(CW\*(C`ev_periodic_set\*(C'\fR, -although libev might modify this value for better numerical stability). -.Sp -Can be modified any time, but changes only take effect when the periodic -timer fires or \f(CW\*(C`ev_periodic_again\*(C'\fR is being called. -.IP "ev_tstamp interval [read\-write]" 4 -.IX Item "ev_tstamp interval [read-write]" -The current interval value. Can be modified any time, but changes only -take effect when the periodic timer fires or \f(CW\*(C`ev_periodic_again\*(C'\fR is being -called. -.IP "ev_tstamp (*reschedule_cb)(ev_periodic *w, ev_tstamp now) [read\-write]" 4 -.IX Item "ev_tstamp (*reschedule_cb)(ev_periodic *w, ev_tstamp now) [read-write]" -The current reschedule callback, or \f(CW0\fR, if this functionality is -switched off. Can be changed any time, but changes only take effect when -the periodic timer fires or \f(CW\*(C`ev_periodic_again\*(C'\fR is being called. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: Call a callback every hour, or, more precisely, whenever the -system time is divisible by 3600. The callback invocation times have -potentially a lot of jitter, but good long-term stability. -.PP -.Vb 5 -\& static void -\& clock_cb (struct ev_loop *loop, ev_periodic *w, int revents) -\& { -\& ... its now a full hour (UTC, or TAI or whatever your clock follows) -\& } -\& -\& ev_periodic hourly_tick; -\& ev_periodic_init (&hourly_tick, clock_cb, 0., 3600., 0); -\& ev_periodic_start (loop, &hourly_tick); -.Ve -.PP -Example: The same as above, but use a reschedule callback to do it: -.PP -.Vb 1 -\& #include -\& -\& static ev_tstamp -\& my_scheduler_cb (ev_periodic *w, ev_tstamp now) -\& { -\& return now + (3600. \- fmod (now, 3600.)); -\& } -\& -\& ev_periodic_init (&hourly_tick, clock_cb, 0., 0., my_scheduler_cb); -.Ve -.PP -Example: Call a callback every hour, starting now: -.PP -.Vb 4 -\& ev_periodic hourly_tick; -\& ev_periodic_init (&hourly_tick, clock_cb, -\& fmod (ev_now (loop), 3600.), 3600., 0); -\& ev_periodic_start (loop, &hourly_tick); -.Ve -.ie n .SS """ev_signal"" \- signal me when a signal gets signalled!" -.el .SS "\f(CWev_signal\fP \- signal me when a signal gets signalled!" -.IX Subsection "ev_signal - signal me when a signal gets signalled!" -Signal watchers will trigger an event when the process receives a specific -signal one or more times. Even though signals are very asynchronous, libev -will try its best to deliver signals synchronously, i.e. as part of the -normal event processing, like any other event. -.PP -If you want signals to be delivered truly asynchronously, just use -\&\f(CW\*(C`sigaction\*(C'\fR as you would do without libev and forget about sharing -the signal. You can even use \f(CW\*(C`ev_async\*(C'\fR from a signal handler to -synchronously wake up an event loop. -.PP -You can configure as many watchers as you like for the same signal, but -only within the same loop, i.e. you can watch for \f(CW\*(C`SIGINT\*(C'\fR in your -default loop and for \f(CW\*(C`SIGIO\*(C'\fR in another loop, but you cannot watch for -\&\f(CW\*(C`SIGINT\*(C'\fR in both the default loop and another loop at the same time. At -the moment, \f(CW\*(C`SIGCHLD\*(C'\fR is permanently tied to the default loop. -.PP -When the first watcher gets started will libev actually register something -with the kernel (thus it coexists with your own signal handlers as long as -you don't register any with libev for the same signal). -.PP -If possible and supported, libev will install its handlers with -\&\f(CW\*(C`SA_RESTART\*(C'\fR (or equivalent) behaviour enabled, so system calls should -not be unduly interrupted. If you have a problem with system calls getting -interrupted by signals you can block all signals in an \f(CW\*(C`ev_check\*(C'\fR watcher -and unblock them in an \f(CW\*(C`ev_prepare\*(C'\fR watcher. -.PP -\fIThe special problem of inheritance over fork/execve/pthread_create\fR -.IX Subsection "The special problem of inheritance over fork/execve/pthread_create" -.PP -Both the signal mask (\f(CW\*(C`sigprocmask\*(C'\fR) and the signal disposition -(\f(CW\*(C`sigaction\*(C'\fR) are unspecified after starting a signal watcher (and after -stopping it again), that is, libev might or might not block the signal, -and might or might not set or restore the installed signal handler (but -see \f(CW\*(C`EVFLAG_NOSIGMASK\*(C'\fR). -.PP -While this does not matter for the signal disposition (libev never -sets signals to \f(CW\*(C`SIG_IGN\*(C'\fR, so handlers will be reset to \f(CW\*(C`SIG_DFL\*(C'\fR on -\&\f(CW\*(C`execve\*(C'\fR), this matters for the signal mask: many programs do not expect -certain signals to be blocked. -.PP -This means that before calling \f(CW\*(C`exec\*(C'\fR (from the child) you should reset -the signal mask to whatever \*(L"default\*(R" you expect (all clear is a good -choice usually). -.PP -The simplest way to ensure that the signal mask is reset in the child is -to install a fork handler with \f(CW\*(C`pthread_atfork\*(C'\fR that resets it. That will -catch fork calls done by libraries (such as the libc) as well. -.PP -In current versions of libev, the signal will not be blocked indefinitely -unless you use the \f(CW\*(C`signalfd\*(C'\fR \s-1API\s0 (\f(CW\*(C`EV_SIGNALFD\*(C'\fR). While this reduces -the window of opportunity for problems, it will not go away, as libev -\&\fIhas\fR to modify the signal mask, at least temporarily. -.PP -So I can't stress this enough: \fIIf you do not reset your signal mask when -you expect it to be empty, you have a race condition in your code\fR. This -is not a libev-specific thing, this is true for most event libraries. -.PP -\fIThe special problem of threads signal handling\fR -.IX Subsection "The special problem of threads signal handling" -.PP -\&\s-1POSIX\s0 threads has problematic signal handling semantics, specifically, -a lot of functionality (sigfd, sigwait etc.) only really works if all -threads in a process block signals, which is hard to achieve. -.PP -When you want to use sigwait (or mix libev signal handling with your own -for the same signals), you can tackle this problem by globally blocking -all signals before creating any threads (or creating them with a fully set -sigprocmask) and also specifying the \f(CW\*(C`EVFLAG_NOSIGMASK\*(C'\fR when creating -loops. Then designate one thread as \*(L"signal receiver thread\*(R" which handles -these signals. You can pass on any signals that libev might be interested -in by calling \f(CW\*(C`ev_feed_signal\*(C'\fR. -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_signal_init (ev_signal *, callback, int signum)" 4 -.IX Item "ev_signal_init (ev_signal *, callback, int signum)" -.PD 0 -.IP "ev_signal_set (ev_signal *, int signum)" 4 -.IX Item "ev_signal_set (ev_signal *, int signum)" -.PD -Configures the watcher to trigger on the given signal number (usually one -of the \f(CW\*(C`SIGxxx\*(C'\fR constants). -.IP "int signum [read\-only]" 4 -.IX Item "int signum [read-only]" -The signal the watcher watches out for. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: Try to exit cleanly on \s-1SIGINT\s0. -.PP -.Vb 5 -\& static void -\& sigint_cb (struct ev_loop *loop, ev_signal *w, int revents) -\& { -\& ev_break (loop, EVBREAK_ALL); -\& } -\& -\& ev_signal signal_watcher; -\& ev_signal_init (&signal_watcher, sigint_cb, SIGINT); -\& ev_signal_start (loop, &signal_watcher); -.Ve -.ie n .SS """ev_child"" \- watch out for process status changes" -.el .SS "\f(CWev_child\fP \- watch out for process status changes" -.IX Subsection "ev_child - watch out for process status changes" -Child watchers trigger when your process receives a \s-1SIGCHLD\s0 in response to -some child status changes (most typically when a child of yours dies or -exits). It is permissible to install a child watcher \fIafter\fR the child -has been forked (which implies it might have already exited), as long -as the event loop isn't entered (or is continued from a watcher), i.e., -forking and then immediately registering a watcher for the child is fine, -but forking and registering a watcher a few event loop iterations later or -in the next callback invocation is not. -.PP -Only the default event loop is capable of handling signals, and therefore -you can only register child watchers in the default event loop. -.PP -Due to some design glitches inside libev, child watchers will always be -handled at maximum priority (their priority is set to \f(CW\*(C`EV_MAXPRI\*(C'\fR by -libev) -.PP -\fIProcess Interaction\fR -.IX Subsection "Process Interaction" -.PP -Libev grabs \f(CW\*(C`SIGCHLD\*(C'\fR as soon as the default event loop is -initialised. This is necessary to guarantee proper behaviour even if the -first child watcher is started after the child exits. The occurrence -of \f(CW\*(C`SIGCHLD\*(C'\fR is recorded asynchronously, but child reaping is done -synchronously as part of the event loop processing. Libev always reaps all -children, even ones not watched. -.PP -\fIOverriding the Built-In Processing\fR -.IX Subsection "Overriding the Built-In Processing" -.PP -Libev offers no special support for overriding the built-in child -processing, but if your application collides with libev's default child -handler, you can override it easily by installing your own handler for -\&\f(CW\*(C`SIGCHLD\*(C'\fR after initialising the default loop, and making sure the -default loop never gets destroyed. You are encouraged, however, to use an -event-based approach to child reaping and thus use libev's support for -that, so other libev users can use \f(CW\*(C`ev_child\*(C'\fR watchers freely. -.PP -\fIStopping the Child Watcher\fR -.IX Subsection "Stopping the Child Watcher" -.PP -Currently, the child watcher never gets stopped, even when the -child terminates, so normally one needs to stop the watcher in the -callback. Future versions of libev might stop the watcher automatically -when a child exit is detected (calling \f(CW\*(C`ev_child_stop\*(C'\fR twice is not a -problem). -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_child_init (ev_child *, callback, int pid, int trace)" 4 -.IX Item "ev_child_init (ev_child *, callback, int pid, int trace)" -.PD 0 -.IP "ev_child_set (ev_child *, int pid, int trace)" 4 -.IX Item "ev_child_set (ev_child *, int pid, int trace)" -.PD -Configures the watcher to wait for status changes of process \f(CW\*(C`pid\*(C'\fR (or -\&\fIany\fR process if \f(CW\*(C`pid\*(C'\fR is specified as \f(CW0\fR). The callback can look -at the \f(CW\*(C`rstatus\*(C'\fR member of the \f(CW\*(C`ev_child\*(C'\fR watcher structure to see -the status word (use the macros from \f(CW\*(C`sys/wait.h\*(C'\fR and see your systems -\&\f(CW\*(C`waitpid\*(C'\fR documentation). The \f(CW\*(C`rpid\*(C'\fR member contains the pid of the -process causing the status change. \f(CW\*(C`trace\*(C'\fR must be either \f(CW0\fR (only -activate the watcher when the process terminates) or \f(CW1\fR (additionally -activate the watcher when the process is stopped or continued). -.IP "int pid [read\-only]" 4 -.IX Item "int pid [read-only]" -The process id this watcher watches out for, or \f(CW0\fR, meaning any process id. -.IP "int rpid [read\-write]" 4 -.IX Item "int rpid [read-write]" -The process id that detected a status change. -.IP "int rstatus [read\-write]" 4 -.IX Item "int rstatus [read-write]" -The process exit/trace status caused by \f(CW\*(C`rpid\*(C'\fR (see your systems -\&\f(CW\*(C`waitpid\*(C'\fR and \f(CW\*(C`sys/wait.h\*(C'\fR documentation for details). -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: \f(CW\*(C`fork()\*(C'\fR a new process and install a child handler to wait for -its completion. -.PP -.Vb 1 -\& ev_child cw; -\& -\& static void -\& child_cb (EV_P_ ev_child *w, int revents) -\& { -\& ev_child_stop (EV_A_ w); -\& printf ("process %d exited with status %x\en", w\->rpid, w\->rstatus); -\& } -\& -\& pid_t pid = fork (); -\& -\& if (pid < 0) -\& // error -\& else if (pid == 0) -\& { -\& // the forked child executes here -\& exit (1); -\& } -\& else -\& { -\& ev_child_init (&cw, child_cb, pid, 0); -\& ev_child_start (EV_DEFAULT_ &cw); -\& } -.Ve -.ie n .SS """ev_stat"" \- did the file attributes just change?" -.el .SS "\f(CWev_stat\fP \- did the file attributes just change?" -.IX Subsection "ev_stat - did the file attributes just change?" -This watches a file system path for attribute changes. That is, it calls -\&\f(CW\*(C`stat\*(C'\fR on that path in regular intervals (or when the \s-1OS\s0 says it changed) -and sees if it changed compared to the last time, invoking the callback -if it did. Starting the watcher \f(CW\*(C`stat\*(C'\fR's the file, so only changes that -happen after the watcher has been started will be reported. -.PP -The path does not need to exist: changing from \*(L"path exists\*(R" to \*(L"path does -not exist\*(R" is a status change like any other. The condition \*(L"path does not -exist\*(R" (or more correctly \*(L"path cannot be stat'ed\*(R") is signified by the -\&\f(CW\*(C`st_nlink\*(C'\fR field being zero (which is otherwise always forced to be at -least one) and all the other fields of the stat buffer having unspecified -contents. -.PP -The path \fImust not\fR end in a slash or contain special components such as -\&\f(CW\*(C`.\*(C'\fR or \f(CW\*(C`..\*(C'\fR. The path \fIshould\fR be absolute: If it is relative and -your working directory changes, then the behaviour is undefined. -.PP -Since there is no portable change notification interface available, the -portable implementation simply calls \f(CWstat(2)\fR regularly on the path -to see if it changed somehow. You can specify a recommended polling -interval for this case. If you specify a polling interval of \f(CW0\fR (highly -recommended!) then a \fIsuitable, unspecified default\fR value will be used -(which you can expect to be around five seconds, although this might -change dynamically). Libev will also impose a minimum interval which is -currently around \f(CW0.1\fR, but that's usually overkill. -.PP -This watcher type is not meant for massive numbers of stat watchers, -as even with OS-supported change notifications, this can be -resource-intensive. -.PP -At the time of this writing, the only OS-specific interface implemented -is the Linux inotify interface (implementing kqueue support is left as an -exercise for the reader. Note, however, that the author sees no way of -implementing \f(CW\*(C`ev_stat\*(C'\fR semantics with kqueue, except as a hint). -.PP -\fI\s-1ABI\s0 Issues (Largefile Support)\fR -.IX Subsection "ABI Issues (Largefile Support)" -.PP -Libev by default (unless the user overrides this) uses the default -compilation environment, which means that on systems with large file -support disabled by default, you get the 32 bit version of the stat -structure. When using the library from programs that change the \s-1ABI\s0 to -use 64 bit file offsets the programs will fail. In that case you have to -compile libev with the same flags to get binary compatibility. This is -obviously the case with any flags that change the \s-1ABI\s0, but the problem is -most noticeably displayed with ev_stat and large file support. -.PP -The solution for this is to lobby your distribution maker to make large -file interfaces available by default (as e.g. FreeBSD does) and not -optional. Libev cannot simply switch on large file support because it has -to exchange stat structures with application programs compiled using the -default compilation environment. -.PP -\fIInotify and Kqueue\fR -.IX Subsection "Inotify and Kqueue" -.PP -When \f(CW\*(C`inotify (7)\*(C'\fR support has been compiled into libev and present at -runtime, it will be used to speed up change detection where possible. The -inotify descriptor will be created lazily when the first \f(CW\*(C`ev_stat\*(C'\fR -watcher is being started. -.PP -Inotify presence does not change the semantics of \f(CW\*(C`ev_stat\*(C'\fR watchers -except that changes might be detected earlier, and in some cases, to avoid -making regular \f(CW\*(C`stat\*(C'\fR calls. Even in the presence of inotify support -there are many cases where libev has to resort to regular \f(CW\*(C`stat\*(C'\fR polling, -but as long as kernel 2.6.25 or newer is used (2.6.24 and older have too -many bugs), the path exists (i.e. stat succeeds), and the path resides on -a local filesystem (libev currently assumes only ext2/3, jfs, reiserfs and -xfs are fully working) libev usually gets away without polling. -.PP -There is no support for kqueue, as apparently it cannot be used to -implement this functionality, due to the requirement of having a file -descriptor open on the object at all times, and detecting renames, unlinks -etc. is difficult. -.PP -\fI\f(CI\*(C`stat ()\*(C'\fI is a synchronous operation\fR -.IX Subsection "stat () is a synchronous operation" -.PP -Libev doesn't normally do any kind of I/O itself, and so is not blocking -the process. The exception are \f(CW\*(C`ev_stat\*(C'\fR watchers \- those call \f(CW\*(C`stat -()\*(C'\fR, which is a synchronous operation. -.PP -For local paths, this usually doesn't matter: unless the system is very -busy or the intervals between stat's are large, a stat call will be fast, -as the path data is usually in memory already (except when starting the -watcher). -.PP -For networked file systems, calling \f(CW\*(C`stat ()\*(C'\fR can block an indefinite -time due to network issues, and even under good conditions, a stat call -often takes multiple milliseconds. -.PP -Therefore, it is best to avoid using \f(CW\*(C`ev_stat\*(C'\fR watchers on networked -paths, although this is fully supported by libev. -.PP -\fIThe special problem of stat time resolution\fR -.IX Subsection "The special problem of stat time resolution" -.PP -The \f(CW\*(C`stat ()\*(C'\fR system call only supports full-second resolution portably, -and even on systems where the resolution is higher, most file systems -still only support whole seconds. -.PP -That means that, if the time is the only thing that changes, you can -easily miss updates: on the first update, \f(CW\*(C`ev_stat\*(C'\fR detects a change and -calls your callback, which does something. When there is another update -within the same second, \f(CW\*(C`ev_stat\*(C'\fR will be unable to detect unless the -stat data does change in other ways (e.g. file size). -.PP -The solution to this is to delay acting on a change for slightly more -than a second (or till slightly after the next full second boundary), using -a roughly one-second-delay \f(CW\*(C`ev_timer\*(C'\fR (e.g. \f(CW\*(C`ev_timer_set (w, 0., 1.02); -ev_timer_again (loop, w)\*(C'\fR). -.PP -The \f(CW.02\fR offset is added to work around small timing inconsistencies -of some operating systems (where the second counter of the current time -might be be delayed. One such system is the Linux kernel, where a call to -\&\f(CW\*(C`gettimeofday\*(C'\fR might return a timestamp with a full second later than -a subsequent \f(CW\*(C`time\*(C'\fR call \- if the equivalent of \f(CW\*(C`time ()\*(C'\fR is used to -update file times then there will be a small window where the kernel uses -the previous second to update file times but libev might already execute -the timer callback). -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_stat_init (ev_stat *, callback, const char *path, ev_tstamp interval)" 4 -.IX Item "ev_stat_init (ev_stat *, callback, const char *path, ev_tstamp interval)" -.PD 0 -.IP "ev_stat_set (ev_stat *, const char *path, ev_tstamp interval)" 4 -.IX Item "ev_stat_set (ev_stat *, const char *path, ev_tstamp interval)" -.PD -Configures the watcher to wait for status changes of the given -\&\f(CW\*(C`path\*(C'\fR. The \f(CW\*(C`interval\*(C'\fR is a hint on how quickly a change is expected to -be detected and should normally be specified as \f(CW0\fR to let libev choose -a suitable value. The memory pointed to by \f(CW\*(C`path\*(C'\fR must point to the same -path for as long as the watcher is active. -.Sp -The callback will receive an \f(CW\*(C`EV_STAT\*(C'\fR event when a change was detected, -relative to the attributes at the time the watcher was started (or the -last change was detected). -.IP "ev_stat_stat (loop, ev_stat *)" 4 -.IX Item "ev_stat_stat (loop, ev_stat *)" -Updates the stat buffer immediately with new values. If you change the -watched path in your callback, you could call this function to avoid -detecting this change (while introducing a race condition if you are not -the only one changing the path). Can also be useful simply to find out the -new values. -.IP "ev_statdata attr [read\-only]" 4 -.IX Item "ev_statdata attr [read-only]" -The most-recently detected attributes of the file. Although the type is -\&\f(CW\*(C`ev_statdata\*(C'\fR, this is usually the (or one of the) \f(CW\*(C`struct stat\*(C'\fR types -suitable for your system, but you can only rely on the POSIX-standardised -members to be present. If the \f(CW\*(C`st_nlink\*(C'\fR member is \f(CW0\fR, then there was -some error while \f(CW\*(C`stat\*(C'\fRing the file. -.IP "ev_statdata prev [read\-only]" 4 -.IX Item "ev_statdata prev [read-only]" -The previous attributes of the file. The callback gets invoked whenever -\&\f(CW\*(C`prev\*(C'\fR != \f(CW\*(C`attr\*(C'\fR, or, more precisely, one or more of these members -differ: \f(CW\*(C`st_dev\*(C'\fR, \f(CW\*(C`st_ino\*(C'\fR, \f(CW\*(C`st_mode\*(C'\fR, \f(CW\*(C`st_nlink\*(C'\fR, \f(CW\*(C`st_uid\*(C'\fR, -\&\f(CW\*(C`st_gid\*(C'\fR, \f(CW\*(C`st_rdev\*(C'\fR, \f(CW\*(C`st_size\*(C'\fR, \f(CW\*(C`st_atime\*(C'\fR, \f(CW\*(C`st_mtime\*(C'\fR, \f(CW\*(C`st_ctime\*(C'\fR. -.IP "ev_tstamp interval [read\-only]" 4 -.IX Item "ev_tstamp interval [read-only]" -The specified interval. -.IP "const char *path [read\-only]" 4 -.IX Item "const char *path [read-only]" -The file system path that is being watched. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: Watch \f(CW\*(C`/etc/passwd\*(C'\fR for attribute changes. -.PP -.Vb 10 -\& static void -\& passwd_cb (struct ev_loop *loop, ev_stat *w, int revents) -\& { -\& /* /etc/passwd changed in some way */ -\& if (w\->attr.st_nlink) -\& { -\& printf ("passwd current size %ld\en", (long)w\->attr.st_size); -\& printf ("passwd current atime %ld\en", (long)w\->attr.st_mtime); -\& printf ("passwd current mtime %ld\en", (long)w\->attr.st_mtime); -\& } -\& else -\& /* you shalt not abuse printf for puts */ -\& puts ("wow, /etc/passwd is not there, expect problems. " -\& "if this is windows, they already arrived\en"); -\& } -\& -\& ... -\& ev_stat passwd; -\& -\& ev_stat_init (&passwd, passwd_cb, "/etc/passwd", 0.); -\& ev_stat_start (loop, &passwd); -.Ve -.PP -Example: Like above, but additionally use a one-second delay so we do not -miss updates (however, frequent updates will delay processing, too, so -one might do the work both on \f(CW\*(C`ev_stat\*(C'\fR callback invocation \fIand\fR on -\&\f(CW\*(C`ev_timer\*(C'\fR callback invocation). -.PP -.Vb 2 -\& static ev_stat passwd; -\& static ev_timer timer; -\& -\& static void -\& timer_cb (EV_P_ ev_timer *w, int revents) -\& { -\& ev_timer_stop (EV_A_ w); -\& -\& /* now it\*(Aqs one second after the most recent passwd change */ -\& } -\& -\& static void -\& stat_cb (EV_P_ ev_stat *w, int revents) -\& { -\& /* reset the one\-second timer */ -\& ev_timer_again (EV_A_ &timer); -\& } -\& -\& ... -\& ev_stat_init (&passwd, stat_cb, "/etc/passwd", 0.); -\& ev_stat_start (loop, &passwd); -\& ev_timer_init (&timer, timer_cb, 0., 1.02); -.Ve -.ie n .SS """ev_idle"" \- when you've got nothing better to do..." -.el .SS "\f(CWev_idle\fP \- when you've got nothing better to do..." -.IX Subsection "ev_idle - when you've got nothing better to do..." -Idle watchers trigger events when no other events of the same or higher -priority are pending (prepare, check and other idle watchers do not count -as receiving \*(L"events\*(R"). -.PP -That is, as long as your process is busy handling sockets or timeouts -(or even signals, imagine) of the same or higher priority it will not be -triggered. But when your process is idle (or only lower-priority watchers -are pending), the idle watchers are being called once per event loop -iteration \- until stopped, that is, or your process receives more events -and becomes busy again with higher priority stuff. -.PP -The most noteworthy effect is that as long as any idle watchers are -active, the process will not block when waiting for new events. -.PP -Apart from keeping your process non-blocking (which is a useful -effect on its own sometimes), idle watchers are a good place to do -\&\*(L"pseudo-background processing\*(R", or delay processing stuff to after the -event loop has handled all outstanding events. -.PP -\fIAbusing an \f(CI\*(C`ev_idle\*(C'\fI watcher for its side-effect\fR -.IX Subsection "Abusing an ev_idle watcher for its side-effect" -.PP -As long as there is at least one active idle watcher, libev will never -sleep unnecessarily. Or in other words, it will loop as fast as possible. -For this to work, the idle watcher doesn't need to be invoked at all \- the -lowest priority will do. -.PP -This mode of operation can be useful together with an \f(CW\*(C`ev_check\*(C'\fR watcher, -to do something on each event loop iteration \- for example to balance load -between different connections. -.PP -See \*(L"Abusing an ev_check watcher for its side-effect\*(R" for a longer -example. -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_idle_init (ev_idle *, callback)" 4 -.IX Item "ev_idle_init (ev_idle *, callback)" -Initialises and configures the idle watcher \- it has no parameters of any -kind. There is a \f(CW\*(C`ev_idle_set\*(C'\fR macro, but using it is utterly pointless, -believe me. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: Dynamically allocate an \f(CW\*(C`ev_idle\*(C'\fR watcher, start it, and in the -callback, free it. Also, use no error checking, as usual. -.PP -.Vb 5 -\& static void -\& idle_cb (struct ev_loop *loop, ev_idle *w, int revents) -\& { -\& // stop the watcher -\& ev_idle_stop (loop, w); -\& -\& // now we can free it -\& free (w); -\& -\& // now do something you wanted to do when the program has -\& // no longer anything immediate to do. -\& } -\& -\& ev_idle *idle_watcher = malloc (sizeof (ev_idle)); -\& ev_idle_init (idle_watcher, idle_cb); -\& ev_idle_start (loop, idle_watcher); -.Ve -.ie n .SS """ev_prepare"" and ""ev_check"" \- customise your event loop!" -.el .SS "\f(CWev_prepare\fP and \f(CWev_check\fP \- customise your event loop!" -.IX Subsection "ev_prepare and ev_check - customise your event loop!" -Prepare and check watchers are often (but not always) used in pairs: -prepare watchers get invoked before the process blocks and check watchers -afterwards. -.PP -You \fImust not\fR call \f(CW\*(C`ev_run\*(C'\fR or similar functions that enter -the current event loop from either \f(CW\*(C`ev_prepare\*(C'\fR or \f(CW\*(C`ev_check\*(C'\fR -watchers. Other loops than the current one are fine, however. The -rationale behind this is that you do not need to check for recursion in -those watchers, i.e. the sequence will always be \f(CW\*(C`ev_prepare\*(C'\fR, blocking, -\&\f(CW\*(C`ev_check\*(C'\fR so if you have one watcher of each kind they will always be -called in pairs bracketing the blocking call. -.PP -Their main purpose is to integrate other event mechanisms into libev and -their use is somewhat advanced. They could be used, for example, to track -variable changes, implement your own watchers, integrate net-snmp or a -coroutine library and lots more. They are also occasionally useful if -you cache some data and want to flush it before blocking (for example, -in X programs you might want to do an \f(CW\*(C`XFlush ()\*(C'\fR in an \f(CW\*(C`ev_prepare\*(C'\fR -watcher). -.PP -This is done by examining in each prepare call which file descriptors -need to be watched by the other library, registering \f(CW\*(C`ev_io\*(C'\fR watchers -for them and starting an \f(CW\*(C`ev_timer\*(C'\fR watcher for any timeouts (many -libraries provide exactly this functionality). Then, in the check watcher, -you check for any events that occurred (by checking the pending status -of all watchers and stopping them) and call back into the library. The -I/O and timer callbacks will never actually be called (but must be valid -nevertheless, because you never know, you know?). -.PP -As another example, the Perl Coro module uses these hooks to integrate -coroutines into libev programs, by yielding to other active coroutines -during each prepare and only letting the process block if no coroutines -are ready to run (it's actually more complicated: it only runs coroutines -with priority higher than or equal to the event loop and one coroutine -of lower priority, but only once, using idle watchers to keep the event -loop from blocking if lower-priority coroutines are active, thus mapping -low-priority coroutines to idle/background tasks). -.PP -When used for this purpose, it is recommended to give \f(CW\*(C`ev_check\*(C'\fR watchers -highest (\f(CW\*(C`EV_MAXPRI\*(C'\fR) priority, to ensure that they are being run before -any other watchers after the poll (this doesn't matter for \f(CW\*(C`ev_prepare\*(C'\fR -watchers). -.PP -Also, \f(CW\*(C`ev_check\*(C'\fR watchers (and \f(CW\*(C`ev_prepare\*(C'\fR watchers, too) should not -activate (\*(L"feed\*(R") events into libev. While libev fully supports this, they -might get executed before other \f(CW\*(C`ev_check\*(C'\fR watchers did their job. As -\&\f(CW\*(C`ev_check\*(C'\fR watchers are often used to embed other (non-libev) event -loops those other event loops might be in an unusable state until their -\&\f(CW\*(C`ev_check\*(C'\fR watcher ran (always remind yourself to coexist peacefully with -others). -.PP -\fIAbusing an \f(CI\*(C`ev_check\*(C'\fI watcher for its side-effect\fR -.IX Subsection "Abusing an ev_check watcher for its side-effect" -.PP -\&\f(CW\*(C`ev_check\*(C'\fR (and less often also \f(CW\*(C`ev_prepare\*(C'\fR) watchers can also be -useful because they are called once per event loop iteration. For -example, if you want to handle a large number of connections fairly, you -normally only do a bit of work for each active connection, and if there -is more work to do, you wait for the next event loop iteration, so other -connections have a chance of making progress. -.PP -Using an \f(CW\*(C`ev_check\*(C'\fR watcher is almost enough: it will be called on the -next event loop iteration. However, that isn't as soon as possible \- -without external events, your \f(CW\*(C`ev_check\*(C'\fR watcher will not be invoked. -.PP -This is where \f(CW\*(C`ev_idle\*(C'\fR watchers come in handy \- all you need is a -single global idle watcher that is active as long as you have one active -\&\f(CW\*(C`ev_check\*(C'\fR watcher. The \f(CW\*(C`ev_idle\*(C'\fR watcher makes sure the event loop -will not sleep, and the \f(CW\*(C`ev_check\*(C'\fR watcher makes sure a callback gets -invoked. Neither watcher alone can do that. -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_prepare_init (ev_prepare *, callback)" 4 -.IX Item "ev_prepare_init (ev_prepare *, callback)" -.PD 0 -.IP "ev_check_init (ev_check *, callback)" 4 -.IX Item "ev_check_init (ev_check *, callback)" -.PD -Initialises and configures the prepare or check watcher \- they have no -parameters of any kind. There are \f(CW\*(C`ev_prepare_set\*(C'\fR and \f(CW\*(C`ev_check_set\*(C'\fR -macros, but using them is utterly, utterly, utterly and completely -pointless. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -There are a number of principal ways to embed other event loops or modules -into libev. Here are some ideas on how to include libadns into libev -(there is a Perl module named \f(CW\*(C`EV::ADNS\*(C'\fR that does this, which you could -use as a working example. Another Perl module named \f(CW\*(C`EV::Glib\*(C'\fR embeds a -Glib main context into libev, and finally, \f(CW\*(C`Glib::EV\*(C'\fR embeds \s-1EV\s0 into the -Glib event loop). -.PP -Method 1: Add \s-1IO\s0 watchers and a timeout watcher in a prepare handler, -and in a check watcher, destroy them and call into libadns. What follows -is pseudo-code only of course. This requires you to either use a low -priority for the check watcher or use \f(CW\*(C`ev_clear_pending\*(C'\fR explicitly, as -the callbacks for the IO/timeout watchers might not have been called yet. -.PP -.Vb 2 -\& static ev_io iow [nfd]; -\& static ev_timer tw; -\& -\& static void -\& io_cb (struct ev_loop *loop, ev_io *w, int revents) -\& { -\& } -\& -\& // create io watchers for each fd and a timer before blocking -\& static void -\& adns_prepare_cb (struct ev_loop *loop, ev_prepare *w, int revents) -\& { -\& int timeout = 3600000; -\& struct pollfd fds [nfd]; -\& // actual code will need to loop here and realloc etc. -\& adns_beforepoll (ads, fds, &nfd, &timeout, timeval_from (ev_time ())); -\& -\& /* the callback is illegal, but won\*(Aqt be called as we stop during check */ -\& ev_timer_init (&tw, 0, timeout * 1e\-3, 0.); -\& ev_timer_start (loop, &tw); -\& -\& // create one ev_io per pollfd -\& for (int i = 0; i < nfd; ++i) -\& { -\& ev_io_init (iow + i, io_cb, fds [i].fd, -\& ((fds [i].events & POLLIN ? EV_READ : 0) -\& | (fds [i].events & POLLOUT ? EV_WRITE : 0))); -\& -\& fds [i].revents = 0; -\& ev_io_start (loop, iow + i); -\& } -\& } -\& -\& // stop all watchers after blocking -\& static void -\& adns_check_cb (struct ev_loop *loop, ev_check *w, int revents) -\& { -\& ev_timer_stop (loop, &tw); -\& -\& for (int i = 0; i < nfd; ++i) -\& { -\& // set the relevant poll flags -\& // could also call adns_processreadable etc. here -\& struct pollfd *fd = fds + i; -\& int revents = ev_clear_pending (iow + i); -\& if (revents & EV_READ ) fd\->revents |= fd\->events & POLLIN; -\& if (revents & EV_WRITE) fd\->revents |= fd\->events & POLLOUT; -\& -\& // now stop the watcher -\& ev_io_stop (loop, iow + i); -\& } -\& -\& adns_afterpoll (adns, fds, nfd, timeval_from (ev_now (loop)); -\& } -.Ve -.PP -Method 2: This would be just like method 1, but you run \f(CW\*(C`adns_afterpoll\*(C'\fR -in the prepare watcher and would dispose of the check watcher. -.PP -Method 3: If the module to be embedded supports explicit event -notification (libadns does), you can also make use of the actual watcher -callbacks, and only destroy/create the watchers in the prepare watcher. -.PP -.Vb 5 -\& static void -\& timer_cb (EV_P_ ev_timer *w, int revents) -\& { -\& adns_state ads = (adns_state)w\->data; -\& update_now (EV_A); -\& -\& adns_processtimeouts (ads, &tv_now); -\& } -\& -\& static void -\& io_cb (EV_P_ ev_io *w, int revents) -\& { -\& adns_state ads = (adns_state)w\->data; -\& update_now (EV_A); -\& -\& if (revents & EV_READ ) adns_processreadable (ads, w\->fd, &tv_now); -\& if (revents & EV_WRITE) adns_processwriteable (ads, w\->fd, &tv_now); -\& } -\& -\& // do not ever call adns_afterpoll -.Ve -.PP -Method 4: Do not use a prepare or check watcher because the module you -want to embed is not flexible enough to support it. Instead, you can -override their poll function. The drawback with this solution is that the -main loop is now no longer controllable by \s-1EV\s0. The \f(CW\*(C`Glib::EV\*(C'\fR module uses -this approach, effectively embedding \s-1EV\s0 as a client into the horrible -libglib event loop. -.PP -.Vb 4 -\& static gint -\& event_poll_func (GPollFD *fds, guint nfds, gint timeout) -\& { -\& int got_events = 0; -\& -\& for (n = 0; n < nfds; ++n) -\& // create/start io watcher that sets the relevant bits in fds[n] and increment got_events -\& -\& if (timeout >= 0) -\& // create/start timer -\& -\& // poll -\& ev_run (EV_A_ 0); -\& -\& // stop timer again -\& if (timeout >= 0) -\& ev_timer_stop (EV_A_ &to); -\& -\& // stop io watchers again \- their callbacks should have set -\& for (n = 0; n < nfds; ++n) -\& ev_io_stop (EV_A_ iow [n]); -\& -\& return got_events; -\& } -.Ve -.ie n .SS """ev_embed"" \- when one backend isn't enough..." -.el .SS "\f(CWev_embed\fP \- when one backend isn't enough..." -.IX Subsection "ev_embed - when one backend isn't enough..." -This is a rather advanced watcher type that lets you embed one event loop -into another (currently only \f(CW\*(C`ev_io\*(C'\fR events are supported in the embedded -loop, other types of watchers might be handled in a delayed or incorrect -fashion and must not be used). -.PP -There are primarily two reasons you would want that: work around bugs and -prioritise I/O. -.PP -As an example for a bug workaround, the kqueue backend might only support -sockets on some platform, so it is unusable as generic backend, but you -still want to make use of it because you have many sockets and it scales -so nicely. In this case, you would create a kqueue-based loop and embed -it into your default loop (which might use e.g. poll). Overall operation -will be a bit slower because first libev has to call \f(CW\*(C`poll\*(C'\fR and then -\&\f(CW\*(C`kevent\*(C'\fR, but at least you can use both mechanisms for what they are -best: \f(CW\*(C`kqueue\*(C'\fR for scalable sockets and \f(CW\*(C`poll\*(C'\fR if you want it to work :) -.PP -As for prioritising I/O: under rare circumstances you have the case where -some fds have to be watched and handled very quickly (with low latency), -and even priorities and idle watchers might have too much overhead. In -this case you would put all the high priority stuff in one loop and all -the rest in a second one, and embed the second one in the first. -.PP -As long as the watcher is active, the callback will be invoked every -time there might be events pending in the embedded loop. The callback -must then call \f(CW\*(C`ev_embed_sweep (mainloop, watcher)\*(C'\fR to make a single -sweep and invoke their callbacks (the callback doesn't need to invoke the -\&\f(CW\*(C`ev_embed_sweep\*(C'\fR function directly, it could also start an idle watcher -to give the embedded loop strictly lower priority for example). -.PP -You can also set the callback to \f(CW0\fR, in which case the embed watcher -will automatically execute the embedded loop sweep whenever necessary. -.PP -Fork detection will be handled transparently while the \f(CW\*(C`ev_embed\*(C'\fR watcher -is active, i.e., the embedded loop will automatically be forked when the -embedding loop forks. In other cases, the user is responsible for calling -\&\f(CW\*(C`ev_loop_fork\*(C'\fR on the embedded loop. -.PP -Unfortunately, not all backends are embeddable: only the ones returned by -\&\f(CW\*(C`ev_embeddable_backends\*(C'\fR are, which, unfortunately, does not include any -portable one. -.PP -So when you want to use this feature you will always have to be prepared -that you cannot get an embeddable loop. The recommended way to get around -this is to have a separate variables for your embeddable loop, try to -create it, and if that fails, use the normal loop for everything. -.PP -\fI\f(CI\*(C`ev_embed\*(C'\fI and fork\fR -.IX Subsection "ev_embed and fork" -.PP -While the \f(CW\*(C`ev_embed\*(C'\fR watcher is running, forks in the embedding loop will -automatically be applied to the embedded loop as well, so no special -fork handling is required in that case. When the watcher is not running, -however, it is still the task of the libev user to call \f(CW\*(C`ev_loop_fork ()\*(C'\fR -as applicable. -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)" 4 -.IX Item "ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)" -.PD 0 -.IP "ev_embed_set (ev_embed *, struct ev_loop *embedded_loop)" 4 -.IX Item "ev_embed_set (ev_embed *, struct ev_loop *embedded_loop)" -.PD -Configures the watcher to embed the given loop, which must be -embeddable. If the callback is \f(CW0\fR, then \f(CW\*(C`ev_embed_sweep\*(C'\fR will be -invoked automatically, otherwise it is the responsibility of the callback -to invoke it (it will continue to be called until the sweep has been done, -if you do not want that, you need to temporarily stop the embed watcher). -.IP "ev_embed_sweep (loop, ev_embed *)" 4 -.IX Item "ev_embed_sweep (loop, ev_embed *)" -Make a single, non-blocking sweep over the embedded loop. This works -similarly to \f(CW\*(C`ev_run (embedded_loop, EVRUN_NOWAIT)\*(C'\fR, but in the most -appropriate way for embedded loops. -.IP "struct ev_loop *other [read\-only]" 4 -.IX Item "struct ev_loop *other [read-only]" -The embedded event loop. -.PP -\fIExamples\fR -.IX Subsection "Examples" -.PP -Example: Try to get an embeddable event loop and embed it into the default -event loop. If that is not possible, use the default loop. The default -loop is stored in \f(CW\*(C`loop_hi\*(C'\fR, while the embeddable loop is stored in -\&\f(CW\*(C`loop_lo\*(C'\fR (which is \f(CW\*(C`loop_hi\*(C'\fR in the case no embeddable loop can be -used). -.PP -.Vb 3 -\& struct ev_loop *loop_hi = ev_default_init (0); -\& struct ev_loop *loop_lo = 0; -\& ev_embed embed; -\& -\& // see if there is a chance of getting one that works -\& // (remember that a flags value of 0 means autodetection) -\& loop_lo = ev_embeddable_backends () & ev_recommended_backends () -\& ? ev_loop_new (ev_embeddable_backends () & ev_recommended_backends ()) -\& : 0; -\& -\& // if we got one, then embed it, otherwise default to loop_hi -\& if (loop_lo) -\& { -\& ev_embed_init (&embed, 0, loop_lo); -\& ev_embed_start (loop_hi, &embed); -\& } -\& else -\& loop_lo = loop_hi; -.Ve -.PP -Example: Check if kqueue is available but not recommended and create -a kqueue backend for use with sockets (which usually work with any -kqueue implementation). Store the kqueue/socket\-only event loop in -\&\f(CW\*(C`loop_socket\*(C'\fR. (One might optionally use \f(CW\*(C`EVFLAG_NOENV\*(C'\fR, too). -.PP -.Vb 3 -\& struct ev_loop *loop = ev_default_init (0); -\& struct ev_loop *loop_socket = 0; -\& ev_embed embed; -\& -\& if (ev_supported_backends () & ~ev_recommended_backends () & EVBACKEND_KQUEUE) -\& if ((loop_socket = ev_loop_new (EVBACKEND_KQUEUE)) -\& { -\& ev_embed_init (&embed, 0, loop_socket); -\& ev_embed_start (loop, &embed); -\& } -\& -\& if (!loop_socket) -\& loop_socket = loop; -\& -\& // now use loop_socket for all sockets, and loop for everything else -.Ve -.ie n .SS """ev_fork"" \- the audacity to resume the event loop after a fork" -.el .SS "\f(CWev_fork\fP \- the audacity to resume the event loop after a fork" -.IX Subsection "ev_fork - the audacity to resume the event loop after a fork" -Fork watchers are called when a \f(CW\*(C`fork ()\*(C'\fR was detected (usually because -whoever is a good citizen cared to tell libev about it by calling -\&\f(CW\*(C`ev_loop_fork\*(C'\fR). The invocation is done before the event loop blocks next -and before \f(CW\*(C`ev_check\*(C'\fR watchers are being called, and only in the child -after the fork. If whoever good citizen calling \f(CW\*(C`ev_default_fork\*(C'\fR cheats -and calls it in the wrong process, the fork handlers will be invoked, too, -of course. -.PP -\fIThe special problem of life after fork \- how is it possible?\fR -.IX Subsection "The special problem of life after fork - how is it possible?" -.PP -Most uses of \f(CW\*(C`fork()\*(C'\fR consist of forking, then some simple calls to set -up/change the process environment, followed by a call to \f(CW\*(C`exec()\*(C'\fR. This -sequence should be handled by libev without any problems. -.PP -This changes when the application actually wants to do event handling -in the child, or both parent in child, in effect \*(L"continuing\*(R" after the -fork. -.PP -The default mode of operation (for libev, with application help to detect -forks) is to duplicate all the state in the child, as would be expected -when \fIeither\fR the parent \fIor\fR the child process continues. -.PP -When both processes want to continue using libev, then this is usually the -wrong result. In that case, usually one process (typically the parent) is -supposed to continue with all watchers in place as before, while the other -process typically wants to start fresh, i.e. without any active watchers. -.PP -The cleanest and most efficient way to achieve that with libev is to -simply create a new event loop, which of course will be \*(L"empty\*(R", and -use that for new watchers. This has the advantage of not touching more -memory than necessary, and thus avoiding the copy-on-write, and the -disadvantage of having to use multiple event loops (which do not support -signal watchers). -.PP -When this is not possible, or you want to use the default loop for -other reasons, then in the process that wants to start \*(L"fresh\*(R", call -\&\f(CW\*(C`ev_loop_destroy (EV_DEFAULT)\*(C'\fR followed by \f(CW\*(C`ev_default_loop (...)\*(C'\fR. -Destroying the default loop will \*(L"orphan\*(R" (not stop) all registered -watchers, so you have to be careful not to execute code that modifies -those watchers. Note also that in that case, you have to re-register any -signal watchers. -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_fork_init (ev_fork *, callback)" 4 -.IX Item "ev_fork_init (ev_fork *, callback)" -Initialises and configures the fork watcher \- it has no parameters of any -kind. There is a \f(CW\*(C`ev_fork_set\*(C'\fR macro, but using it is utterly pointless, -really. -.ie n .SS """ev_cleanup"" \- even the best things end" -.el .SS "\f(CWev_cleanup\fP \- even the best things end" -.IX Subsection "ev_cleanup - even the best things end" -Cleanup watchers are called just before the event loop is being destroyed -by a call to \f(CW\*(C`ev_loop_destroy\*(C'\fR. -.PP -While there is no guarantee that the event loop gets destroyed, cleanup -watchers provide a convenient method to install cleanup hooks for your -program, worker threads and so on \- you just to make sure to destroy the -loop when you want them to be invoked. -.PP -Cleanup watchers are invoked in the same way as any other watcher. Unlike -all other watchers, they do not keep a reference to the event loop (which -makes a lot of sense if you think about it). Like all other watchers, you -can call libev functions in the callback, except \f(CW\*(C`ev_cleanup_start\*(C'\fR. -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_cleanup_init (ev_cleanup *, callback)" 4 -.IX Item "ev_cleanup_init (ev_cleanup *, callback)" -Initialises and configures the cleanup watcher \- it has no parameters of -any kind. There is a \f(CW\*(C`ev_cleanup_set\*(C'\fR macro, but using it is utterly -pointless, I assure you. -.PP -Example: Register an atexit handler to destroy the default loop, so any -cleanup functions are called. -.PP -.Vb 5 -\& static void -\& program_exits (void) -\& { -\& ev_loop_destroy (EV_DEFAULT_UC); -\& } -\& -\& ... -\& atexit (program_exits); -.Ve -.ie n .SS """ev_async"" \- how to wake up an event loop" -.el .SS "\f(CWev_async\fP \- how to wake up an event loop" -.IX Subsection "ev_async - how to wake up an event loop" -In general, you cannot use an \f(CW\*(C`ev_loop\*(C'\fR from multiple threads or other -asynchronous sources such as signal handlers (as opposed to multiple event -loops \- those are of course safe to use in different threads). -.PP -Sometimes, however, you need to wake up an event loop you do not control, -for example because it belongs to another thread. This is what \f(CW\*(C`ev_async\*(C'\fR -watchers do: as long as the \f(CW\*(C`ev_async\*(C'\fR watcher is active, you can signal -it by calling \f(CW\*(C`ev_async_send\*(C'\fR, which is thread\- and signal safe. -.PP -This functionality is very similar to \f(CW\*(C`ev_signal\*(C'\fR watchers, as signals, -too, are asynchronous in nature, and signals, too, will be compressed -(i.e. the number of callback invocations may be less than the number of -\&\f(CW\*(C`ev_async_send\*(C'\fR calls). In fact, you could use signal watchers as a kind -of \*(L"global async watchers\*(R" by using a watcher on an otherwise unused -signal, and \f(CW\*(C`ev_feed_signal\*(C'\fR to signal this watcher from another thread, -even without knowing which loop owns the signal. -.PP -\fIQueueing\fR -.IX Subsection "Queueing" -.PP -\&\f(CW\*(C`ev_async\*(C'\fR does not support queueing of data in any way. The reason -is that the author does not know of a simple (or any) algorithm for a -multiple-writer-single-reader queue that works in all cases and doesn't -need elaborate support such as pthreads or unportable memory access -semantics. -.PP -That means that if you want to queue data, you have to provide your own -queue. But at least I can tell you how to implement locking around your -queue: -.IP "queueing from a signal handler context" 4 -.IX Item "queueing from a signal handler context" -To implement race-free queueing, you simply add to the queue in the signal -handler but you block the signal handler in the watcher callback. Here is -an example that does that for some fictitious \s-1SIGUSR1\s0 handler: -.Sp -.Vb 1 -\& static ev_async mysig; -\& -\& static void -\& sigusr1_handler (void) -\& { -\& sometype data; -\& -\& // no locking etc. -\& queue_put (data); -\& ev_async_send (EV_DEFAULT_ &mysig); -\& } -\& -\& static void -\& mysig_cb (EV_P_ ev_async *w, int revents) -\& { -\& sometype data; -\& sigset_t block, prev; -\& -\& sigemptyset (&block); -\& sigaddset (&block, SIGUSR1); -\& sigprocmask (SIG_BLOCK, &block, &prev); -\& -\& while (queue_get (&data)) -\& process (data); -\& -\& if (sigismember (&prev, SIGUSR1) -\& sigprocmask (SIG_UNBLOCK, &block, 0); -\& } -.Ve -.Sp -(Note: pthreads in theory requires you to use \f(CW\*(C`pthread_setmask\*(C'\fR -instead of \f(CW\*(C`sigprocmask\*(C'\fR when you use threads, but libev doesn't do it -either...). -.IP "queueing from a thread context" 4 -.IX Item "queueing from a thread context" -The strategy for threads is different, as you cannot (easily) block -threads but you can easily preempt them, so to queue safely you need to -employ a traditional mutex lock, such as in this pthread example: -.Sp -.Vb 2 -\& static ev_async mysig; -\& static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; -\& -\& static void -\& otherthread (void) -\& { -\& // only need to lock the actual queueing operation -\& pthread_mutex_lock (&mymutex); -\& queue_put (data); -\& pthread_mutex_unlock (&mymutex); -\& -\& ev_async_send (EV_DEFAULT_ &mysig); -\& } -\& -\& static void -\& mysig_cb (EV_P_ ev_async *w, int revents) -\& { -\& pthread_mutex_lock (&mymutex); -\& -\& while (queue_get (&data)) -\& process (data); -\& -\& pthread_mutex_unlock (&mymutex); -\& } -.Ve -.PP -\fIWatcher-Specific Functions and Data Members\fR -.IX Subsection "Watcher-Specific Functions and Data Members" -.IP "ev_async_init (ev_async *, callback)" 4 -.IX Item "ev_async_init (ev_async *, callback)" -Initialises and configures the async watcher \- it has no parameters of any -kind. There is a \f(CW\*(C`ev_async_set\*(C'\fR macro, but using it is utterly pointless, -trust me. -.IP "ev_async_send (loop, ev_async *)" 4 -.IX Item "ev_async_send (loop, ev_async *)" -Sends/signals/activates the given \f(CW\*(C`ev_async\*(C'\fR watcher, that is, feeds -an \f(CW\*(C`EV_ASYNC\*(C'\fR event on the watcher into the event loop, and instantly -returns. -.Sp -Unlike \f(CW\*(C`ev_feed_event\*(C'\fR, this call is safe to do from other threads, -signal or similar contexts (see the discussion of \f(CW\*(C`EV_ATOMIC_T\*(C'\fR in the -embedding section below on what exactly this means). -.Sp -Note that, as with other watchers in libev, multiple events might get -compressed into a single callback invocation (another way to look at -this is that \f(CW\*(C`ev_async\*(C'\fR watchers are level-triggered: they are set on -\&\f(CW\*(C`ev_async_send\*(C'\fR, reset when the event loop detects that). -.Sp -This call incurs the overhead of at most one extra system call per event -loop iteration, if the event loop is blocked, and no syscall at all if -the event loop (or your program) is processing events. That means that -repeated calls are basically free (there is no need to avoid calls for -performance reasons) and that the overhead becomes smaller (typically -zero) under load. -.IP "bool = ev_async_pending (ev_async *)" 4 -.IX Item "bool = ev_async_pending (ev_async *)" -Returns a non-zero value when \f(CW\*(C`ev_async_send\*(C'\fR has been called on the -watcher but the event has not yet been processed (or even noted) by the -event loop. -.Sp -\&\f(CW\*(C`ev_async_send\*(C'\fR sets a flag in the watcher and wakes up the loop. When -the loop iterates next and checks for the watcher to have become active, -it will reset the flag again. \f(CW\*(C`ev_async_pending\*(C'\fR can be used to very -quickly check whether invoking the loop might be a good idea. -.Sp -Not that this does \fInot\fR check whether the watcher itself is pending, -only whether it has been requested to make this watcher pending: there -is a time window between the event loop checking and resetting the async -notification, and the callback being invoked. -.SH "OTHER FUNCTIONS" -.IX Header "OTHER FUNCTIONS" -There are some other functions of possible interest. Described. Here. Now. -.IP "ev_once (loop, int fd, int events, ev_tstamp timeout, callback)" 4 -.IX Item "ev_once (loop, int fd, int events, ev_tstamp timeout, callback)" -This function combines a simple timer and an I/O watcher, calls your -callback on whichever event happens first and automatically stops both -watchers. This is useful if you want to wait for a single event on an fd -or timeout without having to allocate/configure/start/stop/free one or -more watchers yourself. -.Sp -If \f(CW\*(C`fd\*(C'\fR is less than 0, then no I/O watcher will be started and the -\&\f(CW\*(C`events\*(C'\fR argument is being ignored. Otherwise, an \f(CW\*(C`ev_io\*(C'\fR watcher for -the given \f(CW\*(C`fd\*(C'\fR and \f(CW\*(C`events\*(C'\fR set will be created and started. -.Sp -If \f(CW\*(C`timeout\*(C'\fR is less than 0, then no timeout watcher will be -started. Otherwise an \f(CW\*(C`ev_timer\*(C'\fR watcher with after = \f(CW\*(C`timeout\*(C'\fR (and -repeat = 0) will be started. \f(CW0\fR is a valid timeout. -.Sp -The callback has the type \f(CW\*(C`void (*cb)(int revents, void *arg)\*(C'\fR and is -passed an \f(CW\*(C`revents\*(C'\fR set like normal event callbacks (a combination of -\&\f(CW\*(C`EV_ERROR\*(C'\fR, \f(CW\*(C`EV_READ\*(C'\fR, \f(CW\*(C`EV_WRITE\*(C'\fR or \f(CW\*(C`EV_TIMER\*(C'\fR) and the \f(CW\*(C`arg\*(C'\fR -value passed to \f(CW\*(C`ev_once\*(C'\fR. Note that it is possible to receive \fIboth\fR -a timeout and an io event at the same time \- you probably should give io -events precedence. -.Sp -Example: wait up to ten seconds for data to appear on \s-1STDIN_FILENO\s0. -.Sp -.Vb 7 -\& static void stdin_ready (int revents, void *arg) -\& { -\& if (revents & EV_READ) -\& /* stdin might have data for us, joy! */; -\& else if (revents & EV_TIMER) -\& /* doh, nothing entered */; -\& } -\& -\& ev_once (STDIN_FILENO, EV_READ, 10., stdin_ready, 0); -.Ve -.IP "ev_feed_fd_event (loop, int fd, int revents)" 4 -.IX Item "ev_feed_fd_event (loop, int fd, int revents)" -Feed an event on the given fd, as if a file descriptor backend detected -the given events. -.IP "ev_feed_signal_event (loop, int signum)" 4 -.IX Item "ev_feed_signal_event (loop, int signum)" -Feed an event as if the given signal occurred. See also \f(CW\*(C`ev_feed_signal\*(C'\fR, -which is async-safe. -.SH "COMMON OR USEFUL IDIOMS (OR BOTH)" -.IX Header "COMMON OR USEFUL IDIOMS (OR BOTH)" -This section explains some common idioms that are not immediately -obvious. Note that examples are sprinkled over the whole manual, and this -section only contains stuff that wouldn't fit anywhere else. -.SS "\s-1ASSOCIATING\s0 \s-1CUSTOM\s0 \s-1DATA\s0 \s-1WITH\s0 A \s-1WATCHER\s0" -.IX Subsection "ASSOCIATING CUSTOM DATA WITH A WATCHER" -Each watcher has, by default, a \f(CW\*(C`void *data\*(C'\fR member that you can read -or modify at any time: libev will completely ignore it. This can be used -to associate arbitrary data with your watcher. If you need more data and -don't want to allocate memory separately and store a pointer to it in that -data member, you can also \*(L"subclass\*(R" the watcher type and provide your own -data: -.PP -.Vb 7 -\& struct my_io -\& { -\& ev_io io; -\& int otherfd; -\& void *somedata; -\& struct whatever *mostinteresting; -\& }; -\& -\& ... -\& struct my_io w; -\& ev_io_init (&w.io, my_cb, fd, EV_READ); -.Ve -.PP -And since your callback will be called with a pointer to the watcher, you -can cast it back to your own type: -.PP -.Vb 5 -\& static void my_cb (struct ev_loop *loop, ev_io *w_, int revents) -\& { -\& struct my_io *w = (struct my_io *)w_; -\& ... -\& } -.Ve -.PP -More interesting and less C\-conformant ways of casting your callback -function type instead have been omitted. -.SS "\s-1BUILDING\s0 \s-1YOUR\s0 \s-1OWN\s0 \s-1COMPOSITE\s0 \s-1WATCHERS\s0" -.IX Subsection "BUILDING YOUR OWN COMPOSITE WATCHERS" -Another common scenario is to use some data structure with multiple -embedded watchers, in effect creating your own watcher that combines -multiple libev event sources into one \*(L"super-watcher\*(R": -.PP -.Vb 6 -\& struct my_biggy -\& { -\& int some_data; -\& ev_timer t1; -\& ev_timer t2; -\& } -.Ve -.PP -In this case getting the pointer to \f(CW\*(C`my_biggy\*(C'\fR is a bit more -complicated: Either you store the address of your \f(CW\*(C`my_biggy\*(C'\fR struct in -the \f(CW\*(C`data\*(C'\fR member of the watcher (for woozies or \*(C+ coders), or you need -to use some pointer arithmetic using \f(CW\*(C`offsetof\*(C'\fR inside your watchers (for -real programmers): -.PP -.Vb 1 -\& #include -\& -\& static void -\& t1_cb (EV_P_ ev_timer *w, int revents) -\& { -\& struct my_biggy big = (struct my_biggy *) -\& (((char *)w) \- offsetof (struct my_biggy, t1)); -\& } -\& -\& static void -\& t2_cb (EV_P_ ev_timer *w, int revents) -\& { -\& struct my_biggy big = (struct my_biggy *) -\& (((char *)w) \- offsetof (struct my_biggy, t2)); -\& } -.Ve -.SS "\s-1AVOIDING\s0 \s-1FINISHING\s0 \s-1BEFORE\s0 \s-1RETURNING\s0" -.IX Subsection "AVOIDING FINISHING BEFORE RETURNING" -Often you have structures like this in event-based programs: -.PP -.Vb 4 -\& callback () -\& { -\& free (request); -\& } -\& -\& request = start_new_request (..., callback); -.Ve -.PP -The intent is to start some \*(L"lengthy\*(R" operation. The \f(CW\*(C`request\*(C'\fR could be -used to cancel the operation, or do other things with it. -.PP -It's not uncommon to have code paths in \f(CW\*(C`start_new_request\*(C'\fR that -immediately invoke the callback, for example, to report errors. Or you add -some caching layer that finds that it can skip the lengthy aspects of the -operation and simply invoke the callback with the result. -.PP -The problem here is that this will happen \fIbefore\fR \f(CW\*(C`start_new_request\*(C'\fR -has returned, so \f(CW\*(C`request\*(C'\fR is not set. -.PP -Even if you pass the request by some safer means to the callback, you -might want to do something to the request after starting it, such as -canceling it, which probably isn't working so well when the callback has -already been invoked. -.PP -A common way around all these issues is to make sure that -\&\f(CW\*(C`start_new_request\*(C'\fR \fIalways\fR returns before the callback is invoked. If -\&\f(CW\*(C`start_new_request\*(C'\fR immediately knows the result, it can artificially -delay invoking the callback by using a \f(CW\*(C`prepare\*(C'\fR or \f(CW\*(C`idle\*(C'\fR watcher for -example, or more sneakily, by reusing an existing (stopped) watcher and -pushing it into the pending queue: -.PP -.Vb 2 -\& ev_set_cb (watcher, callback); -\& ev_feed_event (EV_A_ watcher, 0); -.Ve -.PP -This way, \f(CW\*(C`start_new_request\*(C'\fR can safely return before the callback is -invoked, while not delaying callback invocation too much. -.SS "\s-1MODEL/NESTED\s0 \s-1EVENT\s0 \s-1LOOP\s0 \s-1INVOCATIONS\s0 \s-1AND\s0 \s-1EXIT\s0 \s-1CONDITIONS\s0" -.IX Subsection "MODEL/NESTED EVENT LOOP INVOCATIONS AND EXIT CONDITIONS" -Often (especially in \s-1GUI\s0 toolkits) there are places where you have -\&\fImodal\fR interaction, which is most easily implemented by recursively -invoking \f(CW\*(C`ev_run\*(C'\fR. -.PP -This brings the problem of exiting \- a callback might want to finish the -main \f(CW\*(C`ev_run\*(C'\fR call, but not the nested one (e.g. user clicked \*(L"Quit\*(R", but -a modal \*(L"Are you sure?\*(R" dialog is still waiting), or just the nested one -and not the main one (e.g. user clocked \*(L"Ok\*(R" in a modal dialog), or some -other combination: In these cases, a simple \f(CW\*(C`ev_break\*(C'\fR will not work. -.PP -The solution is to maintain \*(L"break this loop\*(R" variable for each \f(CW\*(C`ev_run\*(C'\fR -invocation, and use a loop around \f(CW\*(C`ev_run\*(C'\fR until the condition is -triggered, using \f(CW\*(C`EVRUN_ONCE\*(C'\fR: -.PP -.Vb 2 -\& // main loop -\& int exit_main_loop = 0; -\& -\& while (!exit_main_loop) -\& ev_run (EV_DEFAULT_ EVRUN_ONCE); -\& -\& // in a modal watcher -\& int exit_nested_loop = 0; -\& -\& while (!exit_nested_loop) -\& ev_run (EV_A_ EVRUN_ONCE); -.Ve -.PP -To exit from any of these loops, just set the corresponding exit variable: -.PP -.Vb 2 -\& // exit modal loop -\& exit_nested_loop = 1; -\& -\& // exit main program, after modal loop is finished -\& exit_main_loop = 1; -\& -\& // exit both -\& exit_main_loop = exit_nested_loop = 1; -.Ve -.SS "\s-1THREAD\s0 \s-1LOCKING\s0 \s-1EXAMPLE\s0" -.IX Subsection "THREAD LOCKING EXAMPLE" -Here is a fictitious example of how to run an event loop in a different -thread from where callbacks are being invoked and watchers are -created/added/removed. -.PP -For a real-world example, see the \f(CW\*(C`EV::Loop::Async\*(C'\fR perl module, -which uses exactly this technique (which is suited for many high-level -languages). -.PP -The example uses a pthread mutex to protect the loop data, a condition -variable to wait for callback invocations, an async watcher to notify the -event loop thread and an unspecified mechanism to wake up the main thread. -.PP -First, you need to associate some data with the event loop: -.PP -.Vb 6 -\& typedef struct { -\& mutex_t lock; /* global loop lock */ -\& ev_async async_w; -\& thread_t tid; -\& cond_t invoke_cv; -\& } userdata; -\& -\& void prepare_loop (EV_P) -\& { -\& // for simplicity, we use a static userdata struct. -\& static userdata u; -\& -\& ev_async_init (&u\->async_w, async_cb); -\& ev_async_start (EV_A_ &u\->async_w); -\& -\& pthread_mutex_init (&u\->lock, 0); -\& pthread_cond_init (&u\->invoke_cv, 0); -\& -\& // now associate this with the loop -\& ev_set_userdata (EV_A_ u); -\& ev_set_invoke_pending_cb (EV_A_ l_invoke); -\& ev_set_loop_release_cb (EV_A_ l_release, l_acquire); -\& -\& // then create the thread running ev_run -\& pthread_create (&u\->tid, 0, l_run, EV_A); -\& } -.Ve -.PP -The callback for the \f(CW\*(C`ev_async\*(C'\fR watcher does nothing: the watcher is used -solely to wake up the event loop so it takes notice of any new watchers -that might have been added: -.PP -.Vb 5 -\& static void -\& async_cb (EV_P_ ev_async *w, int revents) -\& { -\& // just used for the side effects -\& } -.Ve -.PP -The \f(CW\*(C`l_release\*(C'\fR and \f(CW\*(C`l_acquire\*(C'\fR callbacks simply unlock/lock the mutex -protecting the loop data, respectively. -.PP -.Vb 6 -\& static void -\& l_release (EV_P) -\& { -\& userdata *u = ev_userdata (EV_A); -\& pthread_mutex_unlock (&u\->lock); -\& } -\& -\& static void -\& l_acquire (EV_P) -\& { -\& userdata *u = ev_userdata (EV_A); -\& pthread_mutex_lock (&u\->lock); -\& } -.Ve -.PP -The event loop thread first acquires the mutex, and then jumps straight -into \f(CW\*(C`ev_run\*(C'\fR: -.PP -.Vb 4 -\& void * -\& l_run (void *thr_arg) -\& { -\& struct ev_loop *loop = (struct ev_loop *)thr_arg; -\& -\& l_acquire (EV_A); -\& pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); -\& ev_run (EV_A_ 0); -\& l_release (EV_A); -\& -\& return 0; -\& } -.Ve -.PP -Instead of invoking all pending watchers, the \f(CW\*(C`l_invoke\*(C'\fR callback will -signal the main thread via some unspecified mechanism (signals? pipe -writes? \f(CW\*(C`Async::Interrupt\*(C'\fR?) and then waits until all pending watchers -have been called (in a while loop because a) spurious wakeups are possible -and b) skipping inter-thread-communication when there are no pending -watchers is very beneficial): -.PP -.Vb 4 -\& static void -\& l_invoke (EV_P) -\& { -\& userdata *u = ev_userdata (EV_A); -\& -\& while (ev_pending_count (EV_A)) -\& { -\& wake_up_other_thread_in_some_magic_or_not_so_magic_way (); -\& pthread_cond_wait (&u\->invoke_cv, &u\->lock); -\& } -\& } -.Ve -.PP -Now, whenever the main thread gets told to invoke pending watchers, it -will grab the lock, call \f(CW\*(C`ev_invoke_pending\*(C'\fR and then signal the loop -thread to continue: -.PP -.Vb 4 -\& static void -\& real_invoke_pending (EV_P) -\& { -\& userdata *u = ev_userdata (EV_A); -\& -\& pthread_mutex_lock (&u\->lock); -\& ev_invoke_pending (EV_A); -\& pthread_cond_signal (&u\->invoke_cv); -\& pthread_mutex_unlock (&u\->lock); -\& } -.Ve -.PP -Whenever you want to start/stop a watcher or do other modifications to an -event loop, you will now have to lock: -.PP -.Vb 2 -\& ev_timer timeout_watcher; -\& userdata *u = ev_userdata (EV_A); -\& -\& ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); -\& -\& pthread_mutex_lock (&u\->lock); -\& ev_timer_start (EV_A_ &timeout_watcher); -\& ev_async_send (EV_A_ &u\->async_w); -\& pthread_mutex_unlock (&u\->lock); -.Ve -.PP -Note that sending the \f(CW\*(C`ev_async\*(C'\fR watcher is required because otherwise -an event loop currently blocking in the kernel will have no knowledge -about the newly added timer. By waking up the loop it will pick up any new -watchers in the next event loop iteration. -.SS "\s-1THREADS\s0, \s-1COROUTINES\s0, \s-1CONTINUATIONS\s0, \s-1QUEUES\s0... \s-1INSTEAD\s0 \s-1OF\s0 \s-1CALLBACKS\s0" -.IX Subsection "THREADS, COROUTINES, CONTINUATIONS, QUEUES... INSTEAD OF CALLBACKS" -While the overhead of a callback that e.g. schedules a thread is small, it -is still an overhead. If you embed libev, and your main usage is with some -kind of threads or coroutines, you might want to customise libev so that -doesn't need callbacks anymore. -.PP -Imagine you have coroutines that you can switch to using a function -\&\f(CW\*(C`switch_to (coro)\*(C'\fR, that libev runs in a coroutine called \f(CW\*(C`libev_coro\*(C'\fR -and that due to some magic, the currently active coroutine is stored in a -global called \f(CW\*(C`current_coro\*(C'\fR. Then you can build your own \*(L"wait for libev -event\*(R" primitive by changing \f(CW\*(C`EV_CB_DECLARE\*(C'\fR and \f(CW\*(C`EV_CB_INVOKE\*(C'\fR (note -the differing \f(CW\*(C`;\*(C'\fR conventions): -.PP -.Vb 2 -\& #define EV_CB_DECLARE(type) struct my_coro *cb; -\& #define EV_CB_INVOKE(watcher) switch_to ((watcher)\->cb) -.Ve -.PP -That means instead of having a C callback function, you store the -coroutine to switch to in each watcher, and instead of having libev call -your callback, you instead have it switch to that coroutine. -.PP -A coroutine might now wait for an event with a function called -\&\f(CW\*(C`wait_for_event\*(C'\fR. (the watcher needs to be started, as always, but it doesn't -matter when, or whether the watcher is active or not when this function is -called): -.PP -.Vb 6 -\& void -\& wait_for_event (ev_watcher *w) -\& { -\& ev_set_cb (w, current_coro); -\& switch_to (libev_coro); -\& } -.Ve -.PP -That basically suspends the coroutine inside \f(CW\*(C`wait_for_event\*(C'\fR and -continues the libev coroutine, which, when appropriate, switches back to -this or any other coroutine. -.PP -You can do similar tricks if you have, say, threads with an event queue \- -instead of storing a coroutine, you store the queue object and instead of -switching to a coroutine, you push the watcher onto the queue and notify -any waiters. -.PP -To embed libev, see \*(L"\s-1EMBEDDING\s0\*(R", but in short, it's easiest to create two -files, \fImy_ev.h\fR and \fImy_ev.c\fR that include the respective libev files: -.PP -.Vb 4 -\& // my_ev.h -\& #define EV_CB_DECLARE(type) struct my_coro *cb; -\& #define EV_CB_INVOKE(watcher) switch_to ((watcher)\->cb); -\& #include "../libev/ev.h" -\& -\& // my_ev.c -\& #define EV_H "my_ev.h" -\& #include "../libev/ev.c" -.Ve -.PP -And then use \fImy_ev.h\fR when you would normally use \fIev.h\fR, and compile -\&\fImy_ev.c\fR into your project. When properly specifying include paths, you -can even use \fIev.h\fR as header file name directly. -.SH "LIBEVENT EMULATION" -.IX Header "LIBEVENT EMULATION" -Libev offers a compatibility emulation layer for libevent. It cannot -emulate the internals of libevent, so here are some usage hints: -.IP "\(bu" 4 -Only the libevent\-1.4.1\-beta \s-1API\s0 is being emulated. -.Sp -This was the newest libevent version available when libev was implemented, -and is still mostly unchanged in 2010. -.IP "\(bu" 4 -Use it by including , as usual. -.IP "\(bu" 4 -The following members are fully supported: ev_base, ev_callback, -ev_arg, ev_fd, ev_res, ev_events. -.IP "\(bu" 4 -Avoid using ev_flags and the EVLIST_*\-macros, while it is -maintained by libev, it does not work exactly the same way as in libevent (consider -it a private \s-1API\s0). -.IP "\(bu" 4 -Priorities are not currently supported. Initialising priorities -will fail and all watchers will have the same priority, even though there -is an ev_pri field. -.IP "\(bu" 4 -In libevent, the last base created gets the signals, in libev, the -base that registered the signal gets the signals. -.IP "\(bu" 4 -Other members are not supported. -.IP "\(bu" 4 -The libev emulation is \fInot\fR \s-1ABI\s0 compatible to libevent, you need -to use the libev header file and library. -.SH "\*(C+ SUPPORT" -.IX Header " SUPPORT" -.SS "C \s-1API\s0" -.IX Subsection "C API" -The normal C \s-1API\s0 should work fine when used from \*(C+: both ev.h and the -libev sources can be compiled as \*(C+. Therefore, code that uses the C \s-1API\s0 -will work fine. -.PP -Proper exception specifications might have to be added to callbacks passed -to libev: exceptions may be thrown only from watcher callbacks, all -other callbacks (allocator, syserr, loop acquire/release and periodic -reschedule callbacks) must not throw exceptions, and might need a \f(CW\*(C`throw -()\*(C'\fR specification. If you have code that needs to be compiled as both C -and \*(C+ you can use the \f(CW\*(C`EV_THROW\*(C'\fR macro for this: -.PP -.Vb 6 -\& static void -\& fatal_error (const char *msg) EV_THROW -\& { -\& perror (msg); -\& abort (); -\& } -\& -\& ... -\& ev_set_syserr_cb (fatal_error); -.Ve -.PP -The only \s-1API\s0 functions that can currently throw exceptions are \f(CW\*(C`ev_run\*(C'\fR, -\&\f(CW\*(C`ev_invoke\*(C'\fR, \f(CW\*(C`ev_invoke_pending\*(C'\fR and \f(CW\*(C`ev_loop_destroy\*(C'\fR (the latter -because it runs cleanup watchers). -.PP -Throwing exceptions in watcher callbacks is only supported if libev itself -is compiled with a \*(C+ compiler or your C and \*(C+ environments allow -throwing exceptions through C libraries (most do). -.SS "\*(C+ \s-1API\s0" -.IX Subsection " API" -Libev comes with some simplistic wrapper classes for \*(C+ that mainly allow -you to use some convenience methods to start/stop watchers and also change -the callback model to a model using method callbacks on objects. -.PP -To use it, -.PP -.Vb 1 -\& #include -.Ve -.PP -This automatically includes \fIev.h\fR and puts all of its definitions (many -of them macros) into the global namespace. All \*(C+ specific things are -put into the \f(CW\*(C`ev\*(C'\fR namespace. It should support all the same embedding -options as \fIev.h\fR, most notably \f(CW\*(C`EV_MULTIPLICITY\*(C'\fR. -.PP -Care has been taken to keep the overhead low. The only data member the \*(C+ -classes add (compared to plain C\-style watchers) is the event loop pointer -that the watcher is associated with (or no additional members at all if -you disable \f(CW\*(C`EV_MULTIPLICITY\*(C'\fR when embedding libev). -.PP -Currently, functions, static and non-static member functions and classes -with \f(CW\*(C`operator ()\*(C'\fR can be used as callbacks. Other types should be easy -to add as long as they only need one additional pointer for context. If -you need support for other types of functors please contact the author -(preferably after implementing it). -.PP -For all this to work, your \*(C+ compiler either has to use the same calling -conventions as your C compiler (for static member functions), or you have -to embed libev and compile libev itself as \*(C+. -.PP -Here is a list of things available in the \f(CW\*(C`ev\*(C'\fR namespace: -.ie n .IP """ev::READ"", ""ev::WRITE"" etc." 4 -.el .IP "\f(CWev::READ\fR, \f(CWev::WRITE\fR etc." 4 -.IX Item "ev::READ, ev::WRITE etc." -These are just enum values with the same values as the \f(CW\*(C`EV_READ\*(C'\fR etc. -macros from \fIev.h\fR. -.ie n .IP """ev::tstamp"", ""ev::now""" 4 -.el .IP "\f(CWev::tstamp\fR, \f(CWev::now\fR" 4 -.IX Item "ev::tstamp, ev::now" -Aliases to the same types/functions as with the \f(CW\*(C`ev_\*(C'\fR prefix. -.ie n .IP """ev::io"", ""ev::timer"", ""ev::periodic"", ""ev::idle"", ""ev::sig"" etc." 4 -.el .IP "\f(CWev::io\fR, \f(CWev::timer\fR, \f(CWev::periodic\fR, \f(CWev::idle\fR, \f(CWev::sig\fR etc." 4 -.IX Item "ev::io, ev::timer, ev::periodic, ev::idle, ev::sig etc." -For each \f(CW\*(C`ev_TYPE\*(C'\fR watcher in \fIev.h\fR there is a corresponding class of -the same name in the \f(CW\*(C`ev\*(C'\fR namespace, with the exception of \f(CW\*(C`ev_signal\*(C'\fR -which is called \f(CW\*(C`ev::sig\*(C'\fR to avoid clashes with the \f(CW\*(C`signal\*(C'\fR macro -defined by many implementations. -.Sp -All of those classes have these methods: -.RS 4 -.IP "ev::TYPE::TYPE ()" 4 -.IX Item "ev::TYPE::TYPE ()" -.PD 0 -.IP "ev::TYPE::TYPE (loop)" 4 -.IX Item "ev::TYPE::TYPE (loop)" -.IP "ev::TYPE::~TYPE" 4 -.IX Item "ev::TYPE::~TYPE" -.PD -The constructor (optionally) takes an event loop to associate the watcher -with. If it is omitted, it will use \f(CW\*(C`EV_DEFAULT\*(C'\fR. -.Sp -The constructor calls \f(CW\*(C`ev_init\*(C'\fR for you, which means you have to call the -\&\f(CW\*(C`set\*(C'\fR method before starting it. -.Sp -It will not set a callback, however: You have to call the templated \f(CW\*(C`set\*(C'\fR -method to set a callback before you can start the watcher. -.Sp -(The reason why you have to use a method is a limitation in \*(C+ which does -not allow explicit template arguments for constructors). -.Sp -The destructor automatically stops the watcher if it is active. -.IP "w\->set (object *)" 4 -.IX Item "w->set (object *)" -This method sets the callback method to call. The method has to have a -signature of \f(CW\*(C`void (*)(ev_TYPE &, int)\*(C'\fR, it receives the watcher as -first argument and the \f(CW\*(C`revents\*(C'\fR as second. The object must be given as -parameter and is stored in the \f(CW\*(C`data\*(C'\fR member of the watcher. -.Sp -This method synthesizes efficient thunking code to call your method from -the C callback that libev requires. If your compiler can inline your -callback (i.e. it is visible to it at the place of the \f(CW\*(C`set\*(C'\fR call and -your compiler is good :), then the method will be fully inlined into the -thunking function, making it as fast as a direct C callback. -.Sp -Example: simple class declaration and watcher initialisation -.Sp -.Vb 4 -\& struct myclass -\& { -\& void io_cb (ev::io &w, int revents) { } -\& } -\& -\& myclass obj; -\& ev::io iow; -\& iow.set (&obj); -.Ve -.IP "w\->set (object *)" 4 -.IX Item "w->set (object *)" -This is a variation of a method callback \- leaving out the method to call -will default the method to \f(CW\*(C`operator ()\*(C'\fR, which makes it possible to use -functor objects without having to manually specify the \f(CW\*(C`operator ()\*(C'\fR all -the time. Incidentally, you can then also leave out the template argument -list. -.Sp -The \f(CW\*(C`operator ()\*(C'\fR method prototype must be \f(CW\*(C`void operator ()(watcher &w, -int revents)\*(C'\fR. -.Sp -See the method\-\f(CW\*(C`set\*(C'\fR above for more details. -.Sp -Example: use a functor object as callback. -.Sp -.Vb 7 -\& struct myfunctor -\& { -\& void operator() (ev::io &w, int revents) -\& { -\& ... -\& } -\& } -\& -\& myfunctor f; -\& -\& ev::io w; -\& w.set (&f); -.Ve -.IP "w\->set (void *data = 0)" 4 -.IX Item "w->set (void *data = 0)" -Also sets a callback, but uses a static method or plain function as -callback. The optional \f(CW\*(C`data\*(C'\fR argument will be stored in the watcher's -\&\f(CW\*(C`data\*(C'\fR member and is free for you to use. -.Sp -The prototype of the \f(CW\*(C`function\*(C'\fR must be \f(CW\*(C`void (*)(ev::TYPE &w, int)\*(C'\fR. -.Sp -See the method\-\f(CW\*(C`set\*(C'\fR above for more details. -.Sp -Example: Use a plain function as callback. -.Sp -.Vb 2 -\& static void io_cb (ev::io &w, int revents) { } -\& iow.set (); -.Ve -.IP "w\->set (loop)" 4 -.IX Item "w->set (loop)" -Associates a different \f(CW\*(C`struct ev_loop\*(C'\fR with this watcher. You can only -do this when the watcher is inactive (and not pending either). -.IP "w\->set ([arguments])" 4 -.IX Item "w->set ([arguments])" -Basically the same as \f(CW\*(C`ev_TYPE_set\*(C'\fR (except for \f(CW\*(C`ev::embed\*(C'\fR watchers>), -with the same arguments. Either this method or a suitable start method -must be called at least once. Unlike the C counterpart, an active watcher -gets automatically stopped and restarted when reconfiguring it with this -method. -.Sp -For \f(CW\*(C`ev::embed\*(C'\fR watchers this method is called \f(CW\*(C`set_embed\*(C'\fR, to avoid -clashing with the \f(CW\*(C`set (loop)\*(C'\fR method. -.IP "w\->start ()" 4 -.IX Item "w->start ()" -Starts the watcher. Note that there is no \f(CW\*(C`loop\*(C'\fR argument, as the -constructor already stores the event loop. -.IP "w\->start ([arguments])" 4 -.IX Item "w->start ([arguments])" -Instead of calling \f(CW\*(C`set\*(C'\fR and \f(CW\*(C`start\*(C'\fR methods separately, it is often -convenient to wrap them in one call. Uses the same type of arguments as -the configure \f(CW\*(C`set\*(C'\fR method of the watcher. -.IP "w\->stop ()" 4 -.IX Item "w->stop ()" -Stops the watcher if it is active. Again, no \f(CW\*(C`loop\*(C'\fR argument. -.ie n .IP "w\->again () (""ev::timer"", ""ev::periodic"" only)" 4 -.el .IP "w\->again () (\f(CWev::timer\fR, \f(CWev::periodic\fR only)" 4 -.IX Item "w->again () (ev::timer, ev::periodic only)" -For \f(CW\*(C`ev::timer\*(C'\fR and \f(CW\*(C`ev::periodic\*(C'\fR, this invokes the corresponding -\&\f(CW\*(C`ev_TYPE_again\*(C'\fR function. -.ie n .IP "w\->sweep () (""ev::embed"" only)" 4 -.el .IP "w\->sweep () (\f(CWev::embed\fR only)" 4 -.IX Item "w->sweep () (ev::embed only)" -Invokes \f(CW\*(C`ev_embed_sweep\*(C'\fR. -.ie n .IP "w\->update () (""ev::stat"" only)" 4 -.el .IP "w\->update () (\f(CWev::stat\fR only)" 4 -.IX Item "w->update () (ev::stat only)" -Invokes \f(CW\*(C`ev_stat_stat\*(C'\fR. -.RE -.RS 4 -.RE -.PP -Example: Define a class with two I/O and idle watchers, start the I/O -watchers in the constructor. -.PP -.Vb 5 -\& class myclass -\& { -\& ev::io io ; void io_cb (ev::io &w, int revents); -\& ev::io io2 ; void io2_cb (ev::io &w, int revents); -\& ev::idle idle; void idle_cb (ev::idle &w, int revents); -\& -\& myclass (int fd) -\& { -\& io .set (this); -\& io2 .set (this); -\& idle.set (this); -\& -\& io.set (fd, ev::WRITE); // configure the watcher -\& io.start (); // start it whenever convenient -\& -\& io2.start (fd, ev::READ); // set + start in one call -\& } -\& }; -.Ve -.SH "OTHER LANGUAGE BINDINGS" -.IX Header "OTHER LANGUAGE BINDINGS" -Libev does not offer other language bindings itself, but bindings for a -number of languages exist in the form of third-party packages. If you know -any interesting language binding in addition to the ones listed here, drop -me a note. -.IP "Perl" 4 -.IX Item "Perl" -The \s-1EV\s0 module implements the full libev \s-1API\s0 and is actually used to test -libev. \s-1EV\s0 is developed together with libev. Apart from the \s-1EV\s0 core module, -there are additional modules that implement libev-compatible interfaces -to \f(CW\*(C`libadns\*(C'\fR (\f(CW\*(C`EV::ADNS\*(C'\fR, but \f(CW\*(C`AnyEvent::DNS\*(C'\fR is preferred nowadays), -\&\f(CW\*(C`Net::SNMP\*(C'\fR (\f(CW\*(C`Net::SNMP::EV\*(C'\fR) and the \f(CW\*(C`libglib\*(C'\fR event core (\f(CW\*(C`Glib::EV\*(C'\fR -and \f(CW\*(C`EV::Glib\*(C'\fR). -.Sp -It can be found and installed via \s-1CPAN\s0, its homepage is at -. -.IP "Python" 4 -.IX Item "Python" -Python bindings can be found at . It -seems to be quite complete and well-documented. -.IP "Ruby" 4 -.IX Item "Ruby" -Tony Arcieri has written a ruby extension that offers access to a subset -of the libev \s-1API\s0 and adds file handle abstractions, asynchronous \s-1DNS\s0 and -more on top of it. It can be found via gem servers. Its homepage is at -. -.Sp -Roger Pack reports that using the link order \f(CW\*(C`\-lws2_32 \-lmsvcrt\-ruby\-190\*(C'\fR -makes rev work even on mingw. -.IP "Haskell" 4 -.IX Item "Haskell" -A haskell binding to libev is available at -http://hackage.haskell.org/cgi\-bin/hackage\-scripts/package/hlibev . -.IP "D" 4 -.IX Item "D" -Leandro Lucarella has written a D language binding (\fIev.d\fR) for libev, to -be found at . -.IP "Ocaml" 4 -.IX Item "Ocaml" -Erkki Seppala has written Ocaml bindings for libev, to be found at -http://modeemi.cs.tut.fi/~flux/software/ocaml\-ev/ . -.IP "Lua" 4 -.IX Item "Lua" -Brian Maher has written a partial interface to libev for lua (at the -time of this writing, only \f(CW\*(C`ev_io\*(C'\fR and \f(CW\*(C`ev_timer\*(C'\fR), to be found at -http://github.com/brimworks/lua\-ev . -.IP "Javascript" 4 -.IX Item "Javascript" -Node.js () uses libev as the underlying event library. -.IP "Others" 4 -.IX Item "Others" -There are others, and I stopped counting. -.SH "MACRO MAGIC" -.IX Header "MACRO MAGIC" -Libev can be compiled with a variety of options, the most fundamental -of which is \f(CW\*(C`EV_MULTIPLICITY\*(C'\fR. This option determines whether (most) -functions and callbacks have an initial \f(CW\*(C`struct ev_loop *\*(C'\fR argument. -.PP -To make it easier to write programs that cope with either variant, the -following macros are defined: -.ie n .IP """EV_A"", ""EV_A_""" 4 -.el .IP "\f(CWEV_A\fR, \f(CWEV_A_\fR" 4 -.IX Item "EV_A, EV_A_" -This provides the loop \fIargument\fR for functions, if one is required (\*(L"ev -loop argument\*(R"). The \f(CW\*(C`EV_A\*(C'\fR form is used when this is the sole argument, -\&\f(CW\*(C`EV_A_\*(C'\fR is used when other arguments are following. Example: -.Sp -.Vb 3 -\& ev_unref (EV_A); -\& ev_timer_add (EV_A_ watcher); -\& ev_run (EV_A_ 0); -.Ve -.Sp -It assumes the variable \f(CW\*(C`loop\*(C'\fR of type \f(CW\*(C`struct ev_loop *\*(C'\fR is in scope, -which is often provided by the following macro. -.ie n .IP """EV_P"", ""EV_P_""" 4 -.el .IP "\f(CWEV_P\fR, \f(CWEV_P_\fR" 4 -.IX Item "EV_P, EV_P_" -This provides the loop \fIparameter\fR for functions, if one is required (\*(L"ev -loop parameter\*(R"). The \f(CW\*(C`EV_P\*(C'\fR form is used when this is the sole parameter, -\&\f(CW\*(C`EV_P_\*(C'\fR is used when other parameters are following. Example: -.Sp -.Vb 2 -\& // this is how ev_unref is being declared -\& static void ev_unref (EV_P); -\& -\& // this is how you can declare your typical callback -\& static void cb (EV_P_ ev_timer *w, int revents) -.Ve -.Sp -It declares a parameter \f(CW\*(C`loop\*(C'\fR of type \f(CW\*(C`struct ev_loop *\*(C'\fR, quite -suitable for use with \f(CW\*(C`EV_A\*(C'\fR. -.ie n .IP """EV_DEFAULT"", ""EV_DEFAULT_""" 4 -.el .IP "\f(CWEV_DEFAULT\fR, \f(CWEV_DEFAULT_\fR" 4 -.IX Item "EV_DEFAULT, EV_DEFAULT_" -Similar to the other two macros, this gives you the value of the default -loop, if multiple loops are supported (\*(L"ev loop default\*(R"). The default loop -will be initialised if it isn't already initialised. -.Sp -For non-multiplicity builds, these macros do nothing, so you always have -to initialise the loop somewhere. -.ie n .IP """EV_DEFAULT_UC"", ""EV_DEFAULT_UC_""" 4 -.el .IP "\f(CWEV_DEFAULT_UC\fR, \f(CWEV_DEFAULT_UC_\fR" 4 -.IX Item "EV_DEFAULT_UC, EV_DEFAULT_UC_" -Usage identical to \f(CW\*(C`EV_DEFAULT\*(C'\fR and \f(CW\*(C`EV_DEFAULT_\*(C'\fR, but requires that the -default loop has been initialised (\f(CW\*(C`UC\*(C'\fR == unchecked). Their behaviour -is undefined when the default loop has not been initialised by a previous -execution of \f(CW\*(C`EV_DEFAULT\*(C'\fR, \f(CW\*(C`EV_DEFAULT_\*(C'\fR or \f(CW\*(C`ev_default_init (...)\*(C'\fR. -.Sp -It is often prudent to use \f(CW\*(C`EV_DEFAULT\*(C'\fR when initialising the first -watcher in a function but use \f(CW\*(C`EV_DEFAULT_UC\*(C'\fR afterwards. -.PP -Example: Declare and initialise a check watcher, utilising the above -macros so it will work regardless of whether multiple loops are supported -or not. -.PP -.Vb 5 -\& static void -\& check_cb (EV_P_ ev_timer *w, int revents) -\& { -\& ev_check_stop (EV_A_ w); -\& } -\& -\& ev_check check; -\& ev_check_init (&check, check_cb); -\& ev_check_start (EV_DEFAULT_ &check); -\& ev_run (EV_DEFAULT_ 0); -.Ve -.SH "EMBEDDING" -.IX Header "EMBEDDING" -Libev can (and often is) directly embedded into host -applications. Examples of applications that embed it include the Deliantra -Game Server, the \s-1EV\s0 perl module, the \s-1GNU\s0 Virtual Private Ethernet (gvpe) -and rxvt-unicode. -.PP -The goal is to enable you to just copy the necessary files into your -source directory without having to change even a single line in them, so -you can easily upgrade by simply copying (or having a checked-out copy of -libev somewhere in your source tree). -.SS "\s-1FILESETS\s0" -.IX Subsection "FILESETS" -Depending on what features you need you need to include one or more sets of files -in your application. -.PP -\fI\s-1CORE\s0 \s-1EVENT\s0 \s-1LOOP\s0\fR -.IX Subsection "CORE EVENT LOOP" -.PP -To include only the libev core (all the \f(CW\*(C`ev_*\*(C'\fR functions), with manual -configuration (no autoconf): -.PP -.Vb 2 -\& #define EV_STANDALONE 1 -\& #include "ev.c" -.Ve -.PP -This will automatically include \fIev.h\fR, too, and should be done in a -single C source file only to provide the function implementations. To use -it, do the same for \fIev.h\fR in all files wishing to use this \s-1API\s0 (best -done by writing a wrapper around \fIev.h\fR that you can include instead and -where you can put other configuration options): -.PP -.Vb 2 -\& #define EV_STANDALONE 1 -\& #include "ev.h" -.Ve -.PP -Both header files and implementation files can be compiled with a \*(C+ -compiler (at least, that's a stated goal, and breakage will be treated -as a bug). -.PP -You need the following files in your source tree, or in a directory -in your include path (e.g. in libev/ when using \-Ilibev): -.PP -.Vb 4 -\& ev.h -\& ev.c -\& ev_vars.h -\& ev_wrap.h -\& -\& ev_win32.c required on win32 platforms only -\& -\& ev_select.c only when select backend is enabled (which is enabled by default) -\& ev_poll.c only when poll backend is enabled (disabled by default) -\& ev_epoll.c only when the epoll backend is enabled (disabled by default) -\& ev_kqueue.c only when the kqueue backend is enabled (disabled by default) -\& ev_port.c only when the solaris port backend is enabled (disabled by default) -.Ve -.PP -\&\fIev.c\fR includes the backend files directly when enabled, so you only need -to compile this single file. -.PP -\fI\s-1LIBEVENT\s0 \s-1COMPATIBILITY\s0 \s-1API\s0\fR -.IX Subsection "LIBEVENT COMPATIBILITY API" -.PP -To include the libevent compatibility \s-1API\s0, also include: -.PP -.Vb 1 -\& #include "event.c" -.Ve -.PP -in the file including \fIev.c\fR, and: -.PP -.Vb 1 -\& #include "event.h" -.Ve -.PP -in the files that want to use the libevent \s-1API\s0. This also includes \fIev.h\fR. -.PP -You need the following additional files for this: -.PP -.Vb 2 -\& event.h -\& event.c -.Ve -.PP -\fI\s-1AUTOCONF\s0 \s-1SUPPORT\s0\fR -.IX Subsection "AUTOCONF SUPPORT" -.PP -Instead of using \f(CW\*(C`EV_STANDALONE=1\*(C'\fR and providing your configuration in -whatever way you want, you can also \f(CW\*(C`m4_include([libev.m4])\*(C'\fR in your -\&\fIconfigure.ac\fR and leave \f(CW\*(C`EV_STANDALONE\*(C'\fR undefined. \fIev.c\fR will then -include \fIconfig.h\fR and configure itself accordingly. -.PP -For this of course you need the m4 file: -.PP -.Vb 1 -\& libev.m4 -.Ve -.SS "\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0" -.IX Subsection "PREPROCESSOR SYMBOLS/MACROS" -Libev can be configured via a variety of preprocessor symbols you have to -define before including (or compiling) any of its files. The default in -the absence of autoconf is documented for every option. -.PP -Symbols marked with \*(L"(h)\*(R" do not change the \s-1ABI\s0, and can have different -values when compiling libev vs. including \fIev.h\fR, so it is permissible -to redefine them before including \fIev.h\fR without breaking compatibility -to a compiled library. All other symbols change the \s-1ABI\s0, which means all -users of libev and the libev code itself must be compiled with compatible -settings. -.IP "\s-1EV_COMPAT3\s0 (h)" 4 -.IX Item "EV_COMPAT3 (h)" -Backwards compatibility is a major concern for libev. This is why this -release of libev comes with wrappers for the functions and symbols that -have been renamed between libev version 3 and 4. -.Sp -You can disable these wrappers (to test compatibility with future -versions) by defining \f(CW\*(C`EV_COMPAT3\*(C'\fR to \f(CW0\fR when compiling your -sources. This has the additional advantage that you can drop the \f(CW\*(C`struct\*(C'\fR -from \f(CW\*(C`struct ev_loop\*(C'\fR declarations, as libev will provide an \f(CW\*(C`ev_loop\*(C'\fR -typedef in that case. -.Sp -In some future version, the default for \f(CW\*(C`EV_COMPAT3\*(C'\fR will become \f(CW0\fR, -and in some even more future version the compatibility code will be -removed completely. -.IP "\s-1EV_STANDALONE\s0 (h)" 4 -.IX Item "EV_STANDALONE (h)" -Must always be \f(CW1\fR if you do not use autoconf configuration, which -keeps libev from including \fIconfig.h\fR, and it also defines dummy -implementations for some libevent functions (such as logging, which is not -supported). It will also not define any of the structs usually found in -\&\fIevent.h\fR that are not directly supported by the libev core alone. -.Sp -In standalone mode, libev will still try to automatically deduce the -configuration, but has to be more conservative. -.IP "\s-1EV_USE_FLOOR\s0" 4 -.IX Item "EV_USE_FLOOR" -If defined to be \f(CW1\fR, libev will use the \f(CW\*(C`floor ()\*(C'\fR function for its -periodic reschedule calculations, otherwise libev will fall back on a -portable (slower) implementation. If you enable this, you usually have to -link against libm or something equivalent. Enabling this when the \f(CW\*(C`floor\*(C'\fR -function is not available will fail, so the safe default is to not enable -this. -.IP "\s-1EV_USE_MONOTONIC\s0" 4 -.IX Item "EV_USE_MONOTONIC" -If defined to be \f(CW1\fR, libev will try to detect the availability of the -monotonic clock option at both compile time and runtime. Otherwise no -use of the monotonic clock option will be attempted. If you enable this, -you usually have to link against librt or something similar. Enabling it -when the functionality isn't available is safe, though, although you have -to make sure you link against any libraries where the \f(CW\*(C`clock_gettime\*(C'\fR -function is hiding in (often \fI\-lrt\fR). See also \f(CW\*(C`EV_USE_CLOCK_SYSCALL\*(C'\fR. -.IP "\s-1EV_USE_REALTIME\s0" 4 -.IX Item "EV_USE_REALTIME" -If defined to be \f(CW1\fR, libev will try to detect the availability of the -real-time clock option at compile time (and assume its availability -at runtime if successful). Otherwise no use of the real-time clock -option will be attempted. This effectively replaces \f(CW\*(C`gettimeofday\*(C'\fR -by \f(CW\*(C`clock_get (CLOCK_REALTIME, ...)\*(C'\fR and will not normally affect -correctness. See the note about libraries in the description of -\&\f(CW\*(C`EV_USE_MONOTONIC\*(C'\fR, though. Defaults to the opposite value of -\&\f(CW\*(C`EV_USE_CLOCK_SYSCALL\*(C'\fR. -.IP "\s-1EV_USE_CLOCK_SYSCALL\s0" 4 -.IX Item "EV_USE_CLOCK_SYSCALL" -If defined to be \f(CW1\fR, libev will try to use a direct syscall instead -of calling the system-provided \f(CW\*(C`clock_gettime\*(C'\fR function. This option -exists because on GNU/Linux, \f(CW\*(C`clock_gettime\*(C'\fR is in \f(CW\*(C`librt\*(C'\fR, but \f(CW\*(C`librt\*(C'\fR -unconditionally pulls in \f(CW\*(C`libpthread\*(C'\fR, slowing down single-threaded -programs needlessly. Using a direct syscall is slightly slower (in -theory), because no optimised vdso implementation can be used, but avoids -the pthread dependency. Defaults to \f(CW1\fR on GNU/Linux with glibc 2.x or -higher, as it simplifies linking (no need for \f(CW\*(C`\-lrt\*(C'\fR). -.IP "\s-1EV_USE_NANOSLEEP\s0" 4 -.IX Item "EV_USE_NANOSLEEP" -If defined to be \f(CW1\fR, libev will assume that \f(CW\*(C`nanosleep ()\*(C'\fR is available -and will use it for delays. Otherwise it will use \f(CW\*(C`select ()\*(C'\fR. -.IP "\s-1EV_USE_EVENTFD\s0" 4 -.IX Item "EV_USE_EVENTFD" -If defined to be \f(CW1\fR, then libev will assume that \f(CW\*(C`eventfd ()\*(C'\fR is -available and will probe for kernel support at runtime. This will improve -\&\f(CW\*(C`ev_signal\*(C'\fR and \f(CW\*(C`ev_async\*(C'\fR performance and reduce resource consumption. -If undefined, it will be enabled if the headers indicate GNU/Linux + Glibc -2.7 or newer, otherwise disabled. -.IP "\s-1EV_USE_SELECT\s0" 4 -.IX Item "EV_USE_SELECT" -If undefined or defined to be \f(CW1\fR, libev will compile in support for the -\&\f(CW\*(C`select\*(C'\fR(2) backend. No attempt at auto-detection will be done: if no -other method takes over, select will be it. Otherwise the select backend -will not be compiled in. -.IP "\s-1EV_SELECT_USE_FD_SET\s0" 4 -.IX Item "EV_SELECT_USE_FD_SET" -If defined to \f(CW1\fR, then the select backend will use the system \f(CW\*(C`fd_set\*(C'\fR -structure. This is useful if libev doesn't compile due to a missing -\&\f(CW\*(C`NFDBITS\*(C'\fR or \f(CW\*(C`fd_mask\*(C'\fR definition or it mis-guesses the bitset layout -on exotic systems. This usually limits the range of file descriptors to -some low limit such as 1024 or might have other limitations (winsocket -only allows 64 sockets). The \f(CW\*(C`FD_SETSIZE\*(C'\fR macro, set before compilation, -configures the maximum size of the \f(CW\*(C`fd_set\*(C'\fR. -.IP "\s-1EV_SELECT_IS_WINSOCKET\s0" 4 -.IX Item "EV_SELECT_IS_WINSOCKET" -When defined to \f(CW1\fR, the select backend will assume that -select/socket/connect etc. don't understand file descriptors but -wants osf handles on win32 (this is the case when the select to -be used is the winsock select). This means that it will call -\&\f(CW\*(C`_get_osfhandle\*(C'\fR on the fd to convert it to an \s-1OS\s0 handle. Otherwise, -it is assumed that all these functions actually work on fds, even -on win32. Should not be defined on non\-win32 platforms. -.IP "\s-1EV_FD_TO_WIN32_HANDLE\s0(fd)" 4 -.IX Item "EV_FD_TO_WIN32_HANDLE(fd)" -If \f(CW\*(C`EV_SELECT_IS_WINSOCKET\*(C'\fR is enabled, then libev needs a way to map -file descriptors to socket handles. When not defining this symbol (the -default), then libev will call \f(CW\*(C`_get_osfhandle\*(C'\fR, which is usually -correct. In some cases, programs use their own file descriptor management, -in which case they can provide this function to map fds to socket handles. -.IP "\s-1EV_WIN32_HANDLE_TO_FD\s0(handle)" 4 -.IX Item "EV_WIN32_HANDLE_TO_FD(handle)" -If \f(CW\*(C`EV_SELECT_IS_WINSOCKET\*(C'\fR then libev maps handles to file descriptors -using the standard \f(CW\*(C`_open_osfhandle\*(C'\fR function. For programs implementing -their own fd to handle mapping, overwriting this function makes it easier -to do so. This can be done by defining this macro to an appropriate value. -.IP "\s-1EV_WIN32_CLOSE_FD\s0(fd)" 4 -.IX Item "EV_WIN32_CLOSE_FD(fd)" -If programs implement their own fd to handle mapping on win32, then this -macro can be used to override the \f(CW\*(C`close\*(C'\fR function, useful to unregister -file descriptors again. Note that the replacement function has to close -the underlying \s-1OS\s0 handle. -.IP "\s-1EV_USE_WSASOCKET\s0" 4 -.IX Item "EV_USE_WSASOCKET" -If defined to be \f(CW1\fR, libev will use \f(CW\*(C`WSASocket\*(C'\fR to create its internal -communication socket, which works better in some environments. Otherwise, -the normal \f(CW\*(C`socket\*(C'\fR function will be used, which works better in other -environments. -.IP "\s-1EV_USE_POLL\s0" 4 -.IX Item "EV_USE_POLL" -If defined to be \f(CW1\fR, libev will compile in support for the \f(CW\*(C`poll\*(C'\fR(2) -backend. Otherwise it will be enabled on non\-win32 platforms. It -takes precedence over select. -.IP "\s-1EV_USE_EPOLL\s0" 4 -.IX Item "EV_USE_EPOLL" -If defined to be \f(CW1\fR, libev will compile in support for the Linux -\&\f(CW\*(C`epoll\*(C'\fR(7) backend. Its availability will be detected at runtime, -otherwise another method will be used as fallback. This is the preferred -backend for GNU/Linux systems. If undefined, it will be enabled if the -headers indicate GNU/Linux + Glibc 2.4 or newer, otherwise disabled. -.IP "\s-1EV_USE_KQUEUE\s0" 4 -.IX Item "EV_USE_KQUEUE" -If defined to be \f(CW1\fR, libev will compile in support for the \s-1BSD\s0 style -\&\f(CW\*(C`kqueue\*(C'\fR(2) backend. Its actual availability will be detected at runtime, -otherwise another method will be used as fallback. This is the preferred -backend for \s-1BSD\s0 and BSD-like systems, although on most BSDs kqueue only -supports some types of fds correctly (the only platform we found that -supports ptys for example was NetBSD), so kqueue might be compiled in, but -not be used unless explicitly requested. The best way to use it is to find -out whether kqueue supports your type of fd properly and use an embedded -kqueue loop. -.IP "\s-1EV_USE_PORT\s0" 4 -.IX Item "EV_USE_PORT" -If defined to be \f(CW1\fR, libev will compile in support for the Solaris -10 port style backend. Its availability will be detected at runtime, -otherwise another method will be used as fallback. This is the preferred -backend for Solaris 10 systems. -.IP "\s-1EV_USE_DEVPOLL\s0" 4 -.IX Item "EV_USE_DEVPOLL" -Reserved for future expansion, works like the \s-1USE\s0 symbols above. -.IP "\s-1EV_USE_INOTIFY\s0" 4 -.IX Item "EV_USE_INOTIFY" -If defined to be \f(CW1\fR, libev will compile in support for the Linux inotify -interface to speed up \f(CW\*(C`ev_stat\*(C'\fR watchers. Its actual availability will -be detected at runtime. If undefined, it will be enabled if the headers -indicate GNU/Linux + Glibc 2.4 or newer, otherwise disabled. -.IP "\s-1EV_NO_SMP\s0" 4 -.IX Item "EV_NO_SMP" -If defined to be \f(CW1\fR, libev will assume that memory is always coherent -between threads, that is, threads can be used, but threads never run on -different cpus (or different cpu cores). This reduces dependencies -and makes libev faster. -.IP "\s-1EV_NO_THREADS\s0" 4 -.IX Item "EV_NO_THREADS" -If defined to be \f(CW1\fR, libev will assume that it will never be called from -different threads (that includes signal handlers), which is a stronger -assumption than \f(CW\*(C`EV_NO_SMP\*(C'\fR, above. This reduces dependencies and makes -libev faster. -.IP "\s-1EV_ATOMIC_T\s0" 4 -.IX Item "EV_ATOMIC_T" -Libev requires an integer type (suitable for storing \f(CW0\fR or \f(CW1\fR) whose -access is atomic with respect to other threads or signal contexts. No -such type is easily found in the C language, so you can provide your own -type that you know is safe for your purposes. It is used both for signal -handler \*(L"locking\*(R" as well as for signal and thread safety in \f(CW\*(C`ev_async\*(C'\fR -watchers. -.Sp -In the absence of this define, libev will use \f(CW\*(C`sig_atomic_t volatile\*(C'\fR -(from \fIsignal.h\fR), which is usually good enough on most platforms. -.IP "\s-1EV_H\s0 (h)" 4 -.IX Item "EV_H (h)" -The name of the \fIev.h\fR header file used to include it. The default if -undefined is \f(CW"ev.h"\fR in \fIevent.h\fR, \fIev.c\fR and \fIev++.h\fR. This can be -used to virtually rename the \fIev.h\fR header file in case of conflicts. -.IP "\s-1EV_CONFIG_H\s0 (h)" 4 -.IX Item "EV_CONFIG_H (h)" -If \f(CW\*(C`EV_STANDALONE\*(C'\fR isn't \f(CW1\fR, this variable can be used to override -\&\fIev.c\fR's idea of where to find the \fIconfig.h\fR file, similarly to -\&\f(CW\*(C`EV_H\*(C'\fR, above. -.IP "\s-1EV_EVENT_H\s0 (h)" 4 -.IX Item "EV_EVENT_H (h)" -Similarly to \f(CW\*(C`EV_H\*(C'\fR, this macro can be used to override \fIevent.c\fR's idea -of how the \fIevent.h\fR header can be found, the default is \f(CW"event.h"\fR. -.IP "\s-1EV_PROTOTYPES\s0 (h)" 4 -.IX Item "EV_PROTOTYPES (h)" -If defined to be \f(CW0\fR, then \fIev.h\fR will not define any function -prototypes, but still define all the structs and other symbols. This is -occasionally useful if you want to provide your own wrapper functions -around libev functions. -.IP "\s-1EV_MULTIPLICITY\s0" 4 -.IX Item "EV_MULTIPLICITY" -If undefined or defined to \f(CW1\fR, then all event-loop-specific functions -will have the \f(CW\*(C`struct ev_loop *\*(C'\fR as first argument, and you can create -additional independent event loops. Otherwise there will be no support -for multiple event loops and there is no first event loop pointer -argument. Instead, all functions act on the single default loop. -.Sp -Note that \f(CW\*(C`EV_DEFAULT\*(C'\fR and \f(CW\*(C`EV_DEFAULT_\*(C'\fR will no longer provide a -default loop when multiplicity is switched off \- you always have to -initialise the loop manually in this case. -.IP "\s-1EV_MINPRI\s0" 4 -.IX Item "EV_MINPRI" -.PD 0 -.IP "\s-1EV_MAXPRI\s0" 4 -.IX Item "EV_MAXPRI" -.PD -The range of allowed priorities. \f(CW\*(C`EV_MINPRI\*(C'\fR must be smaller or equal to -\&\f(CW\*(C`EV_MAXPRI\*(C'\fR, but otherwise there are no non-obvious limitations. You can -provide for more priorities by overriding those symbols (usually defined -to be \f(CW\*(C`\-2\*(C'\fR and \f(CW2\fR, respectively). -.Sp -When doing priority-based operations, libev usually has to linearly search -all the priorities, so having many of them (hundreds) uses a lot of space -and time, so using the defaults of five priorities (\-2 .. +2) is usually -fine. -.Sp -If your embedding application does not need any priorities, defining these -both to \f(CW0\fR will save some memory and \s-1CPU\s0. -.IP "\s-1EV_PERIODIC_ENABLE\s0, \s-1EV_IDLE_ENABLE\s0, \s-1EV_EMBED_ENABLE\s0, \s-1EV_STAT_ENABLE\s0, \s-1EV_PREPARE_ENABLE\s0, \s-1EV_CHECK_ENABLE\s0, \s-1EV_FORK_ENABLE\s0, \s-1EV_SIGNAL_ENABLE\s0, \s-1EV_ASYNC_ENABLE\s0, \s-1EV_CHILD_ENABLE\s0." 4 -.IX Item "EV_PERIODIC_ENABLE, EV_IDLE_ENABLE, EV_EMBED_ENABLE, EV_STAT_ENABLE, EV_PREPARE_ENABLE, EV_CHECK_ENABLE, EV_FORK_ENABLE, EV_SIGNAL_ENABLE, EV_ASYNC_ENABLE, EV_CHILD_ENABLE." -If undefined or defined to be \f(CW1\fR (and the platform supports it), then -the respective watcher type is supported. If defined to be \f(CW0\fR, then it -is not. Disabling watcher types mainly saves code size. -.IP "\s-1EV_FEATURES\s0" 4 -.IX Item "EV_FEATURES" -If you need to shave off some kilobytes of code at the expense of some -speed (but with the full \s-1API\s0), you can define this symbol to request -certain subsets of functionality. The default is to enable all features -that can be enabled on the platform. -.Sp -A typical way to use this symbol is to define it to \f(CW0\fR (or to a bitset -with some broad features you want) and then selectively re-enable -additional parts you want, for example if you want everything minimal, -but multiple event loop support, async and child watchers and the poll -backend, use this: -.Sp -.Vb 5 -\& #define EV_FEATURES 0 -\& #define EV_MULTIPLICITY 1 -\& #define EV_USE_POLL 1 -\& #define EV_CHILD_ENABLE 1 -\& #define EV_ASYNC_ENABLE 1 -.Ve -.Sp -The actual value is a bitset, it can be a combination of the following -values (by default, all of these are enabled): -.RS 4 -.ie n .IP "1 \- faster/larger code" 4 -.el .IP "\f(CW1\fR \- faster/larger code" 4 -.IX Item "1 - faster/larger code" -Use larger code to speed up some operations. -.Sp -Currently this is used to override some inlining decisions (enlarging the -code size by roughly 30% on amd64). -.Sp -When optimising for size, use of compiler flags such as \f(CW\*(C`\-Os\*(C'\fR with -gcc is recommended, as well as \f(CW\*(C`\-DNDEBUG\*(C'\fR, as libev contains a number of -assertions. -.Sp -The default is off when \f(CW\*(C`_\|_OPTIMIZE_SIZE_\|_\*(C'\fR is defined by your compiler -(e.g. gcc with \f(CW\*(C`\-Os\*(C'\fR). -.ie n .IP "2 \- faster/larger data structures" 4 -.el .IP "\f(CW2\fR \- faster/larger data structures" 4 -.IX Item "2 - faster/larger data structures" -Replaces the small 2\-heap for timer management by a faster 4\-heap, larger -hash table sizes and so on. This will usually further increase code size -and can additionally have an effect on the size of data structures at -runtime. -.Sp -The default is off when \f(CW\*(C`_\|_OPTIMIZE_SIZE_\|_\*(C'\fR is defined by your compiler -(e.g. gcc with \f(CW\*(C`\-Os\*(C'\fR). -.ie n .IP "4 \- full \s-1API\s0 configuration" 4 -.el .IP "\f(CW4\fR \- full \s-1API\s0 configuration" 4 -.IX Item "4 - full API configuration" -This enables priorities (sets \f(CW\*(C`EV_MAXPRI\*(C'\fR=2 and \f(CW\*(C`EV_MINPRI\*(C'\fR=\-2), and -enables multiplicity (\f(CW\*(C`EV_MULTIPLICITY\*(C'\fR=1). -.ie n .IP "8 \- full \s-1API\s0" 4 -.el .IP "\f(CW8\fR \- full \s-1API\s0" 4 -.IX Item "8 - full API" -This enables a lot of the \*(L"lesser used\*(R" \s-1API\s0 functions. See \f(CW\*(C`ev.h\*(C'\fR for -details on which parts of the \s-1API\s0 are still available without this -feature, and do not complain if this subset changes over time. -.ie n .IP "16 \- enable all optional watcher types" 4 -.el .IP "\f(CW16\fR \- enable all optional watcher types" 4 -.IX Item "16 - enable all optional watcher types" -Enables all optional watcher types. If you want to selectively enable -only some watcher types other than I/O and timers (e.g. prepare, -embed, async, child...) you can enable them manually by defining -\&\f(CW\*(C`EV_watchertype_ENABLE\*(C'\fR to \f(CW1\fR instead. -.ie n .IP "32 \- enable all backends" 4 -.el .IP "\f(CW32\fR \- enable all backends" 4 -.IX Item "32 - enable all backends" -This enables all backends \- without this feature, you need to enable at -least one backend manually (\f(CW\*(C`EV_USE_SELECT\*(C'\fR is a good choice). -.ie n .IP "64 \- enable OS-specific ""helper"" APIs" 4 -.el .IP "\f(CW64\fR \- enable OS-specific ``helper'' APIs" 4 -.IX Item "64 - enable OS-specific helper APIs" -Enable inotify, eventfd, signalfd and similar OS-specific helper APIs by -default. -.RE -.RS 4 -.Sp -Compiling with \f(CW\*(C`gcc \-Os \-DEV_STANDALONE \-DEV_USE_EPOLL=1 \-DEV_FEATURES=0\*(C'\fR -reduces the compiled size of libev from 24.7Kb code/2.8Kb data to 6.5Kb -code/0.3Kb data on my GNU/Linux amd64 system, while still giving you I/O -watchers, timers and monotonic clock support. -.Sp -With an intelligent-enough linker (gcc+binutils are intelligent enough -when you use \f(CW\*(C`\-Wl,\-\-gc\-sections \-ffunction\-sections\*(C'\fR) functions unused by -your program might be left out as well \- a binary starting a timer and an -I/O watcher then might come out at only 5Kb. -.RE -.IP "\s-1EV_API_STATIC\s0" 4 -.IX Item "EV_API_STATIC" -If this symbol is defined (by default it is not), then all identifiers -will have static linkage. This means that libev will not export any -identifiers, and you cannot link against libev anymore. This can be useful -when you embed libev, only want to use libev functions in a single file, -and do not want its identifiers to be visible. -.Sp -To use this, define \f(CW\*(C`EV_API_STATIC\*(C'\fR and include \fIev.c\fR in the file that -wants to use libev. -.Sp -This option only works when libev is compiled with a C compiler, as \*(C+ -doesn't support the required declaration syntax. -.IP "\s-1EV_AVOID_STDIO\s0" 4 -.IX Item "EV_AVOID_STDIO" -If this is set to \f(CW1\fR at compiletime, then libev will avoid using stdio -functions (printf, scanf, perror etc.). This will increase the code size -somewhat, but if your program doesn't otherwise depend on stdio and your -libc allows it, this avoids linking in the stdio library which is quite -big. -.Sp -Note that error messages might become less precise when this option is -enabled. -.IP "\s-1EV_NSIG\s0" 4 -.IX Item "EV_NSIG" -The highest supported signal number, +1 (or, the number of -signals): Normally, libev tries to deduce the maximum number of signals -automatically, but sometimes this fails, in which case it can be -specified. Also, using a lower number than detected (\f(CW32\fR should be -good for about any system in existence) can save some memory, as libev -statically allocates some 12\-24 bytes per signal number. -.IP "\s-1EV_PID_HASHSIZE\s0" 4 -.IX Item "EV_PID_HASHSIZE" -\&\f(CW\*(C`ev_child\*(C'\fR watchers use a small hash table to distribute workload by -pid. The default size is \f(CW16\fR (or \f(CW1\fR with \f(CW\*(C`EV_FEATURES\*(C'\fR disabled), -usually more than enough. If you need to manage thousands of children you -might want to increase this value (\fImust\fR be a power of two). -.IP "\s-1EV_INOTIFY_HASHSIZE\s0" 4 -.IX Item "EV_INOTIFY_HASHSIZE" -\&\f(CW\*(C`ev_stat\*(C'\fR watchers use a small hash table to distribute workload by -inotify watch id. The default size is \f(CW16\fR (or \f(CW1\fR with \f(CW\*(C`EV_FEATURES\*(C'\fR -disabled), usually more than enough. If you need to manage thousands of -\&\f(CW\*(C`ev_stat\*(C'\fR watchers you might want to increase this value (\fImust\fR be a -power of two). -.IP "\s-1EV_USE_4HEAP\s0" 4 -.IX Item "EV_USE_4HEAP" -Heaps are not very cache-efficient. To improve the cache-efficiency of the -timer and periodics heaps, libev uses a 4\-heap when this symbol is defined -to \f(CW1\fR. The 4\-heap uses more complicated (longer) code but has noticeably -faster performance with many (thousands) of watchers. -.Sp -The default is \f(CW1\fR, unless \f(CW\*(C`EV_FEATURES\*(C'\fR overrides it, in which case it -will be \f(CW0\fR. -.IP "\s-1EV_HEAP_CACHE_AT\s0" 4 -.IX Item "EV_HEAP_CACHE_AT" -Heaps are not very cache-efficient. To improve the cache-efficiency of the -timer and periodics heaps, libev can cache the timestamp (\fIat\fR) within -the heap structure (selected by defining \f(CW\*(C`EV_HEAP_CACHE_AT\*(C'\fR to \f(CW1\fR), -which uses 8\-12 bytes more per watcher and a few hundred bytes more code, -but avoids random read accesses on heap changes. This improves performance -noticeably with many (hundreds) of watchers. -.Sp -The default is \f(CW1\fR, unless \f(CW\*(C`EV_FEATURES\*(C'\fR overrides it, in which case it -will be \f(CW0\fR. -.IP "\s-1EV_VERIFY\s0" 4 -.IX Item "EV_VERIFY" -Controls how much internal verification (see \f(CW\*(C`ev_verify ()\*(C'\fR) will -be done: If set to \f(CW0\fR, no internal verification code will be compiled -in. If set to \f(CW1\fR, then verification code will be compiled in, but not -called. If set to \f(CW2\fR, then the internal verification code will be -called once per loop, which can slow down libev. If set to \f(CW3\fR, then the -verification code will be called very frequently, which will slow down -libev considerably. -.Sp -The default is \f(CW1\fR, unless \f(CW\*(C`EV_FEATURES\*(C'\fR overrides it, in which case it -will be \f(CW0\fR. -.IP "\s-1EV_COMMON\s0" 4 -.IX Item "EV_COMMON" -By default, all watchers have a \f(CW\*(C`void *data\*(C'\fR member. By redefining -this macro to something else you can include more and other types of -members. You have to define it each time you include one of the files, -though, and it must be identical each time. -.Sp -For example, the perl \s-1EV\s0 module uses something like this: -.Sp -.Vb 3 -\& #define EV_COMMON \e -\& SV *self; /* contains this struct */ \e -\& SV *cb_sv, *fh /* note no trailing ";" */ -.Ve -.IP "\s-1EV_CB_DECLARE\s0 (type)" 4 -.IX Item "EV_CB_DECLARE (type)" -.PD 0 -.IP "\s-1EV_CB_INVOKE\s0 (watcher, revents)" 4 -.IX Item "EV_CB_INVOKE (watcher, revents)" -.IP "ev_set_cb (ev, cb)" 4 -.IX Item "ev_set_cb (ev, cb)" -.PD -Can be used to change the callback member declaration in each watcher, -and the way callbacks are invoked and set. Must expand to a struct member -definition and a statement, respectively. See the \fIev.h\fR header file for -their default definitions. One possible use for overriding these is to -avoid the \f(CW\*(C`struct ev_loop *\*(C'\fR as first argument in all cases, or to use -method calls instead of plain function calls in \*(C+. -.SS "\s-1EXPORTED\s0 \s-1API\s0 \s-1SYMBOLS\s0" -.IX Subsection "EXPORTED API SYMBOLS" -If you need to re-export the \s-1API\s0 (e.g. via a \s-1DLL\s0) and you need a list of -exported symbols, you can use the provided \fISymbol.*\fR files which list -all public symbols, one per line: -.PP -.Vb 2 -\& Symbols.ev for libev proper -\& Symbols.event for the libevent emulation -.Ve -.PP -This can also be used to rename all public symbols to avoid clashes with -multiple versions of libev linked together (which is obviously bad in -itself, but sometimes it is inconvenient to avoid this). -.PP -A sed command like this will create wrapper \f(CW\*(C`#define\*(C'\fR's that you need to -include before including \fIev.h\fR: -.PP -.Vb 1 -\& wrap.h -.Ve -.PP -This would create a file \fIwrap.h\fR which essentially looks like this: -.PP -.Vb 4 -\& #define ev_backend myprefix_ev_backend -\& #define ev_check_start myprefix_ev_check_start -\& #define ev_check_stop myprefix_ev_check_stop -\& ... -.Ve -.SS "\s-1EXAMPLES\s0" -.IX Subsection "EXAMPLES" -For a real-world example of a program the includes libev -verbatim, you can have a look at the \s-1EV\s0 perl module -(). It has the libev files in -the \fIlibev/\fR subdirectory and includes them in the \fI\s-1EV/EVAPI\s0.h\fR (public -interface) and \fI\s-1EV\s0.xs\fR (implementation) files. Only the \fI\s-1EV\s0.xs\fR file -will be compiled. It is pretty complex because it provides its own header -file. -.PP -The usage in rxvt-unicode is simpler. It has a \fIev_cpp.h\fR header file -that everybody includes and which overrides some configure choices: -.PP -.Vb 8 -\& #define EV_FEATURES 8 -\& #define EV_USE_SELECT 1 -\& #define EV_PREPARE_ENABLE 1 -\& #define EV_IDLE_ENABLE 1 -\& #define EV_SIGNAL_ENABLE 1 -\& #define EV_CHILD_ENABLE 1 -\& #define EV_USE_STDEXCEPT 0 -\& #define EV_CONFIG_H -\& -\& #include "ev++.h" -.Ve -.PP -And a \fIev_cpp.C\fR implementation file that contains libev proper and is compiled: -.PP -.Vb 2 -\& #include "ev_cpp.h" -\& #include "ev.c" -.Ve -.SH "INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT" -.IX Header "INTERACTION WITH OTHER PROGRAMS, LIBRARIES OR THE ENVIRONMENT" -.SS "\s-1THREADS\s0 \s-1AND\s0 \s-1COROUTINES\s0" -.IX Subsection "THREADS AND COROUTINES" -\fI\s-1THREADS\s0\fR -.IX Subsection "THREADS" -.PP -All libev functions are reentrant and thread-safe unless explicitly -documented otherwise, but libev implements no locking itself. This means -that you can use as many loops as you want in parallel, as long as there -are no concurrent calls into any libev function with the same loop -parameter (\f(CW\*(C`ev_default_*\*(C'\fR calls have an implicit default loop parameter, -of course): libev guarantees that different event loops share no data -structures that need any locking. -.PP -Or to put it differently: calls with different loop parameters can be done -concurrently from multiple threads, calls with the same loop parameter -must be done serially (but can be done from different threads, as long as -only one thread ever is inside a call at any point in time, e.g. by using -a mutex per loop). -.PP -Specifically to support threads (and signal handlers), libev implements -so-called \f(CW\*(C`ev_async\*(C'\fR watchers, which allow some limited form of -concurrency on the same event loop, namely waking it up \*(L"from the -outside\*(R". -.PP -If you want to know which design (one loop, locking, or multiple loops -without or something else still) is best for your problem, then I cannot -help you, but here is some generic advice: -.IP "\(bu" 4 -most applications have a main thread: use the default libev loop -in that thread, or create a separate thread running only the default loop. -.Sp -This helps integrating other libraries or software modules that use libev -themselves and don't care/know about threading. -.IP "\(bu" 4 -one loop per thread is usually a good model. -.Sp -Doing this is almost never wrong, sometimes a better-performance model -exists, but it is always a good start. -.IP "\(bu" 4 -other models exist, such as the leader/follower pattern, where one -loop is handed through multiple threads in a kind of round-robin fashion. -.Sp -Choosing a model is hard \- look around, learn, know that usually you can do -better than you currently do :\-) -.IP "\(bu" 4 -often you need to talk to some other thread which blocks in the -event loop. -.Sp -\&\f(CW\*(C`ev_async\*(C'\fR watchers can be used to wake them up from other threads safely -(or from signal contexts...). -.Sp -An example use would be to communicate signals or other events that only -work in the default loop by registering the signal watcher with the -default loop and triggering an \f(CW\*(C`ev_async\*(C'\fR watcher from the default loop -watcher callback into the event loop interested in the signal. -.PP -See also \*(L"\s-1THREAD\s0 \s-1LOCKING\s0 \s-1EXAMPLE\s0\*(R". -.PP -\fI\s-1COROUTINES\s0\fR -.IX Subsection "COROUTINES" -.PP -Libev is very accommodating to coroutines (\*(L"cooperative threads\*(R"): -libev fully supports nesting calls to its functions from different -coroutines (e.g. you can call \f(CW\*(C`ev_run\*(C'\fR on the same loop from two -different coroutines, and switch freely between both coroutines running -the loop, as long as you don't confuse yourself). The only exception is -that you must not do this from \f(CW\*(C`ev_periodic\*(C'\fR reschedule callbacks. -.PP -Care has been taken to ensure that libev does not keep local state inside -\&\f(CW\*(C`ev_run\*(C'\fR, and other calls do not usually allow for coroutine switches as -they do not call any callbacks. -.SS "\s-1COMPILER\s0 \s-1WARNINGS\s0" -.IX Subsection "COMPILER WARNINGS" -Depending on your compiler and compiler settings, you might get no or a -lot of warnings when compiling libev code. Some people are apparently -scared by this. -.PP -However, these are unavoidable for many reasons. For one, each compiler -has different warnings, and each user has different tastes regarding -warning options. \*(L"Warn-free\*(R" code therefore cannot be a goal except when -targeting a specific compiler and compiler-version. -.PP -Another reason is that some compiler warnings require elaborate -workarounds, or other changes to the code that make it less clear and less -maintainable. -.PP -And of course, some compiler warnings are just plain stupid, or simply -wrong (because they don't actually warn about the condition their message -seems to warn about). For example, certain older gcc versions had some -warnings that resulted in an extreme number of false positives. These have -been fixed, but some people still insist on making code warn-free with -such buggy versions. -.PP -While libev is written to generate as few warnings as possible, -\&\*(L"warn-free\*(R" code is not a goal, and it is recommended not to build libev -with any compiler warnings enabled unless you are prepared to cope with -them (e.g. by ignoring them). Remember that warnings are just that: -warnings, not errors, or proof of bugs. -.SS "\s-1VALGRIND\s0" -.IX Subsection "VALGRIND" -Valgrind has a special section here because it is a popular tool that is -highly useful. Unfortunately, valgrind reports are very hard to interpret. -.PP -If you think you found a bug (memory leak, uninitialised data access etc.) -in libev, then check twice: If valgrind reports something like: -.PP -.Vb 3 -\& ==2274== definitely lost: 0 bytes in 0 blocks. -\& ==2274== possibly lost: 0 bytes in 0 blocks. -\& ==2274== still reachable: 256 bytes in 1 blocks. -.Ve -.PP -Then there is no memory leak, just as memory accounted to global variables -is not a memleak \- the memory is still being referenced, and didn't leak. -.PP -Similarly, under some circumstances, valgrind might report kernel bugs -as if it were a bug in libev (e.g. in realloc or in the poll backend, -although an acceptable workaround has been found here), or it might be -confused. -.PP -Keep in mind that valgrind is a very good tool, but only a tool. Don't -make it into some kind of religion. -.PP -If you are unsure about something, feel free to contact the mailing list -with the full valgrind report and an explanation on why you think this -is a bug in libev (best check the archives, too :). However, don't be -annoyed when you get a brisk \*(L"this is no bug\*(R" answer and take the chance -of learning how to interpret valgrind properly. -.PP -If you need, for some reason, empty reports from valgrind for your project -I suggest using suppression lists. -.SH "PORTABILITY NOTES" -.IX Header "PORTABILITY NOTES" -.SS "\s-1GNU/LINUX\s0 32 \s-1BIT\s0 \s-1LIMITATIONS\s0" -.IX Subsection "GNU/LINUX 32 BIT LIMITATIONS" -GNU/Linux is the only common platform that supports 64 bit file/large file -interfaces but \fIdisables\fR them by default. -.PP -That means that libev compiled in the default environment doesn't support -files larger than 2GiB or so, which mainly affects \f(CW\*(C`ev_stat\*(C'\fR watchers. -.PP -Unfortunately, many programs try to work around this GNU/Linux issue -by enabling the large file \s-1API\s0, which makes them incompatible with the -standard libev compiled for their system. -.PP -Likewise, libev cannot enable the large file \s-1API\s0 itself as this would -suddenly make it incompatible to the default compile time environment, -i.e. all programs not using special compile switches. -.SS "\s-1OS/X\s0 \s-1AND\s0 \s-1DARWIN\s0 \s-1BUGS\s0" -.IX Subsection "OS/X AND DARWIN BUGS" -The whole thing is a bug if you ask me \- basically any system interface -you touch is broken, whether it is locales, poll, kqueue or even the -OpenGL drivers. -.PP -\fI\f(CI\*(C`kqueue\*(C'\fI is buggy\fR -.IX Subsection "kqueue is buggy" -.PP -The kqueue syscall is broken in all known versions \- most versions support -only sockets, many support pipes. -.PP -Libev tries to work around this by not using \f(CW\*(C`kqueue\*(C'\fR by default on this -rotten platform, but of course you can still ask for it when creating a -loop \- embedding a socket-only kqueue loop into a select-based one is -probably going to work well. -.PP -\fI\f(CI\*(C`poll\*(C'\fI is buggy\fR -.IX Subsection "poll is buggy" -.PP -Instead of fixing \f(CW\*(C`kqueue\*(C'\fR, Apple replaced their (working) \f(CW\*(C`poll\*(C'\fR -implementation by something calling \f(CW\*(C`kqueue\*(C'\fR internally around the 10.5.6 -release, so now \f(CW\*(C`kqueue\*(C'\fR \fIand\fR \f(CW\*(C`poll\*(C'\fR are broken. -.PP -Libev tries to work around this by not using \f(CW\*(C`poll\*(C'\fR by default on -this rotten platform, but of course you can still ask for it when creating -a loop. -.PP -\fI\f(CI\*(C`select\*(C'\fI is buggy\fR -.IX Subsection "select is buggy" -.PP -All that's left is \f(CW\*(C`select\*(C'\fR, and of course Apple found a way to fuck this -one up as well: On \s-1OS/X\s0, \f(CW\*(C`select\*(C'\fR actively limits the number of file -descriptors you can pass in to 1024 \- your program suddenly crashes when -you use more. -.PP -There is an undocumented \*(L"workaround\*(R" for this \- defining -\&\f(CW\*(C`_DARWIN_UNLIMITED_SELECT\*(C'\fR, which libev tries to use, so select \fIshould\fR -work on \s-1OS/X\s0. -.SS "\s-1SOLARIS\s0 \s-1PROBLEMS\s0 \s-1AND\s0 \s-1WORKAROUNDS\s0" -.IX Subsection "SOLARIS PROBLEMS AND WORKAROUNDS" -\fI\f(CI\*(C`errno\*(C'\fI reentrancy\fR -.IX Subsection "errno reentrancy" -.PP -The default compile environment on Solaris is unfortunately so -thread-unsafe that you can't even use components/libraries compiled -without \f(CW\*(C`\-D_REENTRANT\*(C'\fR in a threaded program, which, of course, isn't -defined by default. A valid, if stupid, implementation choice. -.PP -If you want to use libev in threaded environments you have to make sure -it's compiled with \f(CW\*(C`_REENTRANT\*(C'\fR defined. -.PP -\fIEvent port backend\fR -.IX Subsection "Event port backend" -.PP -The scalable event interface for Solaris is called \*(L"event -ports\*(R". Unfortunately, this mechanism is very buggy in all major -releases. If you run into high \s-1CPU\s0 usage, your program freezes or you get -a large number of spurious wakeups, make sure you have all the relevant -and latest kernel patches applied. No, I don't know which ones, but there -are multiple ones to apply, and afterwards, event ports actually work -great. -.PP -If you can't get it to work, you can try running the program by setting -the environment variable \f(CW\*(C`LIBEV_FLAGS=3\*(C'\fR to only allow \f(CW\*(C`poll\*(C'\fR and -\&\f(CW\*(C`select\*(C'\fR backends. -.SS "\s-1AIX\s0 \s-1POLL\s0 \s-1BUG\s0" -.IX Subsection "AIX POLL BUG" -\&\s-1AIX\s0 unfortunately has a broken \f(CW\*(C`poll.h\*(C'\fR header. Libev works around -this by trying to avoid the poll backend altogether (i.e. it's not even -compiled in), which normally isn't a big problem as \f(CW\*(C`select\*(C'\fR works fine -with large bitsets on \s-1AIX\s0, and \s-1AIX\s0 is dead anyway. -.SS "\s-1WIN32\s0 \s-1PLATFORM\s0 \s-1LIMITATIONS\s0 \s-1AND\s0 \s-1WORKAROUNDS\s0" -.IX Subsection "WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS" -\fIGeneral issues\fR -.IX Subsection "General issues" -.PP -Win32 doesn't support any of the standards (e.g. \s-1POSIX\s0) that libev -requires, and its I/O model is fundamentally incompatible with the \s-1POSIX\s0 -model. Libev still offers limited functionality on this platform in -the form of the \f(CW\*(C`EVBACKEND_SELECT\*(C'\fR backend, and only supports socket -descriptors. This only applies when using Win32 natively, not when using -e.g. cygwin. Actually, it only applies to the microsofts own compilers, -as every compiler comes with a slightly differently broken/incompatible -environment. -.PP -Lifting these limitations would basically require the full -re-implementation of the I/O system. If you are into this kind of thing, -then note that glib does exactly that for you in a very portable way (note -also that glib is the slowest event library known to man). -.PP -There is no supported compilation method available on windows except -embedding it into other applications. -.PP -Sensible signal handling is officially unsupported by Microsoft \- libev -tries its best, but under most conditions, signals will simply not work. -.PP -Not a libev limitation but worth mentioning: windows apparently doesn't -accept large writes: instead of resulting in a partial write, windows will -either accept everything or return \f(CW\*(C`ENOBUFS\*(C'\fR if the buffer is too large, -so make sure you only write small amounts into your sockets (less than a -megabyte seems safe, but this apparently depends on the amount of memory -available). -.PP -Due to the many, low, and arbitrary limits on the win32 platform and -the abysmal performance of winsockets, using a large number of sockets -is not recommended (and not reasonable). If your program needs to use -more than a hundred or so sockets, then likely it needs to use a totally -different implementation for windows, as libev offers the \s-1POSIX\s0 readiness -notification model, which cannot be implemented efficiently on windows -(due to Microsoft monopoly games). -.PP -A typical way to use libev under windows is to embed it (see the embedding -section for details) and use the following \fIevwrap.h\fR header file instead -of \fIev.h\fR: -.PP -.Vb 2 -\& #define EV_STANDALONE /* keeps ev from requiring config.h */ -\& #define EV_SELECT_IS_WINSOCKET 1 /* configure libev for windows select */ -\& -\& #include "ev.h" -.Ve -.PP -And compile the following \fIevwrap.c\fR file into your project (make sure -you do \fInot\fR compile the \fIev.c\fR or any other embedded source files!): -.PP -.Vb 2 -\& #include "evwrap.h" -\& #include "ev.c" -.Ve -.PP -\fIThe winsocket \f(CI\*(C`select\*(C'\fI function\fR -.IX Subsection "The winsocket select function" -.PP -The winsocket \f(CW\*(C`select\*(C'\fR function doesn't follow \s-1POSIX\s0 in that it -requires socket \fIhandles\fR and not socket \fIfile descriptors\fR (it is -also extremely buggy). This makes select very inefficient, and also -requires a mapping from file descriptors to socket handles (the Microsoft -C runtime provides the function \f(CW\*(C`_open_osfhandle\*(C'\fR for this). See the -discussion of the \f(CW\*(C`EV_SELECT_USE_FD_SET\*(C'\fR, \f(CW\*(C`EV_SELECT_IS_WINSOCKET\*(C'\fR and -\&\f(CW\*(C`EV_FD_TO_WIN32_HANDLE\*(C'\fR preprocessor symbols for more info. -.PP -The configuration for a \*(L"naked\*(R" win32 using the Microsoft runtime -libraries and raw winsocket select is: -.PP -.Vb 2 -\& #define EV_USE_SELECT 1 -\& #define EV_SELECT_IS_WINSOCKET 1 /* forces EV_SELECT_USE_FD_SET, too */ -.Ve -.PP -Note that winsockets handling of fd sets is O(n), so you can easily get a -complexity in the O(nA\*^X) range when using win32. -.PP -\fILimited number of file descriptors\fR -.IX Subsection "Limited number of file descriptors" -.PP -Windows has numerous arbitrary (and low) limits on things. -.PP -Early versions of winsocket's select only supported waiting for a maximum -of \f(CW64\fR handles (probably owning to the fact that all windows kernels -can only wait for \f(CW64\fR things at the same time internally; Microsoft -recommends spawning a chain of threads and wait for 63 handles and the -previous thread in each. Sounds great!). -.PP -Newer versions support more handles, but you need to define \f(CW\*(C`FD_SETSIZE\*(C'\fR -to some high number (e.g. \f(CW2048\fR) before compiling the winsocket select -call (which might be in libev or elsewhere, for example, perl and many -other interpreters do their own select emulation on windows). -.PP -Another limit is the number of file descriptors in the Microsoft runtime -libraries, which by default is \f(CW64\fR (there must be a hidden \fI64\fR -fetish or something like this inside Microsoft). You can increase this -by calling \f(CW\*(C`_setmaxstdio\*(C'\fR, which can increase this limit to \f(CW2048\fR -(another arbitrary limit), but is broken in many versions of the Microsoft -runtime libraries. This might get you to about \f(CW512\fR or \f(CW2048\fR sockets -(depending on windows version and/or the phase of the moon). To get more, -you need to wrap all I/O functions and provide your own fd management, but -the cost of calling select (O(nA\*^X)) will likely make this unworkable. -.SS "\s-1PORTABILITY\s0 \s-1REQUIREMENTS\s0" -.IX Subsection "PORTABILITY REQUIREMENTS" -In addition to a working ISO-C implementation and of course the -backend-specific APIs, libev relies on a few additional extensions: -.ie n .IP """void (*)(ev_watcher_type *, int revents)"" must have compatible calling conventions regardless of ""ev_watcher_type *""." 4 -.el .IP "\f(CWvoid (*)(ev_watcher_type *, int revents)\fR must have compatible calling conventions regardless of \f(CWev_watcher_type *\fR." 4 -.IX Item "void (*)(ev_watcher_type *, int revents) must have compatible calling conventions regardless of ev_watcher_type *." -Libev assumes not only that all watcher pointers have the same internal -structure (guaranteed by \s-1POSIX\s0 but not by \s-1ISO\s0 C for example), but it also -assumes that the same (machine) code can be used to call any watcher -callback: The watcher callbacks have different type signatures, but libev -calls them using an \f(CW\*(C`ev_watcher *\*(C'\fR internally. -.IP "pointer accesses must be thread-atomic" 4 -.IX Item "pointer accesses must be thread-atomic" -Accessing a pointer value must be atomic, it must both be readable and -writable in one piece \- this is the case on all current architectures. -.ie n .IP """sig_atomic_t volatile"" must be thread-atomic as well" 4 -.el .IP "\f(CWsig_atomic_t volatile\fR must be thread-atomic as well" 4 -.IX Item "sig_atomic_t volatile must be thread-atomic as well" -The type \f(CW\*(C`sig_atomic_t volatile\*(C'\fR (or whatever is defined as -\&\f(CW\*(C`EV_ATOMIC_T\*(C'\fR) must be atomic with respect to accesses from different -threads. This is not part of the specification for \f(CW\*(C`sig_atomic_t\*(C'\fR, but is -believed to be sufficiently portable. -.ie n .IP """sigprocmask"" must work in a threaded environment" 4 -.el .IP "\f(CWsigprocmask\fR must work in a threaded environment" 4 -.IX Item "sigprocmask must work in a threaded environment" -Libev uses \f(CW\*(C`sigprocmask\*(C'\fR to temporarily block signals. This is not -allowed in a threaded program (\f(CW\*(C`pthread_sigmask\*(C'\fR has to be used). Typical -pthread implementations will either allow \f(CW\*(C`sigprocmask\*(C'\fR in the \*(L"main -thread\*(R" or will block signals process-wide, both behaviours would -be compatible with libev. Interaction between \f(CW\*(C`sigprocmask\*(C'\fR and -\&\f(CW\*(C`pthread_sigmask\*(C'\fR could complicate things, however. -.Sp -The most portable way to handle signals is to block signals in all threads -except the initial one, and run the signal handling loop in the initial -thread as well. -.ie n .IP """long"" must be large enough for common memory allocation sizes" 4 -.el .IP "\f(CWlong\fR must be large enough for common memory allocation sizes" 4 -.IX Item "long must be large enough for common memory allocation sizes" -To improve portability and simplify its \s-1API\s0, libev uses \f(CW\*(C`long\*(C'\fR internally -instead of \f(CW\*(C`size_t\*(C'\fR when allocating its data structures. On non-POSIX -systems (Microsoft...) this might be unexpectedly low, but is still at -least 31 bits everywhere, which is enough for hundreds of millions of -watchers. -.ie n .IP """double"" must hold a time value in seconds with enough accuracy" 4 -.el .IP "\f(CWdouble\fR must hold a time value in seconds with enough accuracy" 4 -.IX Item "double must hold a time value in seconds with enough accuracy" -The type \f(CW\*(C`double\*(C'\fR is used to represent timestamps. It is required to -have at least 51 bits of mantissa (and 9 bits of exponent), which is -good enough for at least into the year 4000 with millisecond accuracy -(the design goal for libev). This requirement is overfulfilled by -implementations using \s-1IEEE\s0 754, which is basically all existing ones. -.Sp -With \s-1IEEE\s0 754 doubles, you get microsecond accuracy until at least the -year 2255 (and millisecond accuracy till the year 287396 \- by then, libev -is either obsolete or somebody patched it to use \f(CW\*(C`long double\*(C'\fR or -something like that, just kidding). -.PP -If you know of other additional requirements drop me a note. -.SH "ALGORITHMIC COMPLEXITIES" -.IX Header "ALGORITHMIC COMPLEXITIES" -In this section the complexities of (many of) the algorithms used inside -libev will be documented. For complexity discussions about backends see -the documentation for \f(CW\*(C`ev_default_init\*(C'\fR. -.PP -All of the following are about amortised time: If an array needs to be -extended, libev needs to realloc and move the whole array, but this -happens asymptotically rarer with higher number of elements, so O(1) might -mean that libev does a lengthy realloc operation in rare cases, but on -average it is much faster and asymptotically approaches constant time. -.IP "Starting and stopping timer/periodic watchers: O(log skipped_other_timers)" 4 -.IX Item "Starting and stopping timer/periodic watchers: O(log skipped_other_timers)" -This means that, when you have a watcher that triggers in one hour and -there are 100 watchers that would trigger before that, then inserting will -have to skip roughly seven (\f(CW\*(C`ld 100\*(C'\fR) of these watchers. -.IP "Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers)" 4 -.IX Item "Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers)" -That means that changing a timer costs less than removing/adding them, -as only the relative motion in the event queue has to be paid for. -.IP "Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1)" 4 -.IX Item "Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1)" -These just add the watcher into an array or at the head of a list. -.IP "Stopping check/prepare/idle/fork/async watchers: O(1)" 4 -.IX Item "Stopping check/prepare/idle/fork/async watchers: O(1)" -.PD 0 -.IP "Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % \s-1EV_PID_HASHSIZE\s0))" 4 -.IX Item "Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE))" -.PD -These watchers are stored in lists, so they need to be walked to find the -correct watcher to remove. The lists are usually short (you don't usually -have many watchers waiting for the same fd or signal: one is typical, two -is rare). -.IP "Finding the next timer in each loop iteration: O(1)" 4 -.IX Item "Finding the next timer in each loop iteration: O(1)" -By virtue of using a binary or 4\-heap, the next timer is always found at a -fixed position in the storage array. -.IP "Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)" 4 -.IX Item "Each change on a file descriptor per loop iteration: O(number_of_watchers_for_this_fd)" -A change means an I/O watcher gets started or stopped, which requires -libev to recalculate its status (and possibly tell the kernel, depending -on backend and whether \f(CW\*(C`ev_io_set\*(C'\fR was used). -.IP "Activating one watcher (putting it into the pending state): O(1)" 4 -.IX Item "Activating one watcher (putting it into the pending state): O(1)" -.PD 0 -.IP "Priority handling: O(number_of_priorities)" 4 -.IX Item "Priority handling: O(number_of_priorities)" -.PD -Priorities are implemented by allocating some space for each -priority. When doing priority-based operations, libev usually has to -linearly search all the priorities, but starting/stopping and activating -watchers becomes O(1) with respect to priority handling. -.IP "Sending an ev_async: O(1)" 4 -.IX Item "Sending an ev_async: O(1)" -.PD 0 -.IP "Processing ev_async_send: O(number_of_async_watchers)" 4 -.IX Item "Processing ev_async_send: O(number_of_async_watchers)" -.IP "Processing signals: O(max_signal_number)" 4 -.IX Item "Processing signals: O(max_signal_number)" -.PD -Sending involves a system call \fIiff\fR there were no other \f(CW\*(C`ev_async_send\*(C'\fR -calls in the current loop iteration and the loop is currently -blocked. Checking for async and signal events involves iterating over all -running async watchers or all signal numbers. -.SH "PORTING FROM LIBEV 3.X TO 4.X" -.IX Header "PORTING FROM LIBEV 3.X TO 4.X" -The major version 4 introduced some incompatible changes to the \s-1API\s0. -.PP -At the moment, the \f(CW\*(C`ev.h\*(C'\fR header file provides compatibility definitions -for all changes, so most programs should still compile. The compatibility -layer might be removed in later versions of libev, so better update to the -new \s-1API\s0 early than late. -.ie n .IP """EV_COMPAT3"" backwards compatibility mechanism" 4 -.el .IP "\f(CWEV_COMPAT3\fR backwards compatibility mechanism" 4 -.IX Item "EV_COMPAT3 backwards compatibility mechanism" -The backward compatibility mechanism can be controlled by -\&\f(CW\*(C`EV_COMPAT3\*(C'\fR. See \*(L"\s-1PREPROCESSOR\s0 \s-1SYMBOLS/MACROS\s0\*(R" in the \*(L"\s-1EMBEDDING\s0\*(R" -section. -.ie n .IP """ev_default_destroy"" and ""ev_default_fork"" have been removed" 4 -.el .IP "\f(CWev_default_destroy\fR and \f(CWev_default_fork\fR have been removed" 4 -.IX Item "ev_default_destroy and ev_default_fork have been removed" -These calls can be replaced easily by their \f(CW\*(C`ev_loop_xxx\*(C'\fR counterparts: -.Sp -.Vb 2 -\& ev_loop_destroy (EV_DEFAULT_UC); -\& ev_loop_fork (EV_DEFAULT); -.Ve -.IP "function/symbol renames" 4 -.IX Item "function/symbol renames" -A number of functions and symbols have been renamed: -.Sp -.Vb 3 -\& ev_loop => ev_run -\& EVLOOP_NONBLOCK => EVRUN_NOWAIT -\& EVLOOP_ONESHOT => EVRUN_ONCE -\& -\& ev_unloop => ev_break -\& EVUNLOOP_CANCEL => EVBREAK_CANCEL -\& EVUNLOOP_ONE => EVBREAK_ONE -\& EVUNLOOP_ALL => EVBREAK_ALL -\& -\& EV_TIMEOUT => EV_TIMER -\& -\& ev_loop_count => ev_iteration -\& ev_loop_depth => ev_depth -\& ev_loop_verify => ev_verify -.Ve -.Sp -Most functions working on \f(CW\*(C`struct ev_loop\*(C'\fR objects don't have an -\&\f(CW\*(C`ev_loop_\*(C'\fR prefix, so it was removed; \f(CW\*(C`ev_loop\*(C'\fR, \f(CW\*(C`ev_unloop\*(C'\fR and -associated constants have been renamed to not collide with the \f(CW\*(C`struct -ev_loop\*(C'\fR anymore and \f(CW\*(C`EV_TIMER\*(C'\fR now follows the same naming scheme -as all other watcher types. Note that \f(CW\*(C`ev_loop_fork\*(C'\fR is still called -\&\f(CW\*(C`ev_loop_fork\*(C'\fR because it would otherwise clash with the \f(CW\*(C`ev_fork\*(C'\fR -typedef. -.ie n .IP """EV_MINIMAL"" mechanism replaced by ""EV_FEATURES""" 4 -.el .IP "\f(CWEV_MINIMAL\fR mechanism replaced by \f(CWEV_FEATURES\fR" 4 -.IX Item "EV_MINIMAL mechanism replaced by EV_FEATURES" -The preprocessor symbol \f(CW\*(C`EV_MINIMAL\*(C'\fR has been replaced by a different -mechanism, \f(CW\*(C`EV_FEATURES\*(C'\fR. Programs using \f(CW\*(C`EV_MINIMAL\*(C'\fR usually compile -and work, but the library code will of course be larger. -.SH "GLOSSARY" -.IX Header "GLOSSARY" -.IP "active" 4 -.IX Item "active" -A watcher is active as long as it has been started and not yet stopped. -See \*(L"\s-1WATCHER\s0 \s-1STATES\s0\*(R" for details. -.IP "application" 4 -.IX Item "application" -In this document, an application is whatever is using libev. -.IP "backend" 4 -.IX Item "backend" -The part of the code dealing with the operating system interfaces. -.IP "callback" 4 -.IX Item "callback" -The address of a function that is called when some event has been -detected. Callbacks are being passed the event loop, the watcher that -received the event, and the actual event bitset. -.IP "callback/watcher invocation" 4 -.IX Item "callback/watcher invocation" -The act of calling the callback associated with a watcher. -.IP "event" 4 -.IX Item "event" -A change of state of some external event, such as data now being available -for reading on a file descriptor, time having passed or simply not having -any other events happening anymore. -.Sp -In libev, events are represented as single bits (such as \f(CW\*(C`EV_READ\*(C'\fR or -\&\f(CW\*(C`EV_TIMER\*(C'\fR). -.IP "event library" 4 -.IX Item "event library" -A software package implementing an event model and loop. -.IP "event loop" 4 -.IX Item "event loop" -An entity that handles and processes external events and converts them -into callback invocations. -.IP "event model" 4 -.IX Item "event model" -The model used to describe how an event loop handles and processes -watchers and events. -.IP "pending" 4 -.IX Item "pending" -A watcher is pending as soon as the corresponding event has been -detected. See \*(L"\s-1WATCHER\s0 \s-1STATES\s0\*(R" for details. -.IP "real time" 4 -.IX Item "real time" -The physical time that is observed. It is apparently strictly monotonic :) -.IP "wall-clock time" 4 -.IX Item "wall-clock time" -The time and date as shown on clocks. Unlike real time, it can actually -be wrong and jump forwards and backwards, e.g. when you adjust your -clock. -.IP "watcher" 4 -.IX Item "watcher" -A data structure that describes interest in certain events. Watchers need -to be started (attached to an event loop) before they can receive events. -.SH "AUTHOR" -.IX Header "AUTHOR" -Marc Lehmann , with repeated corrections by Mikael -Magnusson and Emanuele Giaquinta, and minor corrections by many others. diff --git a/lib/libev/ev.c b/lib/libev/ev.c index 5bf467c..252a31f 100644 --- a/lib/libev/ev.c +++ b/lib/libev/ev.c @@ -729,6 +729,8 @@ struct signalfd_siginfo #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE #endif +#include + /*****************************************************************************/ #if __cplusplus diff --git a/lib/libhttp_parser/Makefile b/lib/libhttp_parser/Makefile index 682e801..18179f2 100644 --- a/lib/libhttp_parser/Makefile +++ b/lib/libhttp_parser/Makefile @@ -104,7 +104,7 @@ default: all all: library package -clean: +clean maintainer-clean: rm -f *.o *.a tags test test_fast test_g \ http_parser.tar libhttp_parser.so* \ url_parser url_parser_g parsertrace parsertrace_g diff --git a/lib/libuinet/Makefile b/lib/libuinet/Makefile index 78c4c47..09cf597 100644 --- a/lib/libuinet/Makefile +++ b/lib/libuinet/Makefile @@ -350,8 +350,8 @@ ${OBJS}: %.o: %.c ${IMACROS_FILE} .m.h: ${AWK} -f $S/tools/makeobjops.awk $< -h -.PHONY: clean -clean: +.PHONY: maintainer-clean clean +maintainer-clean clean: rm -f libuinet.a rm -f ${MHEADERS} ${MSRCS} ${HOST_OBJS} ${OBJS} ${PROGRAM} ${IMACROS_FILE} rm -rf ${MACHINE_INCLUDES_ROOT} diff --git a/lib/libuinet/Makefile.inc b/lib/libuinet/Makefile.inc index b2a89c9..64277fa 100644 --- a/lib/libuinet/Makefile.inc +++ b/lib/libuinet/Makefile.inc @@ -9,3 +9,6 @@ LDADD+= -lcrypto else LDADD+= -lssl endif +ifeq ($(shell uname -s),FreeBSD) +LDADD+= -lcrypto +endif diff --git a/lib/libuinet/api_include/uinet_api.h b/lib/libuinet/api_include/uinet_api.h index c5f3920..e628a4e 100644 --- a/lib/libuinet/api_include/uinet_api.h +++ b/lib/libuinet/api_include/uinet_api.h @@ -37,10 +37,12 @@ extern "C" { #include "uinet_config.h" #include "uinet_queue.h" +int uinet_clearifstat(const char *name); void uinet_finalize_thread(void); int uinet_getl2info(struct uinet_socket *so, struct uinet_in_l2info *l2i); int uinet_getifstat(const char *name, struct uinet_ifstat *stat); void uinet_gettcpstat(struct uinet_tcpstat *stat); +void uinet_cleartcpstat(void); char *uinet_inet_ntoa(struct uinet_in_addr in, char *buf, unsigned int size); const char *uinet_inet_ntop(int af, const void *src, char *dst, unsigned int size); int uinet_inet_pton(int af, const char *src, void *dst); diff --git a/lib/libuinet/api_include/uinet_api_types.h b/lib/libuinet/api_include/uinet_api_types.h index 67645a4..cf3fdc6 100644 --- a/lib/libuinet/api_include/uinet_api_types.h +++ b/lib/libuinet/api_include/uinet_api_types.h @@ -424,6 +424,8 @@ struct uinet_in_l2tagstack { #define UINET_INL2I_TAG_ANY 0x01 +#define UINET_INL2I_TAG_SRCIF_EXT 0x02 +#define UINET_INL2I_TAG_SRCIF_INT 0x04 struct uinet_in_l2info { uint8_t inl2i_local_addr[UINET_IN_L2INFO_ADDR_MAX]; diff --git a/lib/libuinet/uinet_api.c b/lib/libuinet/uinet_api.c index 173561e..becc465 100644 --- a/lib/libuinet/uinet_api.c +++ b/lib/libuinet/uinet_api.c @@ -123,6 +123,47 @@ uinet_finalize_thread(void) } +int +uinet_clearifstat(const char *name) +{ + struct uinet_config_if *ifcfg; + struct ifnet *ifp; + + ifcfg = uinet_iffind_byname(name); + if (NULL == ifcfg) { + printf("could not find interface %s\n", name); + return (EINVAL); + } + + ifp = ifnet_byindex_ref(ifcfg->ifindex); + if (NULL == ifp) { + printf("could not find interface %s by index\n", name); + return (EINVAL); + } + + ifp->if_data.ifi_ipackets = 0; + ifp->if_data.ifi_ierrors = 0; + ifp->if_data.ifi_opackets = 0; + ifp->if_data.ifi_oerrors = 0; + ifp->if_data.ifi_collisions = 0; + ifp->if_data.ifi_ibytes = 0; + ifp->if_data.ifi_obytes = 0; + ifp->if_data.ifi_imcasts = 0; + ifp->if_data.ifi_omcasts = 0; + ifp->if_data.ifi_iqdrops = 0; + ifp->if_data.ifi_noproto = 0; + ifp->if_data.ifi_hwassist = 0; + ifp->if_data.ifi_epoch = 0; + ifp->if_data.ifi_icopies = 0; + ifp->if_data.ifi_izcopies = 0; + ifp->if_data.ifi_ocopies = 0; + ifp->if_data.ifi_ozcopies = 0; + + if_rele(ifp); + + return (0); +} + int uinet_getifstat(const char *name, struct uinet_ifstat *stat) { @@ -171,6 +212,13 @@ uinet_gettcpstat(struct uinet_tcpstat *stat) *((struct tcpstat *)stat) = tcpstat; } +void +uinet_cleartcpstat(void) +{ + + bzero(&tcpstat, sizeof(tcpstat)); +} + char * uinet_inet_ntoa(struct uinet_in_addr in, char *buf, unsigned int size) diff --git a/lib/libuinet/uinet_api.symlist b/lib/libuinet/uinet_api.symlist index 615d8e2..4bbb962 100644 --- a/lib/libuinet/uinet_api.symlist +++ b/lib/libuinet/uinet_api.symlist @@ -1,3 +1,5 @@ +uinet_clearifstat +uinet_cleartcpstat uinet_config_blackhole uinet_errno_to_os uinet_finalize_thread diff --git a/lib/libuinet/uinet_config.c b/lib/libuinet/uinet_config.c index 0d9298b..8fe4f44 100644 --- a/lib/libuinet/uinet_config.c +++ b/lib/libuinet/uinet_config.c @@ -185,6 +185,12 @@ uinet_ifdestroy_internal(struct uinet_config_if *cfg) case UINET_IFTYPE_PCAP: error = if_pcap_detach(cfg); break; + case UINET_IFTYPE_BRIDGE: + error = if_bridge_detach(cfg); + break; + case UINET_IFTYPE_SPAN: + error = if_span_detach(cfg); + break; default: printf("Error detaching interface %s: unknown interface type %d\n", cfg->name, cfg->type); error = ENXIO; diff --git a/lib/libuinet/uinet_config_kernel.c b/lib/libuinet/uinet_config_kernel.c index db61a61..ccb8831 100644 --- a/lib/libuinet/uinet_config_kernel.c +++ b/lib/libuinet/uinet_config_kernel.c @@ -66,4 +66,3 @@ uinet_config_blackhole(uinet_blackhole_t action) &val, sizeof(int), NULL, 0); return (error); } - diff --git a/lib/libuinet/uinet_host_interface.c b/lib/libuinet/uinet_host_interface.c index d095625..3d2121f 100644 --- a/lib/libuinet/uinet_host_interface.c +++ b/lib/libuinet/uinet_host_interface.c @@ -490,6 +490,7 @@ int uhi_thread_bound_cpu() int bound_cpu; int i; + bzero(&cpuset, sizeof(cpuset)); pthread_getaffinity_np(pthread_self(), sizeof(cpuset_t), &cpuset); /* @@ -1104,11 +1105,16 @@ uhi_arc4rand(void *ptr, unsigned int len, int reseed) { #if !defined(__APPLE__) + int ret; + (void)reseed; /* XXX assuming that we don't have to manually seed this */ - RAND_pseudo_bytes(ptr, len); + ret = RAND_pseudo_bytes(ptr, len); + if (ret != 1) { + printf("%s: didn't return random data!\n", __func__); + } #else if (reseed) arc4random_stir(); @@ -1121,7 +1127,7 @@ uhi_arc4rand(void *ptr, unsigned int len, int reseed) uint32_t uhi_arc4random(void) { - uint32_t ret; + uint32_t ret = 0; uhi_arc4rand(&ret, sizeof ret, 0); return ret; diff --git a/lib/libuinet/uinet_host_sysctl_api.c b/lib/libuinet/uinet_host_sysctl_api.c index 7be3abc..4894e89 100644 --- a/lib/libuinet/uinet_host_sysctl_api.c +++ b/lib/libuinet/uinet_host_sysctl_api.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -470,6 +471,13 @@ uinet_host_sysctl_listener_thread(void *arg) (void) unlink(path); + /* Set thread title */ +#if defined(__FreeBSD__) + pthread_set_name_np(pthread_self(), "sysctl thread"); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), "sysctl thread"); +#endif + bzero(&sun, sizeof(sun)); strcpy(sun.sun_path, path); sun.sun_family = AF_UNIX; @@ -504,6 +512,7 @@ uinet_host_sysctl_listener_thread(void *arg) int ret; const char *type; + sl = sizeof(sun_n); ns = accept(s, (struct sockaddr *) &sun_n, &sl); if (ns < 0) { fprintf(stderr, "%s: accept failed: %d\n", __func__, errno); diff --git a/lib/libuinet/uinet_if_bridge.c b/lib/libuinet/uinet_if_bridge.c index 4720363..00c4b6f 100644 --- a/lib/libuinet/uinet_if_bridge.c +++ b/lib/libuinet/uinet_if_bridge.c @@ -61,10 +61,12 @@ extern int (*bridge_output_p)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); struct if_bridge_member; +struct if_bridge_softc; struct if_bridge_member { LIST_ENTRY(if_bridge_member) bif_next; struct ifnet *ifp; + struct if_bridge_softc *br_softc; int is_inside; int is_outside; }; @@ -90,11 +92,12 @@ static struct mbuf * if_bridge_input(struct ifnet *ifp, struct mbuf *m) { struct if_bridge_softc *sc; - struct if_bridge_member *bif; + struct if_bridge_member *bif, *bif_m; struct ifnet *bifp; struct mbuf *mc2; - sc = ifp->if_bridge; + bif = ifp->if_bridge; + sc = bif->br_softc; bifp = sc->sc_ifp; // printf("%s: m=%p: called\n", __func__, m); @@ -117,6 +120,14 @@ if_bridge_input(struct ifnet *ifp, struct mbuf *m) * ie, from is_input? send to only is_output. */ + /* Tag the mbuf with the correct direction information */ + m->m_flags &= ~(M_BRIDGEIF_DIR_INT | M_BRIDGEIF_DIR_EXT); + if (bif->is_inside) { + m->m_flags |= M_BRIDGEIF_DIR_INT; + } else if (bif->is_outside) { + m->m_flags |= M_BRIDGEIF_DIR_EXT; + } + /* * XXX TODO: don't hold the lock across sending to the two * (or more) ports - it's highly inefficient and effectively @@ -124,37 +135,33 @@ if_bridge_input(struct ifnet *ifp, struct mbuf *m) * LOCK2REF/etc stuff to do this without holding a lock. */ mtx_lock(&sc->sc_mtx); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { - if (bif->ifp == ifp) + LIST_FOREACH(bif_m, &sc->sc_iflist, bif_next) { + /* Don't send traffic back to the same interface */ + if (bif_m->ifp == ifp) + continue; + + /* Don't send traffic to the same interface type */ + if (bif_m->is_inside && bif->is_inside) + continue; + if (bif_m->is_outside && bif->is_outside) continue; + //mc2 = m_copypacket(m, M_DONTWAIT); mc2 = m_dup(m, M_DONTWAIT); /* XXX count failure */ if (mc2 == NULL) continue; /* XXX count failure */ - (void) bif->ifp->if_transmit(bif->ifp, mc2); + (void) bif_m->ifp->if_transmit(bif_m->ifp, mc2); } mtx_unlock(&sc->sc_mtx); - /* We don't do local processing; just punt to the bridge */ - + /* We don't do local processing; just punt to the stack as if_bridge */ m->m_pkthdr.rcvif = bifp; (*bifp->if_input)(bifp, m); - return (NULL); -#if 0 - /* Duplicate; pass up to the stack */ - mc2 = m_copypacket(m, M_DONTWAIT); - /* XXX count failure */ - if (mc2 != NULL) { - mc2->m_pkthdr.rcvif = bifp; - (*bifp->if_input)(bifp, mc2); - } - - /* Return the original packet for local processing. */ - return (m); -#endif + /* We're not passing this up the stack for local processing */ + return (NULL); } /* @@ -284,8 +291,12 @@ if_bridge_addm(struct if_bridge_softc *sc, const char *ifname, int isin) /* Add to list; link back from the ifnet to the parent bridge */ bif->ifp = nifp; + /* And a link back to the bridge softc */ + bif->br_softc = sc; + /* Add to the member list */ LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next); - nifp->if_bridge = sc; + + nifp->if_bridge = bif; mtx_unlock(&sc->sc_mtx); diff --git a/lib/libuinet_memstat/Makefile b/lib/libuinet_memstat/Makefile index 2149058..298f7d7 100644 --- a/lib/libuinet_memstat/Makefile +++ b/lib/libuinet_memstat/Makefile @@ -15,7 +15,7 @@ all: libuinet_memstat.a libuinet_memstat.a: $(OBJS) $(AR) -c -r libuinet_memstat.a $(OBJS) -clean: +clean maintainer-clean: $(RM) $(OBJS) libuinet_memstat.a install: diff --git a/lib/libuinetnv/Makefile b/lib/libuinetnv/Makefile index f8074d6..486d905 100644 --- a/lib/libuinetnv/Makefile +++ b/lib/libuinetnv/Makefile @@ -14,7 +14,7 @@ all: libuinetnv.a libuinetnv.a: $(OBJS) $(AR) -c -r libuinetnv.a $(OBJS) -clean: +clean maintainer-clean: $(RM) $(OBJS) libuinetnv.a install: diff --git a/mk/prog.mk b/mk/prog.mk index 5283198..7e170a2 100644 --- a/mk/prog.mk +++ b/mk/prog.mk @@ -17,6 +17,7 @@ endif ifdef PROG_CXX PROG= ${PROG_CXX} +CXX= c++ endif ifndef PROG @@ -57,7 +58,7 @@ else endif -clean: +maintainer-clean clean: @rm -f ${PROG} ${OBJS} all: ${PROG} diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h index dde9b73..179d13f 100644 --- a/sys/net/ethernet.h +++ b/sys/net/ethernet.h @@ -28,6 +28,16 @@ */ #define ETHER_ALIGN 2 /* driver adjust for IP hdr alignment */ +#define ETHER_ADDR_COPY(dst, src) \ + do { \ + ((char *) dst)[0] = ((char *) src)[0]; \ + ((char *) dst)[1] = ((char *) src)[1]; \ + ((char *) dst)[2] = ((char *) src)[2]; \ + ((char *) dst)[3] = ((char *) src)[3]; \ + ((char *) dst)[4] = ((char *) src)[4]; \ + ((char *) dst)[5] = ((char *) src)[5]; \ + } while (0) + /* * Compute the maximum frame size based on ethertype (i.e. possible * encapsulation) and whether or not an FCS is present. @@ -41,6 +51,8 @@ * Ethernet-specific mbuf flags. */ #define M_HASFCS M_PROTO5 /* FCS included at end of frame */ +#define M_BRIDGEIF_DIR_EXT M_PROTO6 /* Bridge traffic; from external interface */ +#define M_BRIDGEIF_DIR_INT M_PROTO7 /* Bridge traffic; from internal interface */ /* * Ethernet CRC32 polynomials (big- and little-endian verions). diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 56fa7f2..923234b 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -362,10 +362,10 @@ ether_output(struct ifnet *ifp, struct mbuf *m, d = mtod(m, uint8_t *); eh = (struct ether_header *)d; - (void)memcpy(d, l2i->inl2i_foreign_addr, ETHER_ADDR_LEN); + ETHER_ADDR_COPY(d, l2i->inl2i_foreign_addr); d += ETHER_ADDR_LEN; - (void)memcpy(d, l2i->inl2i_local_addr, ETHER_ADDR_LEN); + ETHER_ADDR_COPY(d, l2i->inl2i_local_addr); d += ETHER_ADDR_LEN; if (num_tag_bytes) { @@ -734,8 +734,40 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m) } } + /* + * This code is much earlier than previous code - we want + * a VLAN bridge that actually just copies the mbufs before + * VLAN de-encapsulation. + * + * It also needs to be done before the promiscinet information + * is added via mbuf tags or those tags get copied into + * bridge/span interface mbufs during m_copypacket() - and + * that's a lot of wasted time. + */ + + /* + * Allow if_bridge(4) to claim this frame. + * The BRIDGE_INPUT() macro will update ifp if the bridge changed it + * and the frame should be delivered locally. + */ + if (ifp->if_bridge != NULL) { + m->m_flags &= ~M_PROMISC; + BRIDGE_INPUT(ifp, m); + if (m == NULL) { + CURVNET_RESTORE(); + return; + } + } #ifdef PROMISCUOUS_INET + /* + * Span mode debug - we shouldn't see PROMISCINET if if_bridge + * is set. + */ + if ((ifp->if_flags & IFF_PROMISCINET) && (ifp->if_bridge != NULL)) { + printf("wtf?\n"); + } + if (ifp->if_flags & IFF_PROMISCINET) { struct ifl2info *l2info_tag; struct in_l2info *l2info; @@ -757,9 +789,18 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m) l2info = &l2info_tag->ifl2i_info; l2ts = &l2info->inl2i_tagstack; - memcpy(l2info->inl2i_local_addr, eh->ether_dhost, ETHER_ADDR_LEN); - memcpy(l2info->inl2i_foreign_addr, eh->ether_shost, ETHER_ADDR_LEN); + ETHER_ADDR_COPY(l2info->inl2i_local_addr, eh->ether_dhost); + ETHER_ADDR_COPY(l2info->inl2i_foreign_addr, eh->ether_shost); l2ts->inl2t_cnt = 0; + l2info->inl2i_flags = 0; + + /* + * Handle the bridge mbuf flags to set interface directionality. + */ + if (m->m_flags & M_BRIDGEIF_DIR_INT) + l2info->inl2i_flags |= INL2I_TAG_SRCIF_INT; + else if (m->m_flags & M_BRIDGEIF_DIR_EXT) + l2info->inl2i_flags |= INL2I_TAG_SRCIF_EXT; /* * If the interface is in IFF_PROMISCINET mode and the hardware @@ -899,6 +940,7 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m) } } +#if 0 /* * Allow if_bridge(4) to claim this frame. * The BRIDGE_INPUT() macro will update ifp if the bridge changed it @@ -912,6 +954,8 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m) return; } } +#ne +#endif #if defined(INET) || defined(INET6) /* diff --git a/sys/netinet/in_promisc.h b/sys/netinet/in_promisc.h index f587b90..d1e3a1e 100644 --- a/sys/netinet/in_promisc.h +++ b/sys/netinet/in_promisc.h @@ -66,6 +66,8 @@ struct in_l2tagstack { /* flags for inl2i_flags */ #define INL2I_TAG_ANY 0x01 +#define INL2I_TAG_SRCIF_EXT 0x02 +#define INL2I_TAG_SRCIF_INT 0x04 struct in_l2info { uint8_t inl2i_local_addr[IN_L2INFO_ADDR_MAX]; diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 917b8eb..3801323 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -575,7 +575,7 @@ tcp_input(struct mbuf *m, int off0) u_char *optp = NULL; int optlen = 0; #ifdef INET - int len; +// int len; #endif int tlen = 0, off; int drop_hdrlen; @@ -686,6 +686,16 @@ tcp_input(struct mbuf *m, int off0) th = (struct tcphdr *)((caddr_t)ip + off0); tlen = ip->ip_len; + /* + * TCP checksums are disabled for now. + * + * It's pretty stupid, but the netmap interface + * doesn't seem to provide hardware checksums up to + * the userland code and so this kernel code + * recalculates them. This chews a noticable + * amount of CPU time for large amounts of data. + */ +#if 0 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) th->th_sum = m->m_pkthdr.csum_data; @@ -714,6 +724,8 @@ tcp_input(struct mbuf *m, int off0) TCPSTAT_INC(tcps_rcvbadsum); goto drop; } +#endif + th->th_sum = 0; /* Re-initialization for later version check */ ip->ip_v = IPVERSION; }