summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <root>2007-11-27 10:59:10 +0000
committerroot <root>2007-11-27 10:59:10 +0000
commit2e4f855ad17fd958d1643d2170054734053033fc (patch)
tree45b3c8fa4bf0b781f443aea504b3edc02e6f2fd2
parentba71cf07f3506b8e303130e981d3b5b3e9ea5dc8 (diff)
docs
-rw-r--r--ev++.h5
-rw-r--r--ev.393
-rw-r--r--ev.c37
-rw-r--r--ev.h45
-rw-r--r--ev.html109
-rw-r--r--ev.pod98
-rw-r--r--ev_vars.h6
-rw-r--r--ev_wrap.h3
8 files changed, 378 insertions, 18 deletions
diff --git a/ev++.h b/ev++.h
index 9d0df26..ce18ca0 100644
--- a/ev++.h
+++ b/ev++.h
@@ -52,10 +52,13 @@ namespace ev {
TIMEOUT = EV_TIMEOUT,
PERIODIC = EV_PERIODIC,
SIGNAL = EV_SIGNAL,
+ CHILD = EV_CHILD,
+ STAT = EV_STAT,
IDLE = EV_IDLE,
CHECK = EV_CHECK,
PREPARE = EV_PREPARE,
- CHILD = EV_CHILD,
+ FORK = EV_FORK,
+ EMBED = EV_EMBED,
ERROR = EV_ERROR,
};
diff --git a/ev.3 b/ev.3
index 31d1f6b..01e5c65 100644
--- a/ev.3
+++ b/ev.3
@@ -709,6 +709,15 @@ received events. 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_loop\*(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_ERROR""" 4
.el .IP "\f(CWEV_ERROR\fR" 4
.IX Item "EV_ERROR"
@@ -1615,6 +1624,21 @@ apropriate way for embedded loops.
.IP "struct ev_loop *loop [read\-only]" 4
.IX Item "struct ev_loop *loop [read-only]"
The embedded event loop.
+.ie n .Sh """ev_fork"" \- the audacity to resume the event loop after a fork"
+.el .Sh "\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_default_fork\*(C'\fR or \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.
+.IP "ev_fork_init (ev_signal *, callback)" 4
+.IX Item "ev_fork_init (ev_signal *, 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,
+believe me.
.SH "OTHER FUNCTIONS"
.IX Header "OTHER FUNCTIONS"
There are some other functions of possible interest. Described. Here. Now.
@@ -1794,6 +1818,71 @@ the constructor.
\& io.start (fd, ev::READ);
\& }
.Ve
+.SH "MACRO MAGIC"
+.IX Header "MACRO MAGIC"
+Libev can be compiled with a variety of options, the most fundemantal is
+\&\f(CW\*(C`EV_MULTIPLICITY\*(C'\fR. This option determines wether (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""\fR, \f(CW""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_loop (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""\fR, \f(CW""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);
+.Ve
+.Sp
+.Vb 2
+\& // 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""\fR, \f(CW""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").
+.PP
+Example: Declare and initialise a check watcher, working regardless of
+wether 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);
+\& }
+.Ve
+.PP
+.Vb 4
+\& ev_check check;
+\& ev_check_init (&check, check_cb);
+\& ev_check_start (EV_DEFAULT_ &check);
+\& ev_loop (EV_DEFAULT_ 0);
+.Ve
.SH "EMBEDDING"
.IX Header "EMBEDDING"
Libev can (and often is) directly embedded into host
@@ -2022,6 +2111,10 @@ defined to be \f(CW0\fR, then they are not.
.IX Item "EV_STAT_ENABLE"
If undefined or defined to be \f(CW1\fR, then stat watchers are supported. If
defined to be \f(CW0\fR, then they are not.
+.IP "\s-1EV_FORK_ENABLE\s0" 4
+.IX Item "EV_FORK_ENABLE"
+If undefined or defined to be \f(CW1\fR, then fork watchers are supported. If
+defined to be \f(CW0\fR, then they are not.
.IP "\s-1EV_MINIMAL\s0" 4
.IX Item "EV_MINIMAL"
If you need to shave off some kilobytes of code at the expense of some
diff --git a/ev.c b/ev.c
index 40e2292..bf20d1a 100644
--- a/ev.c
+++ b/ev.c
@@ -1278,6 +1278,14 @@ ev_loop (EV_P_ int flags)
while (activecnt)
{
+ /* we might have forked, so reify kernel state if necessary */
+ if (expect_false (postfork))
+ if (forkcnt)
+ {
+ queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
+ call_pending (EV_A);
+ }
+
/* queue check watchers (and execute them) */
if (expect_false (preparecnt))
{
@@ -1829,6 +1837,35 @@ ev_embed_stop (EV_P_ ev_embed *w)
}
#endif
+#if EV_FORK_ENABLE
+void
+ev_fork_start (EV_P_ ev_fork *w)
+{
+ if (expect_false (ev_is_active (w)))
+ return;
+
+ ev_start (EV_A_ (W)w, ++forkcnt);
+ array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
+ forks [forkcnt - 1] = w;
+}
+
+void
+ev_fork_stop (EV_P_ ev_fork *w)
+{
+ ev_clear_pending (EV_A_ (W)w);
+ if (expect_false (!ev_is_active (w)))
+ return;
+
+ {
+ int active = ((W)w)->active;
+ forks [active - 1] = forks [--forkcnt];
+ ((W)forks [active - 1])->active = active;
+ }
+
+ ev_stop (EV_A_ (W)w);
+}
+#endif
+
/*****************************************************************************/
struct ev_once
diff --git a/ev.h b/ev.h
index 76f7a10..26ffe78 100644
--- a/ev.h
+++ b/ev.h
@@ -56,6 +56,10 @@ typedef double ev_tstamp;
# define EV_STAT_ENABLE 1
#endif
+#ifndef EV_FORK_ENABLE
+# define EV_FORK_ENABLE 1
+#endif
+
#ifndef EV_EMBED_ENABLE
# define EV_EMBED_ENABLE 1
#endif
@@ -73,15 +77,15 @@ struct ev_loop;
# define EV_P_ EV_P,
# define EV_A loop
# define EV_A_ EV_A,
-# define EV_DEFAULT_A ev_default_loop (0)
-# define EV_DEFAULT_A_ EV_DEFAULT_A,
+# define EV_DEFAULT ev_default_loop (0)
+# define EV_DEFAULT_ EV_DEFAULT,
#else
# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_
-# define EV_DEFAULT_A
-# define EV_DEFAULT_A_
+# define EV_DEFAULT
+# define EV_DEFAULT_
# undef EV_EMBED_ENABLE
#endif
@@ -94,12 +98,13 @@ struct ev_loop;
#define EV_TIMEOUT 0x00000100L /* timer timed out */
#define EV_PERIODIC 0x00000200L /* periodic timer timed out */
#define EV_SIGNAL 0x00000400L /* signal was received */
-#define EV_IDLE 0x00000800L /* event loop is idling */
-#define EV_PREPARE 0x00001000L /* event loop about to poll */
-#define EV_CHECK 0x00002000L /* event loop finished poll */
-#define EV_CHILD 0x00004000L /* child/pid had status change */
-#define EV_EMBED 0x00008000L /* embedded event loop needs sweep */
-#define EV_STAT 0x00010000L /* stat data changed */
+#define EV_CHILD 0x00000800L /* child/pid had status change */
+#define EV_STAT 0x00001000L /* stat data changed */
+#define EV_IDLE 0x00002000L /* event loop is idling */
+#define EV_PREPARE 0x00004000L /* event loop about to poll */
+#define EV_CHECK 0x00008000L /* event loop finished poll */
+#define EV_EMBED 0x00010000L /* embedded event loop needs sweep */
+#define EV_FORK 0x00020000L /* event loop resumed in child */
#define EV_ERROR 0x80000000L /* sent when an error occurs */
/* can be used to add custom fields to all watchers, while losing binary compatibility */
@@ -255,6 +260,14 @@ typedef struct ev_check
EV_WATCHER (ev_check)
} ev_check;
+#if EV_FORK_ENABLE
+/* the callback gets invoked before check in the child process when a fork was detected */
+typedef struct ev_fork
+{
+ EV_WATCHER (ev_fork)
+} ev_fork;
+#endif
+
#if EV_EMBED_ENABLE
/* used to embed an event loop inside another */
/* the callback gets invoked when the event loop has handled events, and can be 0 */
@@ -276,6 +289,7 @@ union ev_any_watcher
struct ev_io io;
struct ev_timer timer;
struct ev_periodic periodic;
+ struct ev_signal signal;
struct ev_child child;
#if EV_STAT_ENABLE
struct ev_stat stat;
@@ -283,7 +297,9 @@ union ev_any_watcher
struct ev_idle idle;
struct ev_prepare prepare;
struct ev_check check;
- struct ev_signal signal;
+#if EV_FORK_ENABLE
+ struct ev_fork fork;
+#endif
#if EV_EMBED_ENABLE
struct ev_embed embed;
#endif
@@ -413,6 +429,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_embed_set(ev,loop_) do { (ev)->loop = (loop_); } while (0)
+#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
@@ -424,6 +441,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
#define ev_embed_init(ev,cb,loop) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(loop)); } while (0)
+#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
@@ -483,6 +501,11 @@ void ev_prepare_stop (EV_P_ ev_prepare *w);
void ev_check_start (EV_P_ ev_check *w);
void ev_check_stop (EV_P_ ev_check *w);
+# if EV_FORK_ENABLE
+void ev_fork_start (EV_P_ ev_fork *w);
+void ev_fork_stop (EV_P_ ev_fork *w);
+# endif
+
# if EV_EMBED_ENABLE
/* only supported when loop to be embedded is in fact embeddable */
void ev_embed_start (EV_P_ ev_embed *w);
diff --git a/ev.html b/ev.html
index f643a6b..c5df51e 100644
--- a/ev.html
+++ b/ev.html
@@ -6,7 +6,7 @@
<meta name="description" content="Pod documentation for libev" />
<meta name="inputfile" content="&lt;standard input&gt;" />
<meta name="outputfile" content="&lt;standard output&gt;" />
- <meta name="created" content="Tue Nov 27 09:20:40 2007" />
+ <meta name="created" content="Tue Nov 27 11:59:06 2007" />
<meta name="generator" content="Pod::Xhtml 1.57" />
<link rel="stylesheet" href="http://res.tst.eu/pod.css"/></head>
<body>
@@ -37,11 +37,13 @@
<li><a href="#code_ev_idle_code_when_you_ve_got_no"><code>ev_idle</code> - when you've got nothing better to do...</a></li>
<li><a href="#code_ev_prepare_code_and_code_ev_che"><code>ev_prepare</code> and <code>ev_check</code> - customise your event loop!</a></li>
<li><a href="#code_ev_embed_code_when_one_backend_"><code>ev_embed</code> - when one backend isn't enough...</a></li>
+<li><a href="#code_ev_fork_code_the_audacity_to_re"><code>ev_fork</code> - the audacity to resume the event loop after a fork</a></li>
</ul>
</li>
<li><a href="#OTHER_FUNCTIONS">OTHER FUNCTIONS</a></li>
<li><a href="#LIBEVENT_EMULATION">LIBEVENT EMULATION</a></li>
<li><a href="#C_SUPPORT">C++ SUPPORT</a></li>
+<li><a href="#MACRO_MAGIC">MACRO MAGIC</a></li>
<li><a href="#EMBEDDING">EMBEDDING</a>
<ul><li><a href="#FILESETS">FILESETS</a>
<ul><li><a href="#CORE_EVENT_LOOP">CORE EVENT LOOP</a></li>
@@ -116,10 +118,6 @@ called <code>ev_tstamp</code>, which is what you should use too. It usually alia
to the <code>double</code> type in C, and when you need to do any calculations on
it, you should treat it as such.</p>
-
-
-
-
</div>
<h1 id="GLOBAL_FUNCTIONS">GLOBAL FUNCTIONS</h1><p><a href="#TOP" class="toplink">Top</a></p>
<div id="GLOBAL_FUNCTIONS_CONTENT">
@@ -608,6 +606,15 @@ many watchers as they want, and all of them will be taken into account
(for example, a <code>ev_prepare</code> watcher might start an idle watcher to keep
<code>ev_loop</code> from blocking).</p>
</dd>
+ <dt><code>EV_EMBED</code></dt>
+ <dd>
+ <p>The embedded event loop specified in the <code>ev_embed</code> watcher needs attention.</p>
+ </dd>
+ <dt><code>EV_FORK</code></dt>
+ <dd>
+ <p>The event loop has been resumed in the child process after fork (see
+<code>ev_fork</code>).</p>
+ </dd>
<dt><code>EV_ERROR</code></dt>
<dd>
<p>An unspecified error has occured, the watcher has been stopped. This might
@@ -1482,6 +1489,29 @@ apropriate way for embedded loops.</p>
</div>
+<h2 id="code_ev_fork_code_the_audacity_to_re"><code>ev_fork</code> - the audacity to resume the event loop after a fork</h2>
+<div id="code_ev_fork_code_the_audacity_to_re-2">
+<p>Fork watchers are called when a <code>fork ()</code> was detected (usually because
+whoever is a good citizen cared to tell libev about it by calling
+<code>ev_default_fork</code> or <code>ev_loop_fork</code>). The invocation is done before the
+event loop blocks next and before <code>ev_check</code> watchers are being called,
+and only in the child after the fork. If whoever good citizen calling
+<code>ev_default_fork</code> cheats and calls it in the wrong process, the fork
+handlers will be invoked, too, of course.</p>
+<dl>
+ <dt>ev_fork_init (ev_signal *, callback)</dt>
+ <dd>
+ <p>Initialises and configures the fork watcher - it has no parameters of any
+kind. There is a <code>ev_fork_set</code> macro, but using it is utterly pointless,
+believe me.</p>
+ </dd>
+</dl>
+
+
+
+
+
+</div>
<h1 id="OTHER_FUNCTIONS">OTHER FUNCTIONS</h1><p><a href="#TOP" class="toplink">Top</a></p>
<div id="OTHER_FUNCTIONS_CONTENT">
<p>There are some other functions of possible interest. Described. Here. Now.</p>
@@ -1658,6 +1688,70 @@ the constructor.</p>
io.start (fd, ev::READ);
}
+
+
+
+</pre>
+
+</div>
+<h1 id="MACRO_MAGIC">MACRO MAGIC</h1><p><a href="#TOP" class="toplink">Top</a></p>
+<div id="MACRO_MAGIC_CONTENT">
+<p>Libev can be compiled with a variety of options, the most fundemantal is
+<code>EV_MULTIPLICITY</code>. This option determines wether (most) functions and
+callbacks have an initial <code>struct ev_loop *</code> argument.</p>
+<p>To make it easier to write programs that cope with either variant, the
+following macros are defined:</p>
+<dl>
+ <dt><code>EV_A</code>, <code>EV_A_</code></dt>
+ <dd>
+ <p>This provides the loop <i>argument</i> for functions, if one is required (&quot;ev
+loop argument&quot;). The <code>EV_A</code> form is used when this is the sole argument,
+<code>EV_A_</code> is used when other arguments are following. Example:</p>
+<pre> ev_unref (EV_A);
+ ev_timer_add (EV_A_ watcher);
+ ev_loop (EV_A_ 0);
+
+</pre>
+ <p>It assumes the variable <code>loop</code> of type <code>struct ev_loop *</code> is in scope,
+which is often provided by the following macro.</p>
+ </dd>
+ <dt><code>EV_P</code>, <code>EV_P_</code></dt>
+ <dd>
+ <p>This provides the loop <i>parameter</i> for functions, if one is required (&quot;ev
+loop parameter&quot;). The <code>EV_P</code> form is used when this is the sole parameter,
+<code>EV_P_</code> is used when other parameters are following. Example:</p>
+<pre> // 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)
+
+</pre>
+ <p>It declares a parameter <code>loop</code> of type <code>struct ev_loop *</code>, quite
+suitable for use with <code>EV_A</code>.</p>
+ </dd>
+ <dt><code>EV_DEFAULT</code>, <code>EV_DEFAULT_</code></dt>
+ <dd>
+ <p>Similar to the other two macros, this gives you the value of the default
+loop, if multiple loops are supported (&quot;ev loop default&quot;).</p>
+ </dd>
+</dl>
+<p>Example: Declare and initialise a check watcher, working regardless of
+wether multiple loops are supported or not.</p>
+<pre> static void
+ check_cb (EV_P_ ev_timer *w, int revents)
+ {
+ ev_check_stop (EV_A_ w);
+ }
+
+ ev_check check;
+ ev_check_init (&amp;check, check_cb);
+ ev_check_start (EV_DEFAULT_ &amp;check);
+ ev_loop (EV_DEFAULT_ 0);
+
+
+
+
</pre>
</div>
@@ -1893,6 +1987,11 @@ defined to be <code>0</code>, then they are not.</p>
<p>If undefined or defined to be <code>1</code>, then stat watchers are supported. If
defined to be <code>0</code>, then they are not.</p>
</dd>
+ <dt>EV_FORK_ENABLE</dt>
+ <dd>
+ <p>If undefined or defined to be <code>1</code>, then fork watchers are supported. If
+defined to be <code>0</code>, then they are not.</p>
+ </dd>
<dt>EV_MINIMAL</dt>
<dd>
<p>If you need to shave off some kilobytes of code at the expense of some
diff --git a/ev.pod b/ev.pod
index 687a53d..17484ff 100644
--- a/ev.pod
+++ b/ev.pod
@@ -50,7 +50,6 @@ called C<ev_tstamp>, which is what you should use too. It usually aliases
to the C<double> type in C, and when you need to do any calculations on
it, you should treat it as such.
-
=head1 GLOBAL FUNCTIONS
These functions can be called anytime, even before initialising the
@@ -567,6 +566,15 @@ many watchers as they want, and all of them will be taken into account
(for example, a C<ev_prepare> watcher might start an idle watcher to keep
C<ev_loop> from blocking).
+=item C<EV_EMBED>
+
+The embedded event loop specified in the C<ev_embed> watcher needs attention.
+
+=item C<EV_FORK>
+
+The event loop has been resumed in the child process after fork (see
+C<ev_fork>).
+
=item C<EV_ERROR>
An unspecified error has occured, the watcher has been stopped. This might
@@ -1472,6 +1480,27 @@ The embedded event loop.
=back
+=head2 C<ev_fork> - the audacity to resume the event loop after a fork
+
+Fork watchers are called when a C<fork ()> was detected (usually because
+whoever is a good citizen cared to tell libev about it by calling
+C<ev_default_fork> or C<ev_loop_fork>). The invocation is done before the
+event loop blocks next and before C<ev_check> watchers are being called,
+and only in the child after the fork. If whoever good citizen calling
+C<ev_default_fork> cheats and calls it in the wrong process, the fork
+handlers will be invoked, too, of course.
+
+=over 4
+
+=item ev_fork_init (ev_signal *, callback)
+
+Initialises and configures the fork watcher - it has no parameters of any
+kind. There is a C<ev_fork_set> macro, but using it is utterly pointless,
+believe me.
+
+=back
+
+
=head1 OTHER FUNCTIONS
There are some other functions of possible interest. Described. Here. Now.
@@ -1666,6 +1695,68 @@ the constructor.
io.start (fd, ev::READ);
}
+
+=head1 MACRO MAGIC
+
+Libev can be compiled with a variety of options, the most fundemantal is
+C<EV_MULTIPLICITY>. This option determines wether (most) functions and
+callbacks have an initial C<struct ev_loop *> argument.
+
+To make it easier to write programs that cope with either variant, the
+following macros are defined:
+
+=over 4
+
+=item C<EV_A>, C<EV_A_>
+
+This provides the loop I<argument> for functions, if one is required ("ev
+loop argument"). The C<EV_A> form is used when this is the sole argument,
+C<EV_A_> is used when other arguments are following. Example:
+
+ ev_unref (EV_A);
+ ev_timer_add (EV_A_ watcher);
+ ev_loop (EV_A_ 0);
+
+It assumes the variable C<loop> of type C<struct ev_loop *> is in scope,
+which is often provided by the following macro.
+
+=item C<EV_P>, C<EV_P_>
+
+This provides the loop I<parameter> for functions, if one is required ("ev
+loop parameter"). The C<EV_P> form is used when this is the sole parameter,
+C<EV_P_> is used when other parameters are following. Example:
+
+ // 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)
+
+It declares a parameter C<loop> of type C<struct ev_loop *>, quite
+suitable for use with C<EV_A>.
+
+=item C<EV_DEFAULT>, C<EV_DEFAULT_>
+
+Similar to the other two macros, this gives you the value of the default
+loop, if multiple loops are supported ("ev loop default").
+
+=back
+
+Example: Declare and initialise a check watcher, working regardless of
+wether multiple loops are supported or not.
+
+ 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_loop (EV_DEFAULT_ 0);
+
+
=head1 EMBEDDING
Libev can (and often is) directly embedded into host
@@ -1897,6 +1988,11 @@ defined to be C<0>, then they are not.
If undefined or defined to be C<1>, then stat watchers are supported. If
defined to be C<0>, then they are not.
+=item EV_FORK_ENABLE
+
+If undefined or defined to be C<1>, then fork watchers are supported. If
+defined to be C<0>, then they are not.
+
=item EV_MINIMAL
If you need to shave off some kilobytes of code at the expense of some
diff --git a/ev_vars.h b/ev_vars.h
index 080ba55..c1bfaa4 100644
--- a/ev_vars.h
+++ b/ev_vars.h
@@ -80,5 +80,11 @@ VARx(struct ev_check **, checks)
VARx(int, checkmax)
VARx(int, checkcnt)
+#if EV_FORK_ENABLE || EV_GENWRAP
+VARx(struct ev_fork **, forks)
+VARx(int, forkmax)
+VARx(int, forkcnt)
+#endif
+
#undef VARx
diff --git a/ev_wrap.h b/ev_wrap.h
index 55ef2cd..37812ca 100644
--- a/ev_wrap.h
+++ b/ev_wrap.h
@@ -51,3 +51,6 @@
#define checks ((loop)->checks)
#define checkmax ((loop)->checkmax)
#define checkcnt ((loop)->checkcnt)
+#define forks ((loop)->forks)
+#define forkmax ((loop)->forkmax)
+#define forkcnt ((loop)->forkcnt)