!EV_MULTIPLICITY.
- implement ev_loop_depth.
- do not compile in any priority code when EV_MAXPRI == EV_MINPRI.
+ - support EV_MINIMAL==2 for a reduced API.
3.6 Tue Apr 28 02:49:30 CEST 2009
- multiple timers becoming ready within an event loop iteration
#endif
}
- unsigned int count () const throw ()
- {
- return ev_loop_count (EV_AX);
- }
-
unsigned int backend () const throw ()
{
return ev_backend (EV_AX);
ev_unref (EV_AX);
}
+#if EV_MINIMAL < 2
+ unsigned int count () const throw ()
+ {
+ return ev_loop_count (EV_AX);
+ }
+
+ unsigned int depth () const throw ()
+ {
+ return ev_loop_depth (EV_AX);
+ }
+
void set_io_collect_interval (tstamp interval) throw ()
{
ev_set_io_collect_interval (EV_AX_ interval);
{
ev_set_timeout_collect_interval (EV_AX_ interval);
}
+#endif
// function callback
void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw ()
#endif
+#if EV_MINIMAL < 2
+# define EV_SUSPEND_CB if (expect_false (suspend_cb)) suspend_cb (EV_A)
+# define EV_RESUME_CB if (expect_false (resume_cb )) resume_cb (EV_A)
+# define EV_INVOKE_PENDING invoke_cb (EV_A)
+#else
+# define EV_SUSPEND_CB (void)0
+# define EV_RESUME_CB (void)0
+# define EV_INVOKE_PENDING ev_invoke_pending (EV_A)
+#endif
+
/*****************************************************************************/
#ifndef EV_HAVE_EV_TIME
return backend;
}
+#if EV_MINIMAL < 2
unsigned int
ev_loop_count (EV_P)
{
timeout_blocktime = interval;
}
+void
+ev_set_userdata (EV_P_ void *data)
+{
+ userdata = data;
+}
+
+void *
+ev_userdata (EV_P)
+{
+ return userdata;
+}
+
+void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P))
+{
+ invoke_cb = invoke_pending_cb;
+}
+
+void ev_set_blocking_cb (EV_P_ void (*suspend_cb_)(EV_P), void (*resume_cb_)(EV_P))
+{
+ suspend_cb = suspend_cb_;
+ resume_cb = resume_cb_;
+}
+#endif
+
/* initialise a loop structure, must be zero-initialised */
static void noinline
loop_init (EV_P_ unsigned int flags)
mn_now = get_clock ();
now_floor = mn_now;
rtmn_diff = ev_rt_now - mn_now;
+#if EV_MINIMAL < 2
invoke_cb = ev_invoke_pending;
+#endif
io_blocktime = 0.;
timeout_blocktime = 0.;
{
postfork = 1; /* must be in line with ev_default_fork */
}
+#endif /* multiplicity */
#if EV_VERIFY
static void noinline
}
#endif
+#if EV_MINIMAL < 2
void
ev_loop_verify (EV_P)
{
# endif
#endif
}
-
-#endif /* multiplicity */
+#endif
#if EV_MULTIPLICITY
struct ev_loop *
EV_CB_INVOKE ((W)w, revents);
}
-void
+void noinline
ev_invoke_pending (EV_P)
{
int pri;
void
ev_loop (EV_P_ int flags)
{
+#if EV_MINIMAL < 2
++loop_depth;
+#endif
loop_done = EVUNLOOP_CANCEL;
- invoke_cb (EV_A); /* in case we recurse, ensure ordering stays nice and clean */
+ EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */
do
{
if (forkcnt)
{
queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
- invoke_cb (EV_A);
+ EV_INVOKE_PENDING;
}
#endif
if (expect_false (preparecnt))
{
queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
- invoke_cb (EV_A);
+ EV_INVOKE_PENDING;
}
/* we might have forked, so reify kernel state if necessary */
}
}
+#if EV_MINIMAL < 2
++loop_count;
+#endif
backend_poll (EV_A_ waittime);
/* update ev_rt_now, do magic */
if (expect_false (checkcnt))
queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
- invoke_cb (EV_A);
+ EV_INVOKE_PENDING;
}
while (expect_true (
activecnt
if (loop_done == EVUNLOOP_ONE)
loop_done = EVUNLOOP_CANCEL;
+#if EV_MINIMAL < 2
--loop_depth;
+#endif
}
void
/* you can actually call it at any time, anywhere :) */
void ev_default_fork (void);
-unsigned int ev_backend (EV_P); /* backend in use by loop */
-unsigned int ev_loop_count (EV_P); /* number of loop iterations */
-unsigned int ev_loop_depth (EV_P); /* #ev_loop enters - #ev_loop leaves */
-void ev_loop_verify (EV_P); /* abort if loop data corrupted */
+unsigned int ev_backend (EV_P); /* backend in use by loop */
-void ev_now_update (EV_P); /* update event loop time */
-void ev_invoke_pending (EV_P); /* invoke all pending watchers */
+void ev_now_update (EV_P); /* update event loop time */
#if EV_WALK_ENABLE
/* walk (almost) all watchers in the loop of a given type, invoking the */
void ev_loop (EV_P_ int flags);
void ev_unloop (EV_P_ int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */
-void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
-void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
-
/*
* ref/unref can be used to add or remove a refcount on the mainloop. every watcher
- * keeps one reference. if you have a long-runing watcher you never unregister that
+ * keeps one reference. if you have a long-running watcher you never unregister that
* should not keep ev_loop from running, unref() after starting, and ref() before stopping.
*/
void ev_ref (EV_P);
void ev_unref (EV_P);
+/*
+ * convenience function, wait for a single event, without registering an event watcher
+ * if timeout is < 0, do wait indefinitely
+ */
+void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg);
+
+# if EV_MINIMAL < 2
+unsigned int ev_loop_count (EV_P); /* number of loop iterations */
+unsigned int ev_loop_depth (EV_P); /* #ev_loop enters - #ev_loop leaves */
+void ev_loop_verify (EV_P); /* abort if loop data corrupted */
+
+void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
+void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
+
+/*
+ * a single void * can be attached to each loop. this is intended
+ * to aid the invoke_pending/blocking callbacks.
+ */
+void ev_set_userdata (EV_P_ void *data);
+void *ev_userdata (EV_P);
+
+/*
+ * hooks to overide how and when libev invokes callbacks,
+ * and hooks that wrap the actual eventloop blocking call.
+ */
+void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P));
+void ev_set_blocking_cb (EV_P_ void (*suspend_cb_)(EV_P), void (*resume_cb_)(EV_P));
+
+void ev_invoke_pending (EV_P); /* invoke all pending watchers */
+
/*
* stop/start the timer handling.
*/
void ev_suspend (EV_P);
void ev_resume (EV_P);
+#endif
-/*
- * convenience function, wait for a single event, without registering an event watcher
- * if timeout is < 0, do wait indefinitely
- */
-void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg);
#endif
/* these may evaluate ev multiple times, and the other arguments at most once */
You can save even more by disabling watcher types you do not need and
setting C<EV_MAXPRI> == C<EV_MINPRI>.
+Defining C<EV_MINIMAL> to C<2> will additionally reduce the core API to
+provide a bare-bones event library. See C<ev.h> for details on what parts
+of the API are still available, and do not complain if this subset changes
+over time.
+
=item EV_PID_HASHSIZE
C<ev_child> watchers use a small hash table to distribute workload by
int i;
int eventcnt;
- if (expect_false (suspend_cb)) suspend_cb (EV_A);
+ EV_SUSPEND_CB;
eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.));
- if (expect_false (resume_cb)) resume_cb (EV_A);
+ EV_RESUME_CB;
if (expect_false (eventcnt < 0))
{
int res, i;
struct timespec ts;
+ EV_SUSPEND_CB;
+
/* need to resize so there is enough space for errors */
if (kqueue_changecnt > kqueue_eventmax)
{
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
}
- if (expect_false (suspend_cb)) suspend_cb (EV_A);
ts.tv_sec = (time_t)timeout;
ts.tv_nsec = (long)((timeout - (ev_tstamp)ts.tv_sec) * 1e9);
res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts);
- if (expect_false (resume_cb)) resume_cb (EV_A);
kqueue_changecnt = 0;
+ EV_RESUME_CB;
+
if (expect_false (res < 0))
{
if (errno != EINTR)
struct pollfd *p;
int res;
- if (expect_false (suspend_cb)) suspend_cb (EV_A);
+ EV_SUSPEND_CB;
res = poll (polls, pollcnt, (int)ceil (timeout * 1000.));
- if (expect_false (resume_cb)) resume_cb (EV_A);
+ EV_RESUME_CB;
if (expect_false (res < 0))
{
struct timespec ts;
uint_t nget = 1;
- if (expect_false (suspend_cb)) suspend_cb (EV_A);
+ EV_SUSPEND_CB;
ts.tv_sec = (time_t)timeout;
ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9;
res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
- if (expect_false (resume_cb)) resume_cb (EV_A);
+ EV_RESUME_CB;
if (res == -1)
{
int res;
int fd_setsize;
- if (expect_false (suspend_cb)) suspend_cb (EV_A);
+ EV_SUSPEND_CB;
tv.tv_sec = (long)timeout;
tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
#else
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
#endif
- if (expect_false (resume_cb)) resume_cb (EV_A);
+ EV_RESUME_CB;
if (expect_false (res < 0))
{
VARx(int, backend)
VARx(int, activecnt) /* total number of active events ("refcount") */
-VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */
-VARx(unsigned int, loop_depth) /* #ev_loop enters - #ev_loop leaves */
VARx(char, loop_done) /* signal by ev_unloop */
VARx(int, backend_fd)
VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
#endif
+#if EV_MINIMAL < 2
+VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */
+VARx(unsigned int, loop_depth) /* #ev_loop enters - #ev_loop leaves */
+
VARx(void *, userdata)
+#endif
+
+#if EV_MINIMAL < 2
VAR (suspend_cb, void (*suspend_cb)(EV_P))
VAR (resume_cb , void (*resume_cb) (EV_P))
VAR (invoke_cb , void (*invoke_cb) (EV_P))
+#endif
#undef VARx