mirror of /home/gitosis/repositories/libev.git
enhance documentation, also typedef all watcher types (doh, can't do this for ev_loop :()
parent
c24b26fe30
commit
7821610173
122
ev.3
122
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
|
||||
|
|
120
ev.c
120
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
|
||||
static void
|
||||
embed_cb (EV_P_ struct ev_io *io, int revents)
|
||||
void
|
||||
ev_embed_loop (EV_P_ ev_embed *w)
|
||||
{
|
||||
struct ev_embed *w = (struct ev_embed *)(((char *)io) - offsetof (struct ev_embed, io));
|
||||
|
||||
ev_feed_event (EV_A_ (W)w, EV_EMBED);
|
||||
ev_loop (w->loop, EVLOOP_NONBLOCK);
|
||||
}
|
||||
|
||||
static void
|
||||
embed_cb (EV_P_ ev_io *io, int revents)
|
||||
{
|
||||
ev_embed *w = (ev_embed *)(((char *)io) - offsetof (ev_embed, io));
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
103
ev.h
103
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
|
||||
|
|
125
ev.html
125
ev.html
|
@ -6,7 +6,7 @@
|
|||
<meta name="description" content="Pod documentation for libev" />
|
||||
<meta name="inputfile" content="<standard input>" />
|
||||
<meta name="outputfile" content="<standard output>" />
|
||||
<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_<type>_start (loop, watch
|
|||
corresponding stop function (<code>ev_<type>_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>
|
||||
|
@ -601,6 +598,84 @@ programs, though, so beware.</p>
|
|||
</dd>
|
||||
</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">
|
||||
|
@ -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.</p>
|
||||
<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>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>
|
||||
|
||||
|
|
123
ev.pod
123
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 *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.
|
||||
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_sweep (loop, ev_embed *)
|
||||
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue