commit 0c364c846f4e3be1dfc43e187f4c47091a01231b
Author: Nathaniel McCallum <npmccallum(a)redhat.com>
Date: Fri Jun 17 16:42:36 2011 -0400
make vertoEv completely opaque; rework modules for opaque vertoEv
src/verto-glib.c | 125 ++++++++++++--------------
src/verto-libev.c | 166 +++++++++++++++--------------------
src/verto-libevent.c | 104 ++++++++--------------
src/verto-module.h | 61 +++++++------
src/verto-tevent.c | 155 +++++++++------------------------
src/verto.c | 238 +++++++++++++++++++++++++++++---------------------
src/verto.h | 106 ++++++++++++++++------
7 files changed, 456 insertions(+), 499 deletions(-)
---
diff --git a/src/verto-glib.c b/src/verto-glib.c
index 46282b8..92aa924 100644
--- a/src/verto-glib.c
+++ b/src/verto-glib.c
@@ -22,6 +22,8 @@
* SOFTWARE.
*/
+#include <errno.h>
+
#include <verto-glib.h>
#include <verto-module.h>
@@ -34,7 +36,6 @@ struct glibEvCtx {
};
struct glibEv {
- struct vertoEv ev;
GSource *src;
guint tag;
GIOChannel *chan;
@@ -107,80 +108,69 @@ glib_ctx_break(void *lp)
static gboolean
glib_callback(gpointer data)
{
- struct glibEv *ev = ((struct glibEv*) data);
- if (ev)
- ev->ev.callback(&ev->ev);
+ verto_call(data);
return TRUE;
}
-#define ctx_add(makesrc) \
- struct glibEv *ev = g_new0(struct glibEv, 1); \
- if (!ev) \
- goto error; \
- makesrc; \
- if (!ev->src) \
- goto error; \
- g_source_set_can_recurse(ev->src, FALSE); \
- g_source_set_priority(ev->src, priority_map[priority]); \
- g_source_set_callback(ev->src, glib_callback, ev, NULL); \
- ev->tag = g_source_attach(ev->src, ((struct glibLoop*) lp)->context); \
- if (ev->tag == 0) \
- goto error; \
- return &ev->ev; \
- error: \
- verto_ctx_del(ev); \
- return NULL
-
-#define ctx_add_io(flag) \
- ctx_add( \
- ev->chan = g_io_channel_unix_new(fd); \
- if (!ev->chan) \
- goto error; \
- g_io_channel_set_close_on_unref(ev->chan, FALSE); \
- ev->src = g_io_create_watch(ev->chan, flag) \
- )
-
-static struct vertoEv *
-glib_ctx_add_read(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
-{
- ctx_add_io(G_IO_IN);
-}
-
-static struct vertoEv *
-glib_ctx_add_write(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
+static int
+glib_ctx_add(void *ctx, struct vertoEv *ev)
{
- ctx_add_io(G_IO_OUT);
-}
+ struct glibEv *gev = g_new0(struct glibEv, 1);
+ if (!ev)
+ return ENOMEM;
+
+ switch (verto_get_type(ev)) {
+ case VERTO_EV_TYPE_READ:
+ case VERTO_EV_TYPE_WRITE:
+ gev->chan = g_io_channel_unix_new(verto_get_fd(ev));
+ if (!gev->chan)
+ goto error;
+ g_io_channel_set_close_on_unref(gev->chan, FALSE);
+
+ gev->src = g_io_create_watch(gev->chan,
+ verto_get_type(ev) == VERTO_EV_TYPE_READ
+ ? G_IO_IN
+ : G_IO_OUT);
+ break;
+ case VERTO_EV_TYPE_TIMEOUT:
+ gev->src = g_timeout_source_new(verto_get_interval(ev));
+ break;
+ case VERTO_EV_TYPE_IDLE:
+ gev->src = g_idle_source_new();
+ break;
+ case VERTO_EV_TYPE_CHILD:
+ gev->src = g_child_watch_source_new(verto_get_pid(ev));
+ break;
+ case VERTO_EV_TYPE_SIGNAL:
+#if GLIB_MAJOR_VERSION >= 2
+#if GLIB_MINOR_VERSION >= 29
+ gev->src = g_unix_signal_source_new(verto_get_signal(ev));
+ break;
+#endif /* GLIB_MINOR_VERSION >= 29 */
+#endif /* GLIB_MAJOR_VERSION >= 2 */
+ default:
+ return -1; /* Not supported */
+ }
-static struct vertoEv *
-glib_ctx_add_timeout(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data, time_t interval)
-{
- ctx_add(ev->src = g_timeout_source_new(interval));
-}
-static struct vertoEv *
-glib_ctx_add_idle(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data)
-{
- ctx_add(ev->src = g_idle_source_new());
-}
+ if (!gev->src)
+ goto error;
-static struct vertoEv *
-glib_ctx_add_signal(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int signal)
-{
- ctx_add(ev->src = g_unix_signal_source_new(signal));
-}
+ g_source_set_can_recurse(gev->src, FALSE);
+ g_source_set_priority(gev->src, priority_map[verto_get_priority(ev)]);
+ g_source_set_callback(gev->src, glib_callback, ev, NULL);
+ gev->tag = g_source_attach(gev->src, ((struct glibEvCtx*) ctx)->context);
+ if (gev->tag == 0)
+ goto error;
-static struct vertoEv *
-glib_ctx_add_child(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- pid_t pid)
-{
- ctx_add(ev->src = g_child_watch_source_new(pid));
+ return 0;
+ error:
+ if (gev) {
+ if (gev->chan)
+ g_io_channel_unref(gev->chan);
+ g_free(gev);
+ }
+ return ENOMEM;
}
static void
@@ -205,4 +195,3 @@ verto_convert_glib(GMainContext *mc, GMainLoop *ml)
{
return verto_convert_funcs(&glib_funcs, glib_convert_(mc, ml));
}
-
diff --git a/src/verto-libev.c b/src/verto-libev.c
index 38ea134..11ea7e3 100644
--- a/src/verto-libev.c
+++ b/src/verto-libev.c
@@ -24,15 +24,11 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <verto-libev.h>
#include <verto-module.h>
-struct libevEv {
- struct vertoEv ev;
- void *watcher;
-};
-
static void *
libev_ctx_new()
{
@@ -46,122 +42,106 @@ libev_ctx_default()
}
static void
-libev_ctx_free(void *priv)
+libev_ctx_free(void *ctx)
{
- if (priv != EV_DEFAULT)
- ev_loop_destroy(priv);
+ if (ctx != EV_DEFAULT)
+ ev_loop_destroy(ctx);
}
static void
-libev_ctx_run(void *priv)
+libev_ctx_run(void *ctx)
{
- ev_run(priv, 0);
+ ev_run(ctx, 0);
}
static void
-libev_ctx_run_once(void *priv)
+libev_ctx_run_once(void *ctx)
{
- ev_run(priv, EVRUN_ONCE);
+ ev_run(ctx, EVRUN_ONCE);
}
static void
-libev_ctx_break(void *priv)
+libev_ctx_break(void *ctx)
{
- ev_break(priv, EVBREAK_ONE);
+ ev_break(ctx, EVBREAK_ONE);
}
-#define setuptype(type, ...) \
- struct libevEv *ev = malloc(sizeof(struct libevEv)); \
- if (ev) { \
- memset(ev, 0, sizeof(struct libevEv)); \
- ev->watcher = malloc(sizeof(ev_ ## type)); \
- if (!ev->watcher) goto error; \
- ev_ ## type ## _init((ev_ ## type *) ev->watcher, __VA_ARGS__); \
- ((ev_ ## type *) ev->watcher)->data = ev; \
- ev_ ## type ## _start(priv, ev->watcher); \
- return &ev->ev; \
- } \
- error: \
- free(ev); \
- return NULL
-
-#define setupcb(type) \
- static void type ## _cb (EV_P_ ev_ ## type *w, int revents) { \
- struct libevEv *ev = ((struct libevEv*) w->data); \
- ev->ev.callback(&ev->ev); \
- }
-
-setupcb(io)
-setupcb(idle)
-setupcb(timer)
-setupcb(signal)
-setupcb(child)
-
-static struct vertoEv *
-libev_ctx_add_read(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
-{
- setuptype(io, io_cb, fd, EV_READ);
-}
-
-static struct vertoEv *
-libev_ctx_add_write(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
-{
- setuptype(io, io_cb, fd, EV_WRITE);
-}
-
-static struct vertoEv *
-libev_ctx_add_timeout(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, time_t interval)
-{
- setuptype(timer, timer_cb, ((ev_tstamp) interval) / 1000.0, ((ev_tstamp) interval) / 1000.0);
-}
-
-static struct vertoEv *
-libev_ctx_add_idle(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data)
+static void
+libev_callback(EV_P_ ev_watcher *w, int revents)
{
- setuptype(idle, idle_cb);
+ verto_call(w->data);
}
-static struct vertoEv *
-libev_ctx_add_signal(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int signal)
+#define setuptype(type, priv, ...) \
+ type ## w = malloc(sizeof(ev_ ## type)); \
+ if (!type ## w) \
+ return ENOMEM; \
+ ev_ ## type ## _init(type ## w, (EV_CB(type, (*))) __VA_ARGS__); \
+ type ## w->data = priv; \
+ ev_ ## type ## _start(ctx, type ## w); \
+ verto_set_module_private(ev, type ## w)
+
+static int
+libev_ctx_add(void *ctx, struct vertoEv *ev)
{
- setuptype(signal, signal_cb, signal);
-}
+ ev_io *iow = NULL;
+ ev_timer *timerw = NULL;
+ ev_idle *idlew = NULL;
+ ev_signal *signalw = NULL;
+ ev_child *childw = NULL;
+ ev_tstamp interval;
+
+ switch (verto_get_type(ev)) {
+ case VERTO_EV_TYPE_READ:
+ setuptype(io, ev, libev_callback, verto_get_fd(ev), EV_READ);
+ break;
+ case VERTO_EV_TYPE_WRITE:
+ setuptype(io, ev, libev_callback, verto_get_fd(ev), EV_WRITE);
+ break;
+ case VERTO_EV_TYPE_TIMEOUT:
+ interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0;
+ setuptype(timer, ev, libev_callback, interval, interval);
+ break;
+ case VERTO_EV_TYPE_IDLE:
+ setuptype(idle, ev, libev_callback);
+ break;
+ case VERTO_EV_TYPE_SIGNAL:
+ setuptype(signal, ev, libev_callback, verto_get_signal(ev));
+ break;
+ case VERTO_EV_TYPE_CHILD:
+ setuptype(child, ev, libev_callback, verto_get_pid(ev), 0);
+ break;
+ default:
+ return -1; /* Not supported */
+ }
-static struct vertoEv *
-libev_ctx_add_child(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- pid_t pid)
-{
- setuptype(child, child_cb, pid, 0);
+ return 0;
}
static void
-libev_ctx_del(void *priv, struct vertoEv *ev)
+libev_ctx_del(void *ctx, struct vertoEv *ev)
{
- if (!priv || !ev)
+ void *priv = verto_get_module_private(ev);
+ if (!priv)
return;
- switch (ev->type) {
- case VERTO_EV_TYPE_READ:
- ev_io_stop(priv, ((struct libevEv*) ev)->watcher);
- case VERTO_EV_TYPE_WRITE:
- ev_io_stop(priv, ((struct libevEv*) ev)->watcher);
- case VERTO_EV_TYPE_TIMEOUT:
- ev_timer_stop(priv, ((struct libevEv*) ev)->watcher);
- case VERTO_EV_TYPE_IDLE:
- ev_idle_stop(priv, ((struct libevEv*) ev)->watcher);
- case VERTO_EV_TYPE_SIGNAL:
- ev_signal_stop(priv, ((struct libevEv*) ev)->watcher);
- case VERTO_EV_TYPE_CHILD:
- ev_child_stop(priv, ((struct libevEv*) ev)->watcher);
+ switch (verto_get_type(ev)) {
+ case VERTO_EV_TYPE_READ:
+ case VERTO_EV_TYPE_WRITE:
+ ev_io_stop(ctx, priv);
+ case VERTO_EV_TYPE_TIMEOUT:
+ ev_timer_stop(ctx, priv);
+ case VERTO_EV_TYPE_IDLE:
+ ev_idle_stop(ctx, priv);
+ case VERTO_EV_TYPE_SIGNAL:
+ ev_signal_stop(ctx, priv);
+ case VERTO_EV_TYPE_CHILD:
+ ev_child_stop(ctx, priv);
+ default:
+ break;
}
- free(ev);
+ free(priv);
}
VERTO_MODULE(libev, ev_loop_new);
diff --git a/src/verto-libevent.c b/src/verto-libevent.c
index cee9e8b..089c6e7 100644
--- a/src/verto-libevent.c
+++ b/src/verto-libevent.c
@@ -24,17 +24,13 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <verto-libevent.h>
#include <verto-module.h>
static struct event_base *defctx;
-struct libeventEv {
- struct vertoEv ev;
- struct event *event;
-};
-
static void *
libevent_ctx_new()
{
@@ -77,76 +73,52 @@ libevent_ctx_break(void *priv)
static void
libevent_callback(evutil_socket_t socket, short type, void *data)
{
- struct libeventEv *ev = (struct libeventEv*) data;
- ev->ev.callback(&ev->ev);
-}
-
-#define add_ev(tv, evnew) \
- struct libeventEv *ev = malloc(sizeof(struct libeventEv)); \
- if (ev) { \
- memset(ev, 0, sizeof(struct libeventEv)); \
- ev->event = evnew; \
- if (!ev->event) { \
- free(ev); \
- ev = NULL; \
- } else { \
- event_add(ev->event, tv); \
- } \
- } \
- return &ev->ev
-
-static struct vertoEv *
-libevent_ctx_add_read(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
-{
- add_ev(NULL, event_new(priv, fd, EV_READ | EV_PERSIST, libevent_callback, ev));
+ verto_call(data);
}
-static struct vertoEv *
-libevent_ctx_add_write(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
-{
- add_ev(NULL, event_new(priv, fd, EV_WRITE | EV_PERSIST, libevent_callback, ev));
-}
-
-static struct vertoEv *
-libevent_ctx_add_timeout(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, time_t interval)
+static int
+libevent_ctx_add(void *ctx, struct vertoEv *ev)
{
+ struct event *priv = NULL;
+ struct timeval *timeout = NULL;
struct timeval tv;
- tv.tv_sec = interval / 1000;
- tv.tv_usec = interval % 1000 * 1000;
- add_ev(&tv, event_new(priv, -1, EV_TIMEOUT | EV_PERSIST, libevent_callback, ev));
-}
-static struct vertoEv *
-libevent_ctx_add_idle(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data)
-{
- return NULL;
-}
-
-static struct vertoEv *
-libevent_ctx_add_signal(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int signal)
-{
- add_ev(NULL, event_new(priv, -1, EV_SIGNAL | EV_PERSIST, libevent_callback, ev));
-}
-
-static struct vertoEv *
-libevent_ctx_add_child(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- pid_t pid)
-{
- return NULL;
+ switch (verto_get_type(ev)) {
+ case VERTO_EV_TYPE_READ:
+ priv = event_new(ctx, verto_get_fd(ev), EV_READ | EV_PERSIST, libevent_callback, ev);
+ break;
+ case VERTO_EV_TYPE_WRITE:
+ priv = event_new(ctx, verto_get_fd(ev), EV_WRITE | EV_PERSIST, libevent_callback, ev);
+ break;
+ case VERTO_EV_TYPE_TIMEOUT:
+ timeout = &tv;
+ tv.tv_sec = verto_get_interval(ev) / 1000;
+ tv.tv_usec = verto_get_interval(ev) % 1000 * 1000;
+ priv = event_new(ctx, -1, EV_TIMEOUT | EV_PERSIST, libevent_callback, ev);
+ break;
+ case VERTO_EV_TYPE_SIGNAL:
+ priv = event_new(ctx, verto_get_signal(ev), EV_SIGNAL | EV_PERSIST, libevent_callback, ev);
+ break;
+ case VERTO_EV_TYPE_IDLE:
+ case VERTO_EV_TYPE_CHILD:
+ default:
+ return -1; /* Not supported */
+ }
+
+ if (!priv)
+ return ENOMEM;
+
+ event_add(priv, timeout);
+ verto_set_module_private(ev, priv);
+ return 0;
}
static void
-libevent_ctx_del(void *priv, struct vertoEv *ev)
+libevent_ctx_del(void *ctx, struct vertoEv *ev)
{
- event_del(((struct libeventEv*) ev)->event);
- event_free(((struct libeventEv*) ev)->event);
- free(ev);
+ struct event *priv = (struct event *) verto_get_module_private(ev);
+ event_del(priv);
+ event_free(priv);
}
VERTO_MODULE(libevent, event_base_init);
diff --git a/src/verto-module.h b/src/verto-module.h
index d9b811b..8ae534f 100644
--- a/src/verto-module.h
+++ b/src/verto-module.h
@@ -39,12 +39,7 @@
name ## _ctx_run, \
name ## _ctx_run_once, \
name ## _ctx_break, \
- name ## _ctx_add_read, \
- name ## _ctx_add_write, \
- name ## _ctx_add_timeout, \
- name ## _ctx_add_idle, \
- name ## _ctx_add_signal, \
- name ## _ctx_add_child, \
+ name ## _ctx_add, \
name ## _ctx_del \
}; \
struct vertoEvCtx *verto_new_ ## name() { \
@@ -61,7 +56,7 @@
verto_default_ ## name, \
};
-typedef struct vertoEvCtx *(*vertoEvCtxConstructor)(void);
+typedef struct vertoEvCtx *(*vertoEvCtxConstructor)();
struct vertoModule {
unsigned int vers;
@@ -74,28 +69,12 @@ struct vertoModule {
struct vertoEvCtxFuncs {
void *(*ctx_new)();
void *(*ctx_default)();
- void (*ctx_free)(void *lp);
- void (*ctx_run)(void *lp);
- void (*ctx_run_once)(void *lp);
- void (*ctx_break)(void *lp);
- struct vertoEv *(*ctx_add_read)(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- int fd);
- struct vertoEv *(*ctx_add_write)(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- int fd);
- struct vertoEv *(*ctx_add_timeout)(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- time_t interval);
- struct vertoEv *(*ctx_add_idle)(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data);
- struct vertoEv *(*ctx_add_signal)(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- int signal);
- struct vertoEv *(*ctx_add_child)(void *lp, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- pid_t pid);
- void (*ctx_del)(void *lp, struct vertoEv *ev);
+ void (*ctx_free)(void *ctx);
+ void (*ctx_run)(void *ctx);
+ void (*ctx_run_once)(void *ctx);
+ void (*ctx_break)(void *ctx);
+ int (*ctx_add)(void *ctx, struct vertoEv *ev);
+ void (*ctx_del)(void *ctx, struct vertoEv *ev);
};
/**
@@ -135,4 +114,28 @@ verto_default_funcs(const struct vertoEvCtxFuncs *funcs);
struct vertoEvCtx *
verto_convert_funcs(const struct vertoEvCtxFuncs *funcs, void *ctx_private);
+/**
+ * Gets the module private stored in this vertoEv.
+ *
+ * This function is only used for module writers to store a context in the
+ * vertoEv for later use.
+ *
+ * @see verto_set_module_private()
+ * @return The module private.
+ */
+void *
+verto_get_module_private(const struct vertoEv *ev);
+
+/**
+ * Sets the module private stored in this vertoEv.
+ *
+ * This function is only used for module writers to store a context in the
+ * vertoEv for later use.
+ *
+ * @see verto_get_module_private()
+ * @return The previous module private.
+ */
+void *
+verto_set_module_private(struct vertoEv *ev, void *priv);
+
#endif /* VERTO_MODULE_H_ */
diff --git a/src/verto-tevent.c b/src/verto-tevent.c
index b4bf9d8..8c36fa0 100644
--- a/src/verto-tevent.c
+++ b/src/verto-tevent.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <verto-tevent.h>
#include <verto-module.h>
@@ -38,15 +39,6 @@ struct teventEvCtx {
bool exit;
};
-struct teventEv {
- struct vertoEv ev;
- union {
- struct tevent_fd *fd;
- struct tevent_signal *signal;
- struct tevent_timer *timer;
- } tev;
-};
-
static void *
tevent_ctx_new()
{
@@ -96,123 +88,60 @@ tevent_ctx_break(void *priv)
texit(priv) = true;
}
-static void
-fd_cb(struct tevent_context *c, struct tevent_fd *fd, uint16_t fl, void *data)
-{
- struct teventEv *tev = (struct teventEv *) data;
- tev->ev.callback(&tev->ev);
-}
-
-static struct vertoEv *
-tevent_ctx_add_read(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
-{
- struct teventEv *ev = talloc_zero(tctx(priv), struct teventEv);
- if (ev) {
- ev->tev.fd = tevent_add_fd(tctx(priv), tctx(priv), fd,
- TEVENT_FD_READ, fd_cb, ev);
- if (!ev->tev.fd) {
- talloc_free(ev);
- ev = NULL;
- }
+#define definecb(type, ...) \
+ static void tevent_ ## type ## _cb(struct tevent_context *c, \
+ struct tevent_ ## type *e, \
+ __VA_ARGS__, void *data) { \
+ verto_call(data); \
}
- return &ev->ev;
-}
-static struct vertoEv *
-tevent_ctx_add_write(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int fd)
-{
- struct teventEv *ev = talloc_zero(tctx(priv), struct teventEv);
- if (ev) {
- ev->tev.fd = tevent_add_fd(tctx(priv), tctx(priv), fd,
- TEVENT_FD_WRITE, fd_cb, ev);
- if (!ev->tev.fd) {
- talloc_free(ev);
- ev = NULL;
- }
- }
- return &ev->ev;
-}
+definecb(fd, uint16_t fl)
+definecb(timer, struct timeval ct)
+definecb(signal, int signum, int count, void *siginfo)
-static void
-timer_cb(struct tevent_context *c, struct tevent_timer *te,
- struct timeval ct, void *data)
+static int
+tevent_ctx_add(void *ctx, struct vertoEv *ev)
{
struct timeval tv;
- struct teventEv *tev = (struct teventEv *) data;
-
- tev->ev.callback(&tev->ev);
-
- /* Make the event recur */
- tv.tv_sec = tev->ev.data.interval / 1000;
- tv.tv_usec = tev->ev.data.interval % 1000 * 1000;
- tev->tev.timer = tevent_add_timer(c, c, tv, timer_cb, tev);
-}
-
-static struct vertoEv *
-tevent_ctx_add_timeout(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, time_t interval)
-{
- struct timeval tv;
-
- struct teventEv *ev = talloc_zero(tctx(priv), struct teventEv);
- if (ev) {
- tv.tv_sec = interval / 1000;
- tv.tv_usec = interval % 1000 * 1000;
- ev->tev.timer = tevent_add_timer(tctx(priv), tctx(priv),
- tv, timer_cb, ev);
- if (!ev->tev.timer) {
- talloc_free(ev);
- ev = NULL;
- }
+ void *priv = NULL;
+
+ switch (verto_get_type(ev)) {
+ case VERTO_EV_TYPE_READ:
+ priv = tevent_add_fd(tctx(priv), tctx(priv), verto_get_fd(ev),
+ TEVENT_FD_READ, tevent_fd_cb, ev);
+ break;
+ case VERTO_EV_TYPE_WRITE:
+ priv = tevent_add_fd(tctx(priv), tctx(priv), verto_get_fd(ev),
+ TEVENT_FD_WRITE, tevent_fd_cb, ev);
+ break;
+ case VERTO_EV_TYPE_TIMEOUT:
+ tv.tv_sec = verto_get_interval(ev) / 1000;
+ tv.tv_usec = verto_get_interval(ev) % 1000 * 1000;
+ priv = tevent_add_timer(tctx(priv), tctx(priv), tv,
+ tevent_timer_cb, ev);
+ break;
+ case VERTO_EV_TYPE_SIGNAL:
+ priv = tevent_add_signal(tctx(priv), tctx(priv),
+ verto_get_signal(ev), 0,
+ tevent_signal_cb, ev);
+ break;
+ case VERTO_EV_TYPE_IDLE:
+ case VERTO_EV_TYPE_CHILD:
+ default:
+ return -1; /* Not supported */
}
- return &ev->ev;
-}
-static struct vertoEv *
-tevent_ctx_add_idle(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data)
-{
- return NULL; /* Not currently supported */
-}
+ if (!priv)
+ return ENOMEM;
-static void
-signal_cb(struct tevent_context *c, struct tevent_signal *se,
- int signum, int count, void *siginfo, void *data)
-{
- struct teventEv *tev = (struct teventEv *) data;
- tev->ev.callback(&tev->ev);
-}
-
-static struct vertoEv *
-tevent_ctx_add_signal(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data, int signal)
-{
- struct teventEv *ev = talloc_zero(tctx(priv), struct teventEv);
- if (ev) {
- ev->tev.signal = tevent_add_signal(tctx(priv), tctx(priv), signal,
- 0, signal_cb, ev);
- if (!ev->tev.signal) {
- talloc_free(ev);
- ev = NULL;
- }
- }
- return &ev->ev;
-}
-
-static struct vertoEv *
-tevent_ctx_add_child(void *priv, enum vertoEvPriority priority,
- vertoCallback callback, void *data,
- pid_t pid)
-{
- return NULL; /* Not currently supported */
+ verto_set_module_private(ev, priv);
+ return 0;
}
static void
tevent_ctx_del(void *priv, struct vertoEv *ev)
{
- talloc_free(ev);
+ talloc_free(verto_set_module_private(ev, NULL));
}
VERTO_MODULE(tevent, g_main_context_default);
diff --git a/src/verto.c b/src/verto.c
index 7763eac..f404749 100644
--- a/src/verto.c
+++ b/src/verto.c
@@ -43,10 +43,25 @@
struct vertoEvCtx {
void *dll;
- void *priv;
+ void *modpriv;
struct vertoEvCtxFuncs funcs;
};
+struct vertoEv {
+ struct vertoEvCtx *ctx;
+ enum vertoEvType type;
+ enum vertoEvPriority priority;
+ vertoCallback callback;
+ void *priv;
+ void *modpriv;
+ union {
+ int fd;
+ int signal;
+ time_t interval;
+ pid_t pid;
+ } option;
+};
+
static inline bool
do_load_file(const char *filename, bool reqsym, void **dll,
struct vertoModule **module)
@@ -172,7 +187,8 @@ load_module(const char *impl, void **dll, struct vertoModule **module)
if (!success)
#endif /* DEFAULT_LIBRARY */
/* Attempt to load any plugin (we're desperate) */
- success = do_load_dir(dname, prefix, suffix, false, dll, module);
+ success = do_load_dir(dname, prefix, suffix, false, dll,
+ module);
}
}
@@ -189,7 +205,7 @@ verto_new(const char *impl)
{
void *dll = NULL;
struct vertoModule *module = NULL;
- struct vertoEvCtx *ctx;
+ struct vertoEvCtx *ctx = NULL;
if (!load_module(impl, &dll, &module))
return NULL;
@@ -208,7 +224,7 @@ verto_default(const char *impl)
{
void *dll = NULL;
struct vertoModule *module = NULL;
- struct vertoEvCtx *ctx;
+ struct vertoEvCtx *ctx = NULL;
if (!load_module(impl, &dll, &module))
return NULL;
@@ -229,7 +245,7 @@ verto_free(struct vertoEvCtx *ctx)
return;
if (ctx->dll)
dlclose(ctx->dll);
- ctx->funcs.ctx_free(ctx->priv);
+ ctx->funcs.ctx_free(ctx->modpriv);
free(ctx);
}
@@ -238,7 +254,7 @@ verto_run(struct vertoEvCtx *ctx)
{
if (!ctx)
return;
- ctx->funcs.ctx_run(ctx->priv);
+ ctx->funcs.ctx_run(ctx->modpriv);
}
void
@@ -246,7 +262,7 @@ verto_run_once(struct vertoEvCtx *ctx)
{
if (!ctx)
return;
- ctx->funcs.ctx_run_once(ctx->priv);
+ ctx->funcs.ctx_run_once(ctx->modpriv);
}
void
@@ -254,141 +270,149 @@ verto_break(struct vertoEvCtx *ctx)
{
if (!ctx)
return;
- ctx->funcs.ctx_break(ctx->priv);
+ ctx->funcs.ctx_break(ctx->modpriv);
}
-struct vertoEv *
-verto_add_read(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
- vertoCallback callback, void *priv, int fd)
+static inline struct vertoEv *
+make_ev(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
+ vertoCallback callback, void *priv, enum vertoEvType type)
{
struct vertoEv *ev = NULL;
- if (!ctx || !callback || fd < 0)
+ if (!ctx || !callback)
return NULL;
+
priority = priority < _VERTO_EV_PRIORITY_MAX + 1
? priority
: VERTO_EV_PRIORITY_DEFAULT;
- ev = ctx->funcs.ctx_add_read(ctx->priv, priority, callback, priv, fd);
+
+ ev = malloc(sizeof(struct vertoEv));
if (ev) {
- ev->ctx = ctx;
- ev->type = VERTO_EV_TYPE_READ;
- ev->priority = priority;
- ev->callback = callback;
- ev->priv = priv;
- ev->data.fd = fd;
+ ev->ctx = ctx;
+ ev->type = type;
+ ev->priority = priority;
+ ev->callback = callback;
+ ev->priv = priv;
}
+
return ev;
}
+#define doadd(set, type) \
+ struct vertoEv *ev = make_ev(ctx, priority, callback, priv, type); \
+ if (ev) { \
+ set; \
+ if (ctx->funcs.ctx_add(ctx->modpriv, ev) != 0) { \
+ free(ev); \
+ return NULL; \
+ } \
+ } \
+ return ev;
+
+struct vertoEv *
+verto_add_read(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
+ vertoCallback callback, void *priv, int fd)
+{
+ if (fd < 0)
+ return NULL;
+ doadd(ev->option.fd = fd, VERTO_EV_TYPE_READ);
+}
+
+
struct vertoEv *
verto_add_write(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
vertoCallback callback, void *priv, int fd)
{
- struct vertoEv *ev = NULL;
-
- if (!ctx || !callback || fd < 0)
+ if (fd < 0)
return NULL;
- priority = priority < _VERTO_EV_PRIORITY_MAX + 1
- ? priority
- : VERTO_EV_PRIORITY_DEFAULT;
- ev = ctx->funcs.ctx_add_write(ctx->priv, priority, callback, priv, fd);
- if (ev) {
- ev->ctx = ctx;
- ev->type = VERTO_EV_TYPE_WRITE;
- ev->priority = priority;
- ev->callback = callback;
- ev->priv = priv;
- ev->data.fd = fd;
- }
- return ev;
+ doadd(ev->option.fd = fd, VERTO_EV_TYPE_WRITE);
}
struct vertoEv *
verto_add_timeout(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
vertoCallback callback, void *priv, time_t interval)
{
- struct vertoEv *ev = NULL;
-
- if (!ctx || !callback)
- return NULL;
- priority = priority < _VERTO_EV_PRIORITY_MAX + 1
- ? priority
- : VERTO_EV_PRIORITY_DEFAULT;
- ev = ctx->funcs.ctx_add_timeout(ctx->priv, priority, callback, priv, interval);
- if (ev) {
- ev->ctx = ctx;
- ev->type = VERTO_EV_TYPE_TIMEOUT;
- ev->priority = priority;
- ev->callback = callback;
- ev->priv = priv;
- ev->data.interval = interval;
- }
- return ev;
+ doadd(ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT);
}
struct vertoEv *
verto_add_idle(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
vertoCallback callback, void *priv)
{
- struct vertoEv *ev = NULL;
-
- if (!ctx || !callback)
- return NULL;
- priority = priority < _VERTO_EV_PRIORITY_MAX + 1
- ? priority
- : VERTO_EV_PRIORITY_DEFAULT;
- ev = ctx->funcs.ctx_add_idle(ctx->priv, priority, callback, priv);
- if (ev) {
- ev->ctx = ctx;
- ev->type = VERTO_EV_TYPE_IDLE;
- ev->priority = priority;
- ev->callback = callback;
- ev->priv = priv;
- }
- return ev;
+ doadd(, VERTO_EV_TYPE_IDLE);
}
struct vertoEv *
verto_add_signal(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
vertoCallback callback, void *priv, int signal)
{
- struct vertoEv *ev = NULL;
-
- if (!ctx || !callback || signal < 0)
+ if (signal < 0)
return NULL;
- priority = priority < _VERTO_EV_PRIORITY_MAX + 1
- ? priority
- : VERTO_EV_PRIORITY_DEFAULT;
- ev = ctx->funcs.ctx_add_signal(ctx->priv, priority, callback, priv, signal);
- if (ev) {
- ev->ctx = ctx;
- ev->type = VERTO_EV_TYPE_SIGNAL;
- ev->priority = priority;
- ev->callback = callback;
- ev->priv = priv;
- ev->data.signal = signal;
- }
- return ev;
+ doadd(ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL);
}
struct vertoEv *
verto_add_child(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
- vertoCallback callback, void *priv, pid_t child)
+ vertoCallback callback, void *priv, pid_t pid)
{
- struct vertoEv *ev = NULL;
-
- if (!ctx || !callback)
+ if (pid < 1)
return NULL;
- ev = ctx->funcs.ctx_add_child(ctx->priv, priority, callback, priv, child);
- if (ev) {
- ev->ctx = ctx;
- ev->type = VERTO_EV_TYPE_CHILD;
- ev->priority = priority;
- ev->callback = callback;
- ev->priv = priv;
- ev->data.child = child;
- }
- return ev;
+ doadd(ev->option.pid = pid, VERTO_EV_TYPE_CHILD);
+}
+
+void
+verto_call(struct vertoEv *ev)
+{
+ ev->callback(ev->ctx, ev);
+}
+
+void *
+verto_get_private(const struct vertoEv *ev)
+{
+ return ev->priv;
+}
+
+enum vertoEvType
+verto_get_type(const struct vertoEv *ev)
+{
+ return ev->type;
+}
+
+enum vertoEvPriority
+verto_get_priority(const struct vertoEv *ev)
+{
+ return ev->priority;
+}
+
+int
+verto_get_fd(const struct vertoEv *ev)
+{
+ if (ev && (ev->type & (VERTO_EV_TYPE_READ | VERTO_EV_TYPE_WRITE)))
+ return ev->option.fd;
+ return -1;
+}
+
+time_t
+verto_get_interval(const struct vertoEv *ev)
+{
+ if (ev && (ev->type & VERTO_EV_TYPE_TIMEOUT))
+ return ev->option.interval;
+ return 0;
+}
+
+int
+verto_get_signal(const struct vertoEv *ev)
+{
+ if (ev && (ev->type & VERTO_EV_TYPE_SIGNAL))
+ return ev->option.signal;
+ return -1;
+}
+
+pid_t
+verto_get_pid(const struct vertoEv *ev) {
+ if (ev && ev->type == VERTO_EV_TYPE_CHILD)
+ return ev->option.pid;
+ return 0;
}
void
@@ -396,7 +420,7 @@ verto_del(struct vertoEv *ev)
{
if (!ev)
return;
- ev->ctx->funcs.ctx_del(ev->ctx->priv, ev);
+ ev->ctx->funcs.ctx_del(ev->ctx->modpriv, ev);
}
/*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/
@@ -453,7 +477,21 @@ verto_convert_funcs(const struct vertoEvCtxFuncs *funcs, void *ctx_private)
if (!ctx)
return NULL;
- ctx->priv = ctx_private;
+ ctx->modpriv = ctx_private;
ctx->funcs = *funcs;
return ctx;
}
+
+void *
+verto_get_module_private(const struct vertoEv *ev)
+{
+ return ev->modpriv;
+}
+
+void *
+verto_set_module_private(struct vertoEv *ev, void *priv)
+{
+ void *oldpriv = ev->modpriv;
+ ev->modpriv = priv;
+ return oldpriv;
+}
diff --git a/src/verto.h b/src/verto.h
index 4303703..56b1c93 100644
--- a/src/verto.h
+++ b/src/verto.h
@@ -32,8 +32,6 @@
struct vertoEvCtx;
struct vertoEv;
-typedef void (*vertoCallback)(struct vertoEv *ev);
-
enum vertoEvType {
VERTO_EV_TYPE_READ = 1,
VERTO_EV_TYPE_WRITE = 1 << 1,
@@ -52,20 +50,7 @@ enum vertoEvPriority {
_VERTO_EV_PRIORITY_MAX = VERTO_EV_PRIORITY_HIGH
};
-struct vertoEv {
- struct vertoEvCtx *ctx;
- enum vertoEvType type;
- enum vertoEvPriority priority;
- vertoCallback callback;
- void *priv;
- union {
- int fd;
- int signal;
- time_t interval;
- pid_t child;
- void *rsvd; /* Reserved for future expansion */
- } data;
-};
+typedef void (*vertoCallback)(struct vertoEvCtx *ctx, struct vertoEv *ev);
/**
* Creates a new event context using an optionally specified implementation.
@@ -118,7 +103,12 @@ verto_new(const char *impl);
/**
* Gets the default event context using an optionally specified implementation.
*
- * You probably don't want this function. See verto_new() for details.
+ * This function is essentially a singleton version of verto_new(). However,
+ * since this function must return the same loop as the *_default() call of
+ * the underlying implementation (if such a function exists), it is *not* a
+ * global singleton, but a per-implementation singleton.
+ *
+ * In all other respects, verto_default() acts exactly like verto_new().
*
* @see verto_new()
* @param impl The implementation to use, or NULL.
@@ -284,7 +274,67 @@ verto_add_signal(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
*/
struct vertoEv *
verto_add_child(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
- vertoCallback callback, void *priv, pid_t child);
+ vertoCallback callback, void *priv, pid_t pid);
+
+/**
+ * Calls the callback of the vertoEv.
+ *
+ * @see verto_add_read()
+ * @see verto_add_write()
+ * @see verto_add_timeout()
+ * @see verto_add_idle()
+ * @see verto_add_signal()
+ * @see verto_add_child()
+ * @param ev The vertoEv
+ * @return The vertoEv type
+ */
+void
+verto_call(struct vertoEv *ev);
+
+/**
+ * Gets the private pointer of the vertoEv.
+ *
+ * @see verto_add_read()
+ * @see verto_add_write()
+ * @see verto_add_timeout()
+ * @see verto_add_idle()
+ * @see verto_add_signal()
+ * @see verto_add_child()
+ * @param ev The vertoEv
+ * @return The vertoEv private pointer
+ */
+void *
+verto_get_private(const struct vertoEv *ev);
+
+/**
+ * Gets the type of the vertoEv.
+ *
+ * @see verto_add_read()
+ * @see verto_add_write()
+ * @see verto_add_timeout()
+ * @see verto_add_idle()
+ * @see verto_add_signal()
+ * @see verto_add_child()
+ * @param ev The vertoEv
+ * @return The vertoEv type
+ */
+enum vertoEvType
+verto_get_type(const struct vertoEv *ev);
+
+/**
+ * Gets the priority of the vertoEv.
+ *
+ * @see verto_add_read()
+ * @see verto_add_write()
+ * @see verto_add_timeout()
+ * @see verto_add_idle()
+ * @see verto_add_signal()
+ * @see verto_add_child()
+ * @param ev The vertoEv
+ * @return The vertoEv priority
+ */
+enum vertoEvPriority
+verto_get_priority(const struct vertoEv *ev);
/**
* Gets the file descriptor associated with a read/write vertoEv.
@@ -294,9 +344,8 @@ verto_add_child(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
* @param ev The vertoEv to retrieve the file descriptor from.
* @return The file descriptor, or -1 if not a read/write event.
*/
-#define verto_get_fd(ev) \
- (((ev)->type & (VERTO_EV_TYPE_READ | VERTO_EV_TYPE_WRITE)) \
- ? (ev)->data.fd : (int) -1)
+int
+verto_get_fd(const struct vertoEv *ev);
/**
* Gets the interval associated with a timeout vertoEv.
@@ -305,9 +354,8 @@ verto_add_child(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
* @param ev The vertoEv to retrieve the interval from.
* @return The interval, or 0 if not a timeout event.
*/
-#define verto_get_interval(ev) \
- (((ev)->type & VERTO_EV_TYPE_TIMEOUT) \
- ? (ev)->data.timeout : (time_t) 0)
+time_t
+verto_get_interval(const struct vertoEv *ev);
/**
* Gets the signal associated with a signal vertoEv.
@@ -316,9 +364,8 @@ verto_add_child(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
* @param ev The vertoEv to retrieve the signal from.
* @return The signal, or -1 if not a signal event.
*/
-#define verto_get_signal(ev) \
- (((ev)->type & VERTO_EV_TYPE_SIGNAL) \
- ? (ev)->data.signal : (int) -1)
+int
+verto_get_signal(const struct vertoEv *ev);
/**
* Gets the pid associated with a child vertoEv.
@@ -327,9 +374,8 @@ verto_add_child(struct vertoEvCtx *ctx, enum vertoEvPriority priority,
* @param ev The vertoEv to retrieve the file descriptor from.
* @return The pid, or 0 if not a child event.
*/
-#define verto_get_pid(ev) \
- (((ev)->type & VERTO_EV_TYPE_CHILD) \
- ? (ev)->data.child : (pid_t) 0)
+pid_t
+verto_get_pid(const struct vertoEv *ev);
/**
* Removes an event from from the event context and frees it.