From 2e4f855ad17fd958d1643d2170054734053033fc Mon Sep 17 00:00:00 2001
From: root
Date: Tue, 27 Nov 2007 10:59:10 +0000
Subject: docs
---
ev++.h | 5 ++-
ev.3 | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ev.c | 37 +++++++++++++++++++++
ev.h | 45 +++++++++++++++++++-------
ev.html | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
ev.pod | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
ev_vars.h | 6 ++++
ev_wrap.h | 3 ++
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 @@
-
+
@@ -37,11 +37,13 @@
@@ -116,10 +118,6 @@ called ev_tstamp, which is what you should use too. It usually alia
to the double type in C, and when you need to do any calculations on
it, you should treat it as such.
@@ -607,6 +605,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 ev_prepare watcher might start an idle watcher to keep
ev_loop from blocking).
+
+
EV_EMBED
+
+
The embedded event loop specified in the ev_embed watcher needs attention.
+
+
EV_FORK
+
+
The event loop has been resumed in the child process after fork (see
+ev_fork).
EV_ERROR
@@ -1481,6 +1488,29 @@ apropriate way for embedded loops.
+
+
ev_fork - the audacity to resume the event loop after a fork
+
+
Fork watchers are called when a fork () was detected (usually because
+whoever is a good citizen cared to tell libev about it by calling
+ev_default_fork or ev_loop_fork). The invocation is done before the
+event loop blocks next and before ev_check watchers are being called,
+and only in the child after the fork. If whoever good citizen calling
+ev_default_fork cheats and calls it in the wrong process, the fork
+handlers will be invoked, too, of course.
+
+
ev_fork_init (ev_signal *, callback)
+
+
Initialises and configures the fork watcher - it has no parameters of any
+kind. There is a ev_fork_set macro, but using it is utterly pointless,
+believe me.
Libev can be compiled with a variety of options, the most fundemantal is
+EV_MULTIPLICITY. This option determines wether (most) functions and
+callbacks have an initial struct ev_loop * argument.
+
To make it easier to write programs that cope with either variant, the
+following macros are defined:
+
+
EV_A, EV_A_
+
+
This provides the loop argument for functions, if one is required ("ev
+loop argument"). The EV_A form is used when this is the sole argument,
+EV_A_ is used when other arguments are following. Example:
It assumes the variable loop of type struct ev_loop * is in scope,
+which is often provided by the following macro.
+
+
EV_P, EV_P_
+
+
This provides the loop parameter for functions, if one is required ("ev
+loop parameter"). The EV_P form is used when this is the sole parameter,
+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 loop of type struct ev_loop *, quite
+suitable for use with EV_A.
+
+
EV_DEFAULT, 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").
+
+
+
Example: Declare and initialise a check watcher, working regardless of
+wether multiple loops are supported or not.
@@ -1891,6 +1985,11 @@ defined to be 0, then they are not.
EV_STAT_ENABLE
If undefined or defined to be 1, then stat watchers are supported. If
+defined to be 0, then they are not.
+
+
EV_FORK_ENABLE
+
+
If undefined or defined to be 1, then fork watchers are supported. If
defined to be 0, then they are not.
EV_MINIMAL
diff --git a/ev.pod b/ev.pod
index 687a53d..17484ff 100644
--- a/ev.pod
+++ b/ev.pod
@@ -50,7 +50,6 @@ called C, which is what you should use too. It usually aliases
to the C 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 watcher might start an idle watcher to keep
C from blocking).
+=item C
+
+The embedded event loop specified in the C watcher needs attention.
+
+=item C
+
+The event loop has been resumed in the child process after fork (see
+C).
+
=item C
An unspecified error has occured, the watcher has been stopped. This might
@@ -1472,6 +1480,27 @@ The embedded event loop.
=back
+=head2 C - the audacity to resume the event loop after a fork
+
+Fork watchers are called when a C was detected (usually because
+whoever is a good citizen cared to tell libev about it by calling
+C or C). The invocation is done before the
+event loop blocks next and before C watchers are being called,
+and only in the child after the fork. If whoever good citizen calling
+C 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 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. This option determines wether (most) functions and
+callbacks have an initial C argument.
+
+To make it easier to write programs that cope with either variant, the
+following macros are defined:
+
+=over 4
+
+=item C, C
+
+This provides the loop I for functions, if one is required ("ev
+loop argument"). The C form is used when this is the sole argument,
+C 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 of type C is in scope,
+which is often provided by the following macro.
+
+=item C, C
+
+This provides the loop I for functions, if one is required ("ev
+loop parameter"). The C form is used when this is the sole parameter,
+C 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 of type C, quite
+suitable for use with C.
+
+=item C, C
+
+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)
--
cgit v1.2.3