rough EV_FEATURES implementation

master
Marc Alexander Lehmann 2010-03-16 00:20:16 +00:00
parent eb9848a8dc
commit a23208bdf8
4 changed files with 169 additions and 136 deletions

View File

@ -1,9 +1,10 @@
Revision history for libev, a high-performance and full-featured event loop.
TODO: accept() documentation
TODO: ABI??? API????? Changes???
- ev_embed_stop did not correctly stop the watcher (very good
testcase by Vladimir Timofeev).
- applied win32 fixes by Michael Lenaghan (also James Mansion).
- replace EV_MINIMAL by EV_FEATURES.
- remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu).
- configure now prepends -O3, not appends it, so one can still
override it.

80
ev.c
View File

@ -221,7 +221,7 @@ extern "C" {
#ifndef EV_USE_CLOCK_SYSCALL
# if __linux && __GLIBC__ >= 2
# define EV_USE_CLOCK_SYSCALL 1
# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
# else
# define EV_USE_CLOCK_SYSCALL 0
# endif
@ -229,7 +229,7 @@ extern "C" {
#ifndef EV_USE_MONOTONIC
# if defined (_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
# define EV_USE_MONOTONIC 1
# define EV_USE_MONOTONIC EV_FEATURE_OS
# else
# define EV_USE_MONOTONIC 0
# endif
@ -241,27 +241,27 @@ extern "C" {
#ifndef EV_USE_NANOSLEEP
# if _POSIX_C_SOURCE >= 199309L
# define EV_USE_NANOSLEEP 1
# define EV_USE_NANOSLEEP EV_FEATURE_OS
# else
# define EV_USE_NANOSLEEP 0
# endif
#endif
#ifndef EV_USE_SELECT
# define EV_USE_SELECT 1
# define EV_USE_SELECT EV_FEATURE_BACKENDS
#endif
#ifndef EV_USE_POLL
# ifdef _WIN32
# define EV_USE_POLL 0
# else
# define EV_USE_POLL 1
# define EV_USE_POLL EV_FEATURE_BACKENDS
# endif
#endif
#ifndef EV_USE_EPOLL
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
# define EV_USE_EPOLL 1
# define EV_USE_EPOLL EV_FEATURE_BACKENDS
# else
# define EV_USE_EPOLL 0
# endif
@ -277,31 +277,23 @@ extern "C" {
#ifndef EV_USE_INOTIFY
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
# define EV_USE_INOTIFY 1
# define EV_USE_INOTIFY EV_FEATURE_OS
# else
# define EV_USE_INOTIFY 0
# endif
#endif
#ifndef EV_PID_HASHSIZE
# if EV_MINIMAL
# define EV_PID_HASHSIZE 1
# else
# define EV_PID_HASHSIZE 16
# endif
# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1
#endif
#ifndef EV_INOTIFY_HASHSIZE
# if EV_MINIMAL
# define EV_INOTIFY_HASHSIZE 1
# else
# define EV_INOTIFY_HASHSIZE 16
# endif
# define EV_INOTIFY_HASHSIZE EV_FEATURE_DATA ? 16 : 1
#endif
#ifndef EV_USE_EVENTFD
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
# define EV_USE_EVENTFD 1
# define EV_USE_EVENTFD EV_FEATURE_OS
# else
# define EV_USE_EVENTFD 0
# endif
@ -309,7 +301,7 @@ extern "C" {
#ifndef EV_USE_SIGNALFD
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
# define EV_USE_SIGNALFD 1
# define EV_USE_SIGNALFD EV_FEATURE_OS
# else
# define EV_USE_SIGNALFD 0
# endif
@ -322,15 +314,15 @@ extern "C" {
#endif
#ifndef EV_VERIFY
# define EV_VERIFY !EV_MINIMAL
# define EV_VERIFY (EV_FEATURE_API ? 1 : 0)
#endif
#ifndef EV_USE_4HEAP
# define EV_USE_4HEAP !EV_MINIMAL
# define EV_USE_4HEAP EV_FEATURE_DATA
#endif
#ifndef EV_HEAP_CACHE_AT
# define EV_HEAP_CACHE_AT !EV_MINIMAL
# define EV_HEAP_CACHE_AT EV_FEATURE_DATA
#endif
/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
@ -478,10 +470,10 @@ struct signalfd_siginfo
#define expect_true(expr) expect ((expr) != 0, 1)
#define inline_size static inline
#if EV_MINIMAL
# define inline_speed static noinline
#else
#if EV_FEATURE_CODE
# define inline_speed static inline
#else
# define inline_speed static noinline
#endif
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
@ -698,7 +690,7 @@ typedef struct
#endif
#if EV_MINIMAL < 2
#if EV_FEATURE_API
# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)
# define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A)
# define EV_INVOKE_PENDING invoke_cb (EV_A)
@ -1405,7 +1397,7 @@ child_reap (EV_P_ int chain, int pid, int status)
ev_child *w;
int traced = WIFSTOPPED (status) || WIFCONTINUED (status);
for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next)
{
if ((w->pid == pid || !w->pid)
&& (!traced || (w->flags & 1)))
@ -1440,7 +1432,7 @@ childcb (EV_P_ ev_signal *sw, int revents)
ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);
child_reap (EV_A_ pid, pid, status);
if (EV_PID_HASHSIZE > 1)
if ((EV_PID_HASHSIZE) > 1)
child_reap (EV_A_ 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */
}
@ -1539,7 +1531,7 @@ ev_backend (EV_P)
return backend;
}
#if EV_MINIMAL < 2
#if EV_FEATURE_API
unsigned int
ev_loop_count (EV_P)
{
@ -1629,7 +1621,7 @@ loop_init (EV_P_ unsigned int flags)
mn_now = get_clock ();
now_floor = mn_now;
rtmn_diff = ev_rt_now - mn_now;
#if EV_MINIMAL < 2
#if EV_FEATURE_API
invoke_cb = ev_invoke_pending;
#endif
@ -1876,7 +1868,7 @@ array_verify (EV_P_ W *ws, int cnt)
}
#endif
#if EV_MINIMAL < 2
#if EV_FEATURE_API
void
ev_loop_verify (EV_P)
{
@ -1939,7 +1931,7 @@ ev_loop_verify (EV_P)
# if 0
#if EV_CHILD_ENABLE
for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next)
for (signum = EV_NSIG; signum--; ) if (signals [signum].pending)
#endif
# endif
@ -2277,7 +2269,7 @@ time_update (EV_P_ ev_tstamp max_block)
void
ev_loop (EV_P_ int flags)
{
#if EV_MINIMAL < 2
#if EV_FEATURE_API
++loop_depth;
#endif
@ -2380,7 +2372,7 @@ ev_loop (EV_P_ int flags)
}
}
#if EV_MINIMAL < 2
#if EV_FEATURE_API
++loop_count;
#endif
assert ((loop_done = EVUNLOOP_RECURSE, 1)); /* assert for side effect */
@ -2419,7 +2411,7 @@ ev_loop (EV_P_ int flags)
if (loop_done == EVUNLOOP_ONE)
loop_done = EVUNLOOP_CANCEL;
#if EV_MINIMAL < 2
#if EV_FEATURE_API
--loop_depth;
#endif
}
@ -2879,7 +2871,7 @@ ev_child_start (EV_P_ ev_child *w)
EV_FREQUENT_CHECK;
ev_start (EV_A_ (W)w, 1);
wlist_add (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
wlist_add (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w);
EV_FREQUENT_CHECK;
}
@ -2893,7 +2885,7 @@ ev_child_stop (EV_P_ ev_child *w)
EV_FREQUENT_CHECK;
wlist_del (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
wlist_del (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w);
ev_stop (EV_A_ (W)w);
EV_FREQUENT_CHECK;
@ -2976,7 +2968,7 @@ infy_add (EV_P_ ev_stat *w)
}
if (w->wd >= 0)
wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w);
wlist_add (&fs_hash [w->wd & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w);
/* now re-arm timer, if required */
if (ev_is_active (&w->timer)) ev_ref (EV_A);
@ -2994,7 +2986,7 @@ infy_del (EV_P_ ev_stat *w)
return;
w->wd = -2;
slot = wd & (EV_INOTIFY_HASHSIZE - 1);
slot = wd & ((EV_INOTIFY_HASHSIZE) - 1);
wlist_del (&fs_hash [slot].head, (WL)w);
/* remove this watcher, if others are watching it, they will rearm */
@ -3006,13 +2998,13 @@ infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
{
if (slot < 0)
/* overflow, need to check for all hash slots */
for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot)
for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot)
infy_wd (EV_A_ slot, wd, ev);
else
{
WL w_;
for (w_ = fs_hash [slot & (EV_INOTIFY_HASHSIZE - 1)].head; w_; )
for (w_ = fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head; w_; )
{
ev_stat *w = (ev_stat *)w_;
w_ = w_->next; /* lets us remove this watcher and all before it */
@ -3021,7 +3013,7 @@ infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
{
if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF))
{
wlist_del (&fs_hash [slot & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w);
wlist_del (&fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w);
w->wd = -1;
infy_add (EV_A_ w); /* re-add, no matter what */
}
@ -3145,7 +3137,7 @@ infy_fork (EV_P)
ev_unref (EV_A);
}
for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot)
for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot)
{
WL w_ = fs_hash [slot].head;
fs_hash [slot].head = 0;
@ -3771,7 +3763,7 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
#if EV_CHILD_ENABLE
if (types & EV_CHILD)
for (i = EV_PID_HASHSIZE; i--; )
for (i = (EV_PID_HASHSIZE); i--; )
for (wl = childs [i]; wl; )
{
wn = wl->next;

62
ev.h
View File

@ -1,7 +1,7 @@
/*
* libev native API header
*
* Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
@ -44,73 +44,79 @@
extern "C" {
#endif
typedef double ev_tstamp;
/*****************************************************************************/
#ifndef EV_FEATURES
# define EV_FEATURES 0x3f
#endif
#define EV_FEATURE_CODE ((EV_FEATURES) & 1)
#define EV_FEATURE_DATA ((EV_FEATURES) & 2)
#define EV_FEATURE_API ((EV_FEATURES) & 4)
#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 8)
#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 16)
#define EV_FEATURE_OS ((EV_FEATURES) & 32)
/* these priorities are inclusive, higher priorities will be called earlier */
#ifndef EV_MINPRI
# define EV_MINPRI -2
# define EV_MINPRI (EV_FEATURE_API ? -2 : 0)
#endif
#ifndef EV_MAXPRI
# define EV_MAXPRI +2
# define EV_MAXPRI (EV_FEATURE_API ? +2 : 0)
#endif
#ifndef EV_MULTIPLICITY
# define EV_MULTIPLICITY 1
# define EV_MULTIPLICITY EV_FEATURE_API
#endif
#ifndef EV_PERIODIC_ENABLE
# define EV_PERIODIC_ENABLE 1
# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_STAT_ENABLE
# define EV_STAT_ENABLE 1
# define EV_STAT_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_PREPARE_ENABLE
# define EV_PREPARE_ENABLE 1
# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHECK_ENABLE
# define EV_CHECK_ENABLE 1
# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_IDLE_ENABLE
# define EV_IDLE_ENABLE 1
# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_FORK_ENABLE
# define EV_FORK_ENABLE 1
# define EV_FORK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE 1
# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHILD_ENABLE
# ifdef _WIN32
# define EV_CHILD_ENABLE 0
# else
# define EV_CHILD_ENABLE 1
# define EV_CHILD_ENABLE EV_FEATURE_WATCHERS
#endif
#endif
#ifndef EV_ASYNC_ENABLE
# define EV_ASYNC_ENABLE 1
# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_EMBED_ENABLE
# define EV_EMBED_ENABLE 1
# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_WALK_ENABLE
# define EV_WALK_ENABLE 0 /* not yet */
#endif
#ifndef EV_ATOMIC_T
# include <signal.h>
# define EV_ATOMIC_T sig_atomic_t volatile
#endif
/*****************************************************************************/
#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE
@ -118,6 +124,20 @@ typedef double ev_tstamp;
# define EV_SIGNAL_ENABLE 1
#endif
/*****************************************************************************/
#if !EV_FEATURE_CODE && !defined (NDEBUG)
# define NDEBUG 1
# include <assert.h>
#endif
typedef double ev_tstamp;
#ifndef EV_ATOMIC_T
# include <signal.h>
# define EV_ATOMIC_T sig_atomic_t volatile
#endif
#if EV_STAT_ENABLE
# ifdef _WIN32
# include <time.h>
@ -569,7 +589,7 @@ void ev_unref (EV_P);
*/
void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg);
# if EV_MINIMAL < 2
# if EV_FEATURE_API
unsigned int ev_loop_count (EV_P); /* number of loop iterations */
unsigned int ev_loop_depth (EV_P); /* #ev_loop enters - #ev_loop leaves */
void ev_loop_verify (EV_P); /* abort if loop data corrupted */

160
ev.pod
View File

@ -3886,64 +3886,90 @@ If undefined or defined to be C<1> (and the platform supports it), then
the respective watcher type is supported. If defined to be C<0>, then it
is not. Disabling watcher types mainly saves codesize.
=item EV_MINIMAL
=item EV_FEATURES
If you need to shave off some kilobytes of code at the expense of some
speed (but with the full API), define this symbol to C<1>. Currently this
is used to override some inlining decisions, saves roughly 30% code size
on amd64. It also selects a much smaller 2-heap for timer management over
the default 4-heap.
speed (but with the full API), 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.
You can save even more by disabling watcher types you do not need
and setting C<EV_MAXPRI> == C<EV_MINPRI>. Also, disabling C<assert>
(C<-DNDEBUG>) will usually reduce code size a lot. Disabling inotify,
eventfd and signalfd will further help, and disabling backends one doesn't
need (e.g. poll, epoll, kqueue, ports) will help further.
Note that using autoconf will usually override most of the features, so
using this symbol makes sense mostly when embedding libev.
Defining C<EV_MINIMAL> to C<2> will additionally reduce the core API to
provide a bare-bones event library. See C<ev.h> for details on what parts
of the API are still available, and do not complain if this subset changes
over time.
A typical way to use this symbol is to define it to C<0> (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:
This example set of settings reduces the compiled size of libev from
23.9Kb to 7.7Kb on my GNU/Linux amd64 system (and leaves little
in - there is also an effect on the amount of memory used). With
an intelligent-enough linker (gcc+binutils do this when you use
C<-Wl,--gc-sections -ffunction-sections>) further unused functions might
be left out as well automatically - a binary starting a timer and an I/O
watcher then might come out at only 5Kb.
#define EV_FEATURES 0
#define EV_MULTIPLICITY 1
#define EV_USE_POLL 1
#define EV_CHILD_ENABLE 1
#define EV_ASYNC_ENABLE 1
// tuning and API changes
#define EV_MINIMAL 2
#define EV_MULTIPLICITY 0
#define EV_MINPRI 0
#define EV_MAXPRI 0
The actual value is a bitset, it can be a combination of the following
values:
// OS-specific backends
#define EV_USE_INOTIFY 0
#define EV_USE_EVENTFD 0
#define EV_USE_SIGNALFD 0
#define EV_USE_REALTIME 0
#define EV_USE_MONOTONIC 0
#define EV_USE_CLOCK_SYSCALL 0
=over 4
// disable all backends except select
#define EV_USE_POLL 0
#define EV_USE_PORT 0
#define EV_USE_KQUEUE 0
#define EV_USE_EPOLL 0
=item C<1> - faster/larger code
// disable all watcher types that cna be disabled
#define EV_STAT_ENABLE 0
#define EV_PERIODIC_ENABLE 0
#define EV_IDLE_ENABLE 0
#define EV_CHECK_ENABLE 0
#define EV_PREPARE_ENABLE 0
#define EV_FORK_ENABLE 0
#define EV_SIGNAL_ENABLE 0
#define EV_CHILD_ENABLE 0
#define EV_ASYNC_ENABLE 0
#define EV_EMBED_ENABLE 0
Use larger code to speed up some operations.
Currently this is used to override some inlining decisions (enlarging the roughly
30% code size on amd64.
Also disables C<assert>'s in the code, unless you define C<NDEBUG>
explicitly to C<0>.
Use of compiler flags such as C<-Os> with gcc that optimise for size are
recommended when disabling this feature.
=item C<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 codesize
and can additionally have an effect on the size of data structures at
runtime.
=item C<4> - full API configuration
This enables priorities (sets C<EV_MAXPRI>=2 and C<EV_MINPRI>=-2), and
enables multiplicity (C<EV_MULTIPLICITY>=1).
It also enables a lot of the "lesser used" core API functions. See C<ev.h>
for details on which parts of the API are still available without this
feature, and do not complain if this subset changes over time.
=item C<8> - 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
C<EV_watchertype_ENABLE> to C<1> instead.
=item C<16> - enable all backends
This enables all backends - without this feature, you need to enable at
least one backend manually (C<EV_USE_SELECT> is a good choice).
=item C<32> - enable OS-specific "helper" APIs
Enable inotify, eventfd, signalfd and similar OS-specific helper APIs by
default.
=back
Compiling with C<gcc -Os -DEV_STANDALONE -DEV_USE_EPOLL=1 -DEV_FEATURES=0>
reduces the compiled size of libev from 24.7Kb to 6.5Kb on my GNU/Linux
amd64 system, while still giving you I/O watchers, timers and monotonic
clock support.
With an intelligent-enough linker (gcc+binutils are intelligent enough
when you use C<-Wl,--gc-sections -ffunction-sections>) 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.
=item EV_AVOID_STDIO
@ -3968,17 +3994,17 @@ statically allocates some 12-24 bytes per signal number.
=item EV_PID_HASHSIZE
C<ev_child> watchers use a small hash table to distribute workload by
pid. The default size is C<16> (or C<1> with C<EV_MINIMAL>), usually more
than enough. If you need to manage thousands of children you might want to
increase this value (I<must> be a power of two).
pid. The default size is C<16> (or C<1> with C<EV_FEATURES> disabled),
usually more than enough. If you need to manage thousands of children you
might want to increase this value (I<must> be a power of two).
=item EV_INOTIFY_HASHSIZE
C<ev_stat> watchers use a small hash table to distribute workload by
inotify watch id. The default size is C<16> (or C<1> with C<EV_MINIMAL>),
usually more than enough. If you need to manage thousands of C<ev_stat>
watchers you might want to increase this value (I<must> be a power of
two).
inotify watch id. The default size is C<16> (or C<1> with C<EV_FEATURES>
disabled), usually more than enough. If you need to manage thousands of
C<ev_stat> watchers you might want to increase this value (I<must> be a
power of two).
=item EV_USE_4HEAP
@ -3987,8 +4013,8 @@ timer and periodics heaps, libev uses a 4-heap when this symbol is defined
to C<1>. The 4-heap uses more complicated (longer) code but has noticeably
faster performance with many (thousands) of watchers.
The default is C<1> unless C<EV_MINIMAL> is set in which case it is C<0>
(disabled).
The default is C<1>, unless C<EV_FEATURES> overrides it, in which case it
will be C<0>.
=item EV_HEAP_CACHE_AT
@ -3999,8 +4025,8 @@ 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.
The default is C<1> unless C<EV_MINIMAL> is set in which case it is C<0>
(disabled).
The default is C<1>, unless C<EV_FEATURES> overrides it, in which case it
will be C<0>.
=item EV_VERIFY
@ -4012,8 +4038,8 @@ called once per loop, which can slow down libev. If set to C<3>, then the
verification code will be called very frequently, which will slow down
libev considerably.
The default is C<1>, unless C<EV_MINIMAL> is set, in which case it will be
C<0>.
The default is C<1>, unless C<EV_FEATURES> overrides it, in which case it
will be C<0>.
=item EV_COMMON
@ -4081,15 +4107,9 @@ file.
The usage in rxvt-unicode is simpler. It has a F<ev_cpp.h> header file
that everybody includes and which overrides some configure choices:
#define EV_MINIMAL 1
#define EV_USE_POLL 0
#define EV_MULTIPLICITY 0
#define EV_PERIODIC_ENABLE 0
#define EV_STAT_ENABLE 0
#define EV_FORK_ENABLE 0
#define EV_FEATURES 0
#define EV_USE_SELECT 1
#define EV_CONFIG_H <config.h>
#define EV_MINPRI 0
#define EV_MAXPRI 0
#include "ev++.h"