summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <root>2007-11-24 07:14:26 +0000
committerroot <root>2007-11-24 07:14:26 +0000
commite47953f244654c540fd11cdce71f46c6dd5a7b64 (patch)
treec02b83d7ec3ab3d1e07d747c53657f4d695cee27
parent5cf190b99b58aa331248add4a0ac5d7b6cec5ecb (diff)
enhance documentation, also typedef all watcher types (doh, can't do this for ev_loop :()
-rw-r--r--ev.3122
-rw-r--r--ev.c118
-rw-r--r--ev.h103
-rw-r--r--ev.html125
-rw-r--r--ev.pod123
5 files changed, 436 insertions, 155 deletions
diff --git a/ev.3 b/ev.3
index 0b1cfd4..ba07a61 100644
--- a/ev.3
+++ b/ev.3
@@ -647,12 +647,7 @@ 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 set macro.
-.PP
-You can check whether an event is active by calling the \f(CW\*(C`ev_is_active
-(watcher *)\*(C'\fR macro. To see whether an event is outstanding (but the
-callback for it has not been called yet) you can use the \f(CW\*(C`ev_is_pending
-(watcher *)\*(C'\fR macro.
+reinitialise it or call its \f(CW\*(C`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
@@ -720,6 +715,75 @@ 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 multithreaded
programs, though, so beware.
+.Sh "\s-1SUMMARY\s0 \s-1OF\s0 \s-1GENERIC\s0 \s-1WATCHER\s0 \s-1FUNCTIONS\s0"
+.IX Subsection "SUMMARY OF GENERIC WATCHER FUNCTIONS"
+In the following description, \f(CW\*(C`TYPE\*(C'\fR stands for the watcher type,
+e.g. \f(CW\*(C`timer\*(C'\fR for \f(CW\*(C`ev_timer\*(C'\fR watchers and \f(CW\*(C`io\*(C'\fR for \f(CW\*(C`ev_io\*(C'\fR watchers.
+.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 callbakc is always of type \f(CW\*(C`void (*)(ev_loop *loop, ev_TYPE *watcher,
+int revents)\*(C'\fR.
+.ie n .IP """ev_TYPE_set"" (ev_TYPE *, [args])" 4
+.el .IP "\f(CWev_TYPE_set\fR (ev_TYPE *, [args])" 4
+.IX Item "ev_TYPE_set (ev_TYPE *, [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.
+.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 convinience 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 convinient method to initialise
+a watcher. The same limitations apply, of course.
+.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.
+.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 again (if active) and clears the pending
+status. It is possible that stopped watchers are pending (for example,
+non-repeating timers are being stopped when they become pending), but
+\&\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) and you must make sure the watcher is available to
+libev (e.g. you cnanot \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_cb_set (ev_TYPE *watcher, callback)" 4
+.IX Item "ev_cb_set (ev_TYPE *watcher, callback)"
+Change the callback. You can change the callback at virtually any time
+(modulo threads).
.Sh "\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 member \f(CW\*(C`void *data\*(C'\fR that you can change
@@ -1207,7 +1271,9 @@ Example: *TODO*.
.el .Sh "\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.
+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.
@@ -1226,6 +1292,14 @@ 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 (you could also start an idle watcher to give the embedded
+loop strictly lower priority for example). You can also set the callback
+to \f(CW0\fR, in which case the embed watcher will automatically execute the
+embedded loop sweep.
+.PP
As long as the watcher is started it will automatically handle events. The
callback will be invoked whenever some events have been handled. You can
set the callback to \f(CW0\fR to avoid having to specify one if you are not
@@ -1269,13 +1343,22 @@ create it, and if that fails, use the normal loop for everything:
\& else
\& loop_lo = loop_hi;
.Ve
-.IP "ev_embed_init (ev_embed *, callback, struct ev_loop *loop)" 4
-.IX Item "ev_embed_init (ev_embed *, callback, struct ev_loop *loop)"
+.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 *, callback, struct ev_loop *loop)" 4
-.IX Item "ev_embed_set (ev_embed *, callback, struct ev_loop *loop)"
+.IP "ev_embed_set (ev_embed *, callback, struct ev_loop *embedded_loop)" 4
+.IX Item "ev_embed_set (ev_embed *, callback, struct ev_loop *embedded_loop)"
.PD
-Configures the watcher to embed the given loop, which must be embeddable.
+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 thta, 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_loop (embedded_loop, EVLOOP_NONBLOCK)\*(C'\fR, but in the most
+apropriate way for embedded loops.
.SH "OTHER FUNCTIONS"
.IX Header "OTHER FUNCTIONS"
There are some other functions of possible interest. Described. Here. Now.
@@ -1314,18 +1397,19 @@ value passed to \f(CW\*(C`ev_once\*(C'\fR:
.Vb 1
\& ev_once (STDIN_FILENO, EV_READ, 10., stdin_ready, 0);
.Ve
-.IP "ev_feed_event (loop, watcher, int events)" 4
-.IX Item "ev_feed_event (loop, watcher, int events)"
+.IP "ev_feed_event (ev_loop *, watcher *, int revents)" 4
+.IX Item "ev_feed_event (ev_loop *, 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).
-.IP "ev_feed_fd_event (loop, int fd, int revents)" 4
-.IX Item "ev_feed_fd_event (loop, int fd, int revents)"
+.IP "ev_feed_fd_event (ev_loop *, int fd, int revents)" 4
+.IX Item "ev_feed_fd_event (ev_loop *, int fd, int revents)"
Feed an event on the given fd, as if a file descriptor backend detected
the given events it.
-.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 occured (loop must be the default loop!).
+.IP "ev_feed_signal_event (ev_loop *loop, int signum)" 4
+.IX Item "ev_feed_signal_event (ev_loop *loop, int signum)"
+Feed an event as if the given signal occured (\f(CW\*(C`loop\*(C'\fR must be the default
+loop!).
.SH "LIBEVENT EMULATION"
.IX Header "LIBEVENT EMULATION"
Libev offers a compatibility emulation layer for libevent. It cannot
diff --git a/ev.c b/ev.c
index d78cc17..e83a1b5 100644
--- a/ev.c
+++ b/ev.c
@@ -204,9 +204,9 @@ extern "C" {
#define EMPTY0 /* required for microsofts broken pseudo-c compiler */
#define EMPTY2(a,b) /* used to suppress some warnings */
-typedef struct ev_watcher *W;
-typedef struct ev_watcher_list *WL;
-typedef struct ev_watcher_time *WT;
+typedef ev_watcher *W;
+typedef ev_watcher_list *WL;
+typedef ev_watcher_time *WT;
static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
@@ -399,9 +399,6 @@ ev_feed_event (EV_P_ void *w, int revents)
return;
}
- if (expect_false (!w_->cb))
- return;
-
w_->pending = ++pendingcnt [ABSPRI (w_)];
array_needsize (ANPENDING, pendings [ABSPRI (w_)], pendingmax [ABSPRI (w_)], pendingcnt [ABSPRI (w_)], EMPTY2);
pendings [ABSPRI (w_)][w_->pending - 1].w = w_;
@@ -421,9 +418,9 @@ inline void
fd_event (EV_P_ int fd, int revents)
{
ANFD *anfd = anfds + fd;
- struct ev_io *w;
+ ev_io *w;
- for (w = (struct ev_io *)anfd->head; w; w = (struct ev_io *)((WL)w)->next)
+ for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)
{
int ev = w->events & revents;
@@ -449,11 +446,11 @@ fd_reify (EV_P)
{
int fd = fdchanges [i];
ANFD *anfd = anfds + fd;
- struct ev_io *w;
+ ev_io *w;
int events = 0;
- for (w = (struct ev_io *)anfd->head; w; w = (struct ev_io *)((WL)w)->next)
+ for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)
events |= w->events;
#if EV_SELECT_IS_WINSOCKET
@@ -490,9 +487,9 @@ fd_change (EV_P_ int fd)
static void
fd_kill (EV_P_ int fd)
{
- struct ev_io *w;
+ ev_io *w;
- while ((w = (struct ev_io *)anfds [fd].head))
+ while ((w = (ev_io *)anfds [fd].head))
{
ev_io_stop (EV_A_ w);
ev_feed_event (EV_A_ (W)w, EV_ERROR | EV_READ | EV_WRITE);
@@ -613,7 +610,7 @@ static int signalmax;
static int sigpipe [2];
static sig_atomic_t volatile gotsig;
-static struct ev_io sigev;
+static ev_io sigev;
static void
signals_init (ANSIG *base, int count)
@@ -666,7 +663,7 @@ ev_feed_signal_event (EV_P_ int signum)
}
static void
-sigcb (EV_P_ struct ev_io *iow, int revents)
+sigcb (EV_P_ ev_io *iow, int revents)
{
int signum;
@@ -703,22 +700,22 @@ siginit (EV_P)
/*****************************************************************************/
-static struct ev_child *childs [PID_HASHSIZE];
+static ev_child *childs [PID_HASHSIZE];
#ifndef _WIN32
-static struct ev_signal childev;
+static ev_signal childev;
#ifndef WCONTINUED
# define WCONTINUED 0
#endif
static void
-child_reap (EV_P_ struct ev_signal *sw, int chain, int pid, int status)
+child_reap (EV_P_ ev_signal *sw, int chain, int pid, int status)
{
- struct ev_child *w;
+ ev_child *w;
- for (w = (struct ev_child *)childs [chain & (PID_HASHSIZE - 1)]; w; w = (struct ev_child *)((WL)w)->next)
+ for (w = (ev_child *)childs [chain & (PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
if (w->pid == pid || !w->pid)
{
ev_priority (w) = ev_priority (sw); /* need to do it *now* */
@@ -729,7 +726,7 @@ child_reap (EV_P_ struct ev_signal *sw, int chain, int pid, int status)
}
static void
-childcb (EV_P_ struct ev_signal *sw, int revents)
+childcb (EV_P_ ev_signal *sw, int revents)
{
int pid, status;
@@ -1090,7 +1087,7 @@ timers_reify (EV_P)
{
while (timercnt && ((WT)timers [0])->at <= mn_now)
{
- struct ev_timer *w = timers [0];
+ ev_timer *w = timers [0];
assert (("inactive timer on timer heap detected", ev_is_active (w)));
@@ -1118,7 +1115,7 @@ periodics_reify (EV_P)
{
while (periodiccnt && ((WT)periodics [0])->at <= ev_rt_now)
{
- struct ev_periodic *w = periodics [0];
+ ev_periodic *w = periodics [0];
assert (("inactive timer on periodic heap detected", ev_is_active (w)));
@@ -1150,7 +1147,7 @@ periodics_reschedule (EV_P)
/* adjust periodics after time jump */
for (i = 0; i < periodiccnt; ++i)
{
- struct ev_periodic *w = periodics [i];
+ ev_periodic *w = periodics [i];
if (w->reschedule_cb)
((WT)w)->at = w->reschedule_cb (w, ev_rt_now);
@@ -1398,7 +1395,7 @@ ev_stop (EV_P_ W w)
/*****************************************************************************/
void
-ev_io_start (EV_P_ struct ev_io *w)
+ev_io_start (EV_P_ ev_io *w)
{
int fd = w->fd;
@@ -1415,7 +1412,7 @@ ev_io_start (EV_P_ struct ev_io *w)
}
void
-ev_io_stop (EV_P_ struct ev_io *w)
+ev_io_stop (EV_P_ ev_io *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1430,7 +1427,7 @@ ev_io_stop (EV_P_ struct ev_io *w)
}
void
-ev_timer_start (EV_P_ struct ev_timer *w)
+ev_timer_start (EV_P_ ev_timer *w)
{
if (expect_false (ev_is_active (w)))
return;
@@ -1440,7 +1437,7 @@ ev_timer_start (EV_P_ struct ev_timer *w)
assert (("ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
ev_start (EV_A_ (W)w, ++timercnt);
- array_needsize (struct ev_timer *, timers, timermax, timercnt, EMPTY2);
+ array_needsize (ev_timer *, timers, timermax, timercnt, EMPTY2);
timers [timercnt - 1] = w;
upheap ((WT *)timers, timercnt - 1);
@@ -1448,7 +1445,7 @@ ev_timer_start (EV_P_ struct ev_timer *w)
}
void
-ev_timer_stop (EV_P_ struct ev_timer *w)
+ev_timer_stop (EV_P_ ev_timer *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1468,7 +1465,7 @@ ev_timer_stop (EV_P_ struct ev_timer *w)
}
void
-ev_timer_again (EV_P_ struct ev_timer *w)
+ev_timer_again (EV_P_ ev_timer *w)
{
if (ev_is_active (w))
{
@@ -1489,7 +1486,7 @@ ev_timer_again (EV_P_ struct ev_timer *w)
#if EV_PERIODICS
void
-ev_periodic_start (EV_P_ struct ev_periodic *w)
+ev_periodic_start (EV_P_ ev_periodic *w)
{
if (expect_false (ev_is_active (w)))
return;
@@ -1504,7 +1501,7 @@ ev_periodic_start (EV_P_ struct ev_periodic *w)
}
ev_start (EV_A_ (W)w, ++periodiccnt);
- array_needsize (struct ev_periodic *, periodics, periodicmax, periodiccnt, EMPTY2);
+ array_needsize (ev_periodic *, periodics, periodicmax, periodiccnt, EMPTY2);
periodics [periodiccnt - 1] = w;
upheap ((WT *)periodics, periodiccnt - 1);
@@ -1512,7 +1509,7 @@ ev_periodic_start (EV_P_ struct ev_periodic *w)
}
void
-ev_periodic_stop (EV_P_ struct ev_periodic *w)
+ev_periodic_stop (EV_P_ ev_periodic *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1530,7 +1527,7 @@ ev_periodic_stop (EV_P_ struct ev_periodic *w)
}
void
-ev_periodic_again (EV_P_ struct ev_periodic *w)
+ev_periodic_again (EV_P_ ev_periodic *w)
{
/* TODO: use adjustheap and recalculation */
ev_periodic_stop (EV_A_ w);
@@ -1539,18 +1536,18 @@ ev_periodic_again (EV_P_ struct ev_periodic *w)
#endif
void
-ev_idle_start (EV_P_ struct ev_idle *w)
+ev_idle_start (EV_P_ ev_idle *w)
{
if (expect_false (ev_is_active (w)))
return;
ev_start (EV_A_ (W)w, ++idlecnt);
- array_needsize (struct ev_idle *, idles, idlemax, idlecnt, EMPTY2);
+ array_needsize (ev_idle *, idles, idlemax, idlecnt, EMPTY2);
idles [idlecnt - 1] = w;
}
void
-ev_idle_stop (EV_P_ struct ev_idle *w)
+ev_idle_stop (EV_P_ ev_idle *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1561,18 +1558,18 @@ ev_idle_stop (EV_P_ struct ev_idle *w)
}
void
-ev_prepare_start (EV_P_ struct ev_prepare *w)
+ev_prepare_start (EV_P_ ev_prepare *w)
{
if (expect_false (ev_is_active (w)))
return;
ev_start (EV_A_ (W)w, ++preparecnt);
- array_needsize (struct ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
+ array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
prepares [preparecnt - 1] = w;
}
void
-ev_prepare_stop (EV_P_ struct ev_prepare *w)
+ev_prepare_stop (EV_P_ ev_prepare *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1583,18 +1580,18 @@ ev_prepare_stop (EV_P_ struct ev_prepare *w)
}
void
-ev_check_start (EV_P_ struct ev_check *w)
+ev_check_start (EV_P_ ev_check *w)
{
if (expect_false (ev_is_active (w)))
return;
ev_start (EV_A_ (W)w, ++checkcnt);
- array_needsize (struct ev_check *, checks, checkmax, checkcnt, EMPTY2);
+ array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
checks [checkcnt - 1] = w;
}
void
-ev_check_stop (EV_P_ struct ev_check *w)
+ev_check_stop (EV_P_ ev_check *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1609,7 +1606,7 @@ ev_check_stop (EV_P_ struct ev_check *w)
#endif
void
-ev_signal_start (EV_P_ struct ev_signal *w)
+ev_signal_start (EV_P_ ev_signal *w)
{
#if EV_MULTIPLICITY
assert (("signal watchers are only supported in the default loop", loop == ev_default_loop_ptr));
@@ -1638,7 +1635,7 @@ ev_signal_start (EV_P_ struct ev_signal *w)
}
void
-ev_signal_stop (EV_P_ struct ev_signal *w)
+ev_signal_stop (EV_P_ ev_signal *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1652,7 +1649,7 @@ ev_signal_stop (EV_P_ struct ev_signal *w)
}
void
-ev_child_start (EV_P_ struct ev_child *w)
+ev_child_start (EV_P_ ev_child *w)
{
#if EV_MULTIPLICITY
assert (("child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
@@ -1665,7 +1662,7 @@ ev_child_start (EV_P_ struct ev_child *w)
}
void
-ev_child_stop (EV_P_ struct ev_child *w)
+ev_child_stop (EV_P_ ev_child *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1676,17 +1673,25 @@ ev_child_stop (EV_P_ struct ev_child *w)
}
#if EV_MULTIPLICITY
+void
+ev_embed_loop (EV_P_ ev_embed *w)
+{
+ ev_loop (w->loop, EVLOOP_NONBLOCK);
+}
+
static void
-embed_cb (EV_P_ struct ev_io *io, int revents)
+embed_cb (EV_P_ ev_io *io, int revents)
{
- struct ev_embed *w = (struct ev_embed *)(((char *)io) - offsetof (struct ev_embed, io));
+ ev_embed *w = (ev_embed *)(((char *)io) - offsetof (ev_embed, io));
- ev_feed_event (EV_A_ (W)w, EV_EMBED);
- ev_loop (w->loop, EVLOOP_NONBLOCK);
+ if (ev_cb (w))
+ ev_feed_event (EV_A_ (W)w, EV_EMBED);
+ else
+ ev_embed_loop (loop, w);
}
void
-ev_embed_start (EV_P_ struct ev_embed *w)
+ev_embed_start (EV_P_ ev_embed *w)
{
if (expect_false (ev_is_active (w)))
return;
@@ -1697,12 +1702,13 @@ ev_embed_start (EV_P_ struct ev_embed *w)
ev_io_init (&w->io, embed_cb, backend_fd, EV_READ);
}
+ ev_set_priority (&w->io, ev_priority (w));
ev_io_start (EV_A_ &w->io);
ev_start (EV_A_ (W)w, 1);
}
void
-ev_embed_stop (EV_P_ struct ev_embed *w)
+ev_embed_stop (EV_P_ ev_embed *w)
{
ev_clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
@@ -1717,8 +1723,8 @@ ev_embed_stop (EV_P_ struct ev_embed *w)
struct ev_once
{
- struct ev_io io;
- struct ev_timer to;
+ ev_io io;
+ ev_timer to;
void (*cb)(int revents, void *arg);
void *arg;
};
@@ -1737,13 +1743,13 @@ once_cb (EV_P_ struct ev_once *once, int revents)
}
static void
-once_cb_io (EV_P_ struct ev_io *w, int revents)
+once_cb_io (EV_P_ ev_io *w, int revents)
{
once_cb (EV_A_ (struct ev_once *)(((char *)w) - offsetof (struct ev_once, io)), revents);
}
static void
-once_cb_to (EV_P_ struct ev_timer *w, int revents)
+once_cb_to (EV_P_ ev_timer *w, int revents)
{
once_cb (EV_A_ (struct ev_once *)(((char *)w) - offsetof (struct ev_once, to)), revents);
}
diff --git a/ev.h b/ev.h
index d8fc17a..500eb34 100644
--- a/ev.h
+++ b/ev.h
@@ -127,105 +127,105 @@ struct ev_loop;
ev_tstamp at; /* private */
/* base class, nothing to see here unless you subclass */
-struct ev_watcher
+typedef struct ev_watcher
{
EV_WATCHER (ev_watcher)
-};
+} ev_watcher;
/* base class, nothing to see here unless you subclass */
-struct ev_watcher_list
+typedef struct ev_watcher_list
{
EV_WATCHER_LIST (ev_watcher_list)
-};
+} ev_watcher_list;
/* base class, nothing to see here unless you subclass */
-struct ev_watcher_time
+typedef struct ev_watcher_time
{
EV_WATCHER_TIME (ev_watcher_time)
-};
+} ev_watcher_time;
/* invoked after a specific time, repeatable (based on monotonic clock) */
/* revent EV_TIMEOUT */
-struct ev_timer
+typedef struct ev_timer
{
EV_WATCHER_TIME (ev_timer)
ev_tstamp repeat; /* rw */
-};
+} ev_timer;
/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */
/* revent EV_PERIODIC */
-struct ev_periodic
+typedef struct ev_periodic
{
EV_WATCHER_TIME (ev_periodic)
ev_tstamp interval; /* rw */
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now); /* rw */
-};
+} ev_periodic;
/* invoked when fd is either EV_READable or EV_WRITEable */
/* revent EV_READ, EV_WRITE */
-struct ev_io
+typedef struct ev_io
{
EV_WATCHER_LIST (ev_io)
int fd; /* ro */
int events; /* ro */
-};
+} ev_io;
/* invoked when the given signal has been received */
/* revent EV_SIGNAL */
-struct ev_signal
+typedef struct ev_signal
{
EV_WATCHER_LIST (ev_signal)
int signum; /* ro */
-};
+} ev_signal;
/* invoked when the nothing else needs to be done, keeps the process from blocking */
/* revent EV_IDLE */
-struct ev_idle
+typedef struct ev_idle
{
EV_WATCHER (ev_idle)
-};
+} ev_idle;
/* invoked for each run of the mainloop, just before the blocking call */
/* you can still change events in any way you like */
/* revent EV_PREPARE */
-struct ev_prepare
+typedef struct ev_prepare
{
EV_WATCHER (ev_prepare)
-};
+} ev_prepare;
/* invoked for each run of the mainloop, just after the blocking call */
/* revent EV_CHECK */
-struct ev_check
+typedef struct ev_check
{
EV_WATCHER (ev_check)
-};
+} ev_check;
/* invoked when sigchld is received and waitpid indicates the given pid */
/* revent EV_CHILD */
/* does not support priorities */
-struct ev_child
+typedef struct ev_child
{
EV_WATCHER_LIST (ev_child)
int pid; /* ro */
int rpid; /* rw, holds the received pid */
int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */
-};
+} ev_child;
#if EV_MULTIPLICITY
/* used to embed an event loop inside another */
/* the callback gets invoked when the event loop has handled events, and can be 0 */
-struct ev_embed
+typedef struct ev_embed
{
EV_WATCHER (ev_embed)
- struct ev_io io; /* private */
+ ev_io io; /* private */
struct ev_loop *loop; /* ro */
-};
+} ev_embed;
#endif
/* the presence of this union forces similar struct layout */
@@ -353,9 +353,9 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
/* these may evaluate ev multiple times, and the other arguments at most once */
/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */
#define ev_init(ev,cb_) do { \
- ((struct ev_watcher *)(void *)(ev))->active = \
- ((struct ev_watcher *)(void *)(ev))->pending = \
- ((struct ev_watcher *)(void *)(ev))->priority = 0; \
+ ((ev_watcher *)(void *)(ev))->active = \
+ ((ev_watcher *)(void *)(ev))->pending = \
+ ((ev_watcher *)(void *)(ev))->priority = 0; \
ev_set_cb ((ev), cb_); \
} while (0)
@@ -379,10 +379,10 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
#define ev_child_init(ev,cb,pid) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid)); } while (0)
#define ev_embed_init(ev,cb,loop) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(loop)); } while (0)
-#define ev_is_pending(ev) (0 + ((struct ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
-#define ev_is_active(ev) (0 + ((struct ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
+#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
+#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
-#define ev_priority(ev) ((struct ev_watcher *)(void *)(ev))->priority /* rw */
+#define ev_priority(ev) ((ev_watcher *)(void *)(ev))->priority /* rw */
#define ev_cb(ev) (ev)->cb /* rw */
#define ev_set_priority(ev,pri) ev_priority (ev) = (pri)
@@ -400,41 +400,42 @@ void ev_feed_event (EV_P_ void *w, int revents);
void ev_feed_fd_event (EV_P_ int fd, int revents);
void ev_feed_signal_event (EV_P_ int signum);
-void ev_io_start (EV_P_ struct ev_io *w);
-void ev_io_stop (EV_P_ struct ev_io *w);
+void ev_io_start (EV_P_ ev_io *w);
+void ev_io_stop (EV_P_ ev_io *w);
-void ev_timer_start (EV_P_ struct ev_timer *w);
-void ev_timer_stop (EV_P_ struct ev_timer *w);
+void ev_timer_start (EV_P_ ev_timer *w);
+void ev_timer_stop (EV_P_ ev_timer *w);
/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */
-void ev_timer_again (EV_P_ struct ev_timer *w);
+void ev_timer_again (EV_P_ ev_timer *w);
#if EV_PERIODICS
-void ev_periodic_start (EV_P_ struct ev_periodic *w);
-void ev_periodic_stop (EV_P_ struct ev_periodic *w);
-void ev_periodic_again (EV_P_ struct ev_periodic *w);
+void ev_periodic_start (EV_P_ ev_periodic *w);
+void ev_periodic_stop (EV_P_ ev_periodic *w);
+void ev_periodic_again (EV_P_ ev_periodic *w);
#endif
-void ev_idle_start (EV_P_ struct ev_idle *w);
-void ev_idle_stop (EV_P_ struct ev_idle *w);
+void ev_idle_start (EV_P_ ev_idle *w);
+void ev_idle_stop (EV_P_ ev_idle *w);
-void ev_prepare_start (EV_P_ struct ev_prepare *w);
-void ev_prepare_stop (EV_P_ struct ev_prepare *w);
+void ev_prepare_start (EV_P_ ev_prepare *w);
+void ev_prepare_stop (EV_P_ ev_prepare *w);
-void ev_check_start (EV_P_ struct ev_check *w);
-void ev_check_stop (EV_P_ struct ev_check *w);
+void ev_check_start (EV_P_ ev_check *w);
+void ev_check_stop (EV_P_ ev_check *w);
/* only supported in the default loop */
-void ev_signal_start (EV_P_ struct ev_signal *w);
-void ev_signal_stop (EV_P_ struct ev_signal *w);
+void ev_signal_start (EV_P_ ev_signal *w);
+void ev_signal_stop (EV_P_ ev_signal *w);
/* only supported in the default loop */
-void ev_child_start (EV_P_ struct ev_child *w);
-void ev_child_stop (EV_P_ struct ev_child *w);
+void ev_child_start (EV_P_ ev_child *w);
+void ev_child_stop (EV_P_ ev_child *w);
# if EV_MULTIPLICITY
/* only supported when loop to be embedded is in fact embeddable */
-void ev_embed_start (EV_P_ struct ev_embed *w);
-void ev_embed_stop (EV_P_ struct ev_embed *w);
+void ev_embed_start (EV_P_ ev_embed *w);
+void ev_embed_stop (EV_P_ ev_embed *w);
+void ev_embed_loop (EV_P_ ev_embed *w);
# endif
#endif
diff --git a/ev.html b/ev.html
index 367ea02..2a99b11 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="Sat Nov 24 05:58:35 2007" />
+ <meta name="created" content="Sat Nov 24 08:13:46 2007" />
<meta name="generator" content="Pod::Xhtml 1.57" />
<link rel="stylesheet" href="http://res.tst.eu/pod.css"/></head>
<body>
@@ -23,7 +23,8 @@
<li><a href="#GLOBAL_FUNCTIONS">GLOBAL FUNCTIONS</a></li>
<li><a href="#FUNCTIONS_CONTROLLING_THE_EVENT_LOOP">FUNCTIONS CONTROLLING THE EVENT LOOP</a></li>
<li><a href="#ANATOMY_OF_A_WATCHER">ANATOMY OF A WATCHER</a>
-<ul><li><a href="#ASSOCIATING_CUSTOM_DATA_WITH_A_WATCH">ASSOCIATING CUSTOM DATA WITH A WATCHER</a></li>
+<ul><li><a href="#SUMMARY_OF_GENERIC_WATCHER_FUNCTIONS">SUMMARY OF GENERIC WATCHER FUNCTIONS</a></li>
+<li><a href="#ASSOCIATING_CUSTOM_DATA_WITH_A_WATCH">ASSOCIATING CUSTOM DATA WITH A WATCHER</a></li>
</ul>
</li>
<li><a href="#WATCHER_TYPES">WATCHER TYPES</a>
@@ -537,11 +538,7 @@ with a watcher-specific start function (<code>ev_&lt;type&gt;_start (loop, watch
corresponding stop function (<code>ev_&lt;type&gt;_stop (loop, watcher *)</code>.</p>
<p>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 set macro.</p>
-<p>You can check whether an event is active by calling the <code>ev_is_active
-(watcher *)</code> macro. To see whether an event is outstanding (but the
-callback for it has not been called yet) you can use the <code>ev_is_pending
-(watcher *)</code> macro.</p>
+reinitialise it or call its <code>set</code> macro.</p>
<p>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.</p>
@@ -602,6 +599,84 @@ programs, though, so beware.</p>
</dl>
</div>
+<h2 id="SUMMARY_OF_GENERIC_WATCHER_FUNCTIONS">SUMMARY OF GENERIC WATCHER FUNCTIONS</h2>
+<div id="SUMMARY_OF_GENERIC_WATCHER_FUNCTIONS-2">
+<p>In the following description, <code>TYPE</code> stands for the watcher type,
+e.g. <code>timer</code> for <code>ev_timer</code> watchers and <code>io</code> for <code>ev_io</code> watchers.</p>
+<dl>
+ <dt><code>ev_init</code> (ev_TYPE *watcher, callback)</dt>
+ <dd>
+ <p>This macro initialises the generic portion of a watcher. The contents
+of the watcher object can be arbitrary (so <code>malloc</code> will do). Only
+the generic parts of the watcher are initialised, you <i>need</i> to call
+the type-specific <code>ev_TYPE_set</code> macro afterwards to initialise the
+type-specific parts. For each type there is also a <code>ev_TYPE_init</code> macro
+which rolls both calls into one.</p>
+ <p>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.</p>
+ <p>The callbakc is always of type <code>void (*)(ev_loop *loop, ev_TYPE *watcher,
+int revents)</code>.</p>
+ </dd>
+ <dt><code>ev_TYPE_set</code> (ev_TYPE *, [args])</dt>
+ <dd>
+ <p>This macro initialises the type-specific parts of a watcher. You need to
+call <code>ev_init</code> at least once before you call this macro, but you can
+call <code>ev_TYPE_set</code> 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 <code>ev_init</code> macro).</p>
+ <p>Although some watcher types do not have type-specific arguments
+(e.g. <code>ev_prepare</code>) you still need to call its <code>set</code> macro.</p>
+ </dd>
+ <dt><code>ev_TYPE_init</code> (ev_TYPE *watcher, callback, [args])</dt>
+ <dd>
+ <p>This convinience macro rolls both <code>ev_init</code> and <code>ev_TYPE_set</code> macro
+calls into a single call. This is the most convinient method to initialise
+a watcher. The same limitations apply, of course.</p>
+ </dd>
+ <dt><code>ev_TYPE_start</code> (loop *, ev_TYPE *watcher)</dt>
+ <dd>
+ <p>Starts (activates) the given watcher. Only active watchers will receive
+events. If the watcher is already active nothing will happen.</p>
+ </dd>
+ <dt><code>ev_TYPE_stop</code> (loop *, ev_TYPE *watcher)</dt>
+ <dd>
+ <p>Stops the given watcher again (if active) and clears the pending
+status. It is possible that stopped watchers are pending (for example,
+non-repeating timers are being stopped when they become pending), but
+<code>ev_TYPE_stop</code> 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 <code>ev_TYPE_stop</code> function.</p>
+ </dd>
+ <dt>bool ev_is_active (ev_TYPE *watcher)</dt>
+ <dd>
+ <p>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.</p>
+ </dd>
+ <dt>bool ev_is_pending (ev_TYPE *watcher)</dt>
+ <dd>
+ <p>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
+<code>ev_TYPE_set</code> is safe) and you must make sure the watcher is available to
+libev (e.g. you cnanot <code>free ()</code> it).</p>
+ </dd>
+ <dt>callback = ev_cb (ev_TYPE *watcher)</dt>
+ <dd>
+ <p>Returns the callback currently set on the watcher.</p>
+ </dd>
+ <dt>ev_cb_set (ev_TYPE *watcher, callback)</dt>
+ <dd>
+ <p>Change the callback. You can change the callback at virtually any time
+(modulo threads).</p>
+ </dd>
+</dl>
+
+
+
+
+
+</div>
<h2 id="ASSOCIATING_CUSTOM_DATA_WITH_A_WATCH">ASSOCIATING CUSTOM DATA WITH A WATCHER</h2>
<div id="ASSOCIATING_CUSTOM_DATA_WITH_A_WATCH-2">
<p>Each watcher has, by default, a member <code>void *data</code> that you can change
@@ -1068,7 +1143,9 @@ macros, but using them is utterly, utterly and completely pointless.</p>
<h2 id="code_ev_embed_code_when_one_backend_"><code>ev_embed</code> - when one backend isn't enough</h2>
<div id="code_ev_embed_code_when_one_backend_-2">
<p>This is a rather advanced watcher type that lets you embed one event loop
-into another.</p>
+into another (currently only <code>ev_io</code> 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).</p>
<p>There are primarily two reasons you would want that: work around bugs and
prioritise I/O.</p>
<p>As an example for a bug workaround, the kqueue backend might only support
@@ -1083,6 +1160,13 @@ 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.</p>
+<p>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 <code>ev_embed_sweep (mainloop, watcher)</code> to make a single sweep and invoke
+their callbacks (you could also start an idle watcher to give the embedded
+loop strictly lower priority for example). You can also set the callback
+to <code>0</code>, in which case the embed watcher will automatically execute the
+embedded loop sweep.</p>
<p>As long as the watcher is started it will automatically handle events. The
callback will be invoked whenever some events have been handled. You can
set the callback to <code>0</code> to avoid having to specify one if you are not
@@ -1119,10 +1203,20 @@ create it, and if that fails, use the normal loop for everything:</p>
</pre>
<dl>
- <dt>ev_embed_init (ev_embed *, callback, struct ev_loop *loop)</dt>
- <dt>ev_embed_set (ev_embed *, callback, struct ev_loop *loop)</dt>
+ <dt>ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)</dt>
+ <dt>ev_embed_set (ev_embed *, callback, struct ev_loop *embedded_loop)</dt>
+ <dd>
+ <p>Configures the watcher to embed the given loop, which must be
+embeddable. If the callback is <code>0</code>, then <code>ev_embed_sweep</code> 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 thta, you need to temporarily stop the embed watcher).</p>
+ </dd>
+ <dt>ev_embed_sweep (loop, ev_embed *)</dt>
<dd>
- <p>Configures the watcher to embed the given loop, which must be embeddable.</p>
+ <p>Make a single, non-blocking sweep over the embedded loop. This works
+similarly to <code>ev_loop (embedded_loop, EVLOOP_NONBLOCK)</code>, but in the most
+apropriate way for embedded loops.</p>
</dd>
</dl>
@@ -1165,20 +1259,21 @@ value passed to <code>ev_once</code>:</p>
</pre>
</dd>
- <dt>ev_feed_event (loop, watcher, int events)</dt>
+ <dt>ev_feed_event (ev_loop *, watcher *, int revents)</dt>
<dd>
<p>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).</p>
</dd>
- <dt>ev_feed_fd_event (loop, int fd, int revents)</dt>
+ <dt>ev_feed_fd_event (ev_loop *, int fd, int revents)</dt>
<dd>
<p>Feed an event on the given fd, as if a file descriptor backend detected
the given events it.</p>
</dd>
- <dt>ev_feed_signal_event (loop, int signum)</dt>
+ <dt>ev_feed_signal_event (ev_loop *loop, int signum)</dt>
<dd>
- <p>Feed an event as if the given signal occured (loop must be the default loop!).</p>
+ <p>Feed an event as if the given signal occured (<code>loop</code> must be the default
+loop!).</p>
</dd>
</dl>
diff --git a/ev.pod b/ev.pod
index 3104747..ac54275 100644
--- a/ev.pod
+++ b/ev.pod
@@ -507,12 +507,7 @@ corresponding stop function (C<< ev_<type>_stop (loop, watcher *) >>.
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 set macro.
-
-You can check whether an event is active by calling the C<ev_is_active
-(watcher *)> macro. To see whether an event is outstanding (but the
-callback for it has not been called yet) you can use the C<ev_is_pending
-(watcher *)> macro.
+reinitialise it or call its C<set> macro.
Each and every callback receives the event loop pointer as first, the
registered watcher structure as second, and a bitset of received events as
@@ -579,6 +574,85 @@ programs, though, so beware.
=back
+=head2 SUMMARY OF GENERIC WATCHER FUNCTIONS
+
+In the following description, C<TYPE> stands for the watcher type,
+e.g. C<timer> for C<ev_timer> watchers and C<io> for C<ev_io> watchers.
+
+=over 4
+
+=item C<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 C<malloc> will do). Only
+the generic parts of the watcher are initialised, you I<need> to call
+the type-specific C<ev_TYPE_set> macro afterwards to initialise the
+type-specific parts. For each type there is also a C<ev_TYPE_init> macro
+which rolls both calls into one.
+
+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.
+
+The callbakc is always of type C<void (*)(ev_loop *loop, ev_TYPE *watcher,
+int revents)>.
+
+=item C<ev_TYPE_set> (ev_TYPE *, [args])
+
+This macro initialises the type-specific parts of a watcher. You need to
+call C<ev_init> at least once before you call this macro, but you can
+call C<ev_TYPE_set> 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 C<ev_init> macro).
+
+Although some watcher types do not have type-specific arguments
+(e.g. C<ev_prepare>) you still need to call its C<set> macro.
+
+=item C<ev_TYPE_init> (ev_TYPE *watcher, callback, [args])
+
+This convinience macro rolls both C<ev_init> and C<ev_TYPE_set> macro
+calls into a single call. This is the most convinient method to initialise
+a watcher. The same limitations apply, of course.
+
+=item C<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.
+
+=item C<ev_TYPE_stop> (loop *, ev_TYPE *watcher)
+
+Stops the given watcher again (if active) and clears the pending
+status. It is possible that stopped watchers are pending (for example,
+non-repeating timers are being stopped when they become pending), but
+C<ev_TYPE_stop> 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 C<ev_TYPE_stop> function.
+
+=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.
+
+=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
+C<ev_TYPE_set> is safe) and you must make sure the watcher is available to
+libev (e.g. you cnanot C<free ()> it).
+
+=item callback = ev_cb (ev_TYPE *watcher)
+
+Returns the callback currently set on the watcher.
+
+=item ev_cb_set (ev_TYPE *watcher, callback)
+
+Change the callback. You can change the callback at virtually any time
+(modulo threads).
+
+=back
+
+
=head2 ASSOCIATING CUSTOM DATA WITH A WATCHER
Each watcher has, by default, a member C<void *data> that you can change
@@ -1060,7 +1134,9 @@ Example: *TODO*.
=head2 C<ev_embed> - when one backend isn't enough
This is a rather advanced watcher type that lets you embed one event loop
-into another.
+into another (currently only C<ev_io> 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).
There are primarily two reasons you would want that: work around bugs and
prioritise I/O.
@@ -1079,6 +1155,14 @@ 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.
+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 C<ev_embed_sweep (mainloop, watcher)> to make a single sweep and invoke
+their callbacks (you could also start an idle watcher to give the embedded
+loop strictly lower priority for example). You can also set the callback
+to C<0>, in which case the embed watcher will automatically execute the
+embedded loop sweep.
+
As long as the watcher is started it will automatically handle events. The
callback will be invoked whenever some events have been handled. You can
set the callback to C<0> to avoid having to specify one if you are not
@@ -1119,11 +1203,21 @@ create it, and if that fails, use the normal loop for everything:
=over 4
-=item ev_embed_init (ev_embed *, callback, struct ev_loop *loop)
+=item ev_embed_init (ev_embed *, callback, struct ev_loop *embedded_loop)
+
+=item ev_embed_set (ev_embed *, callback, struct ev_loop *embedded_loop)
+
+Configures the watcher to embed the given loop, which must be
+embeddable. If the callback is C<0>, then C<ev_embed_sweep> 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 thta, you need to temporarily stop the embed watcher).
-=item ev_embed_set (ev_embed *, callback, struct ev_loop *loop)
+=item ev_embed_sweep (loop, ev_embed *)
-Configures the watcher to embed the given loop, which must be embeddable.
+Make a single, non-blocking sweep over the embedded loop. This works
+similarly to C<ev_loop (embedded_loop, EVLOOP_NONBLOCK)>, but in the most
+apropriate way for embedded loops.
=back
@@ -1166,20 +1260,21 @@ value passed to C<ev_once>:
ev_once (STDIN_FILENO, EV_READ, 10., stdin_ready, 0);
-=item ev_feed_event (loop, watcher, int events)
+=item ev_feed_event (ev_loop *, 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).
-=item ev_feed_fd_event (loop, int fd, int revents)
+=item ev_feed_fd_event (ev_loop *, int fd, int revents)
Feed an event on the given fd, as if a file descriptor backend detected
the given events it.
-=item ev_feed_signal_event (loop, int signum)
+=item ev_feed_signal_event (ev_loop *loop, int signum)
-Feed an event as if the given signal occured (loop must be the default loop!).
+Feed an event as if the given signal occured (C<loop> must be the default
+loop!).
=back