[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/9] QSource: QEMU event source object
From: |
Michael Roth |
Subject: |
[Qemu-devel] [PATCH 3/9] QSource: QEMU event source object |
Date: |
Fri, 3 May 2013 11:03:46 -0500 |
This references QContext, which will be introduced later (and also
references this). These will likely be squashed eventually, but we leave
them separate for now for easier review.
This implements a QOM-based event source object which is used in much
the same way as a GSource.
Signed-off-by: Michael Roth <address@hidden>
---
include/qcontext/qsource.h | 63 +++++++++++++++++++
qcontext/qsource.c | 143 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 206 insertions(+)
create mode 100644 include/qcontext/qsource.h
create mode 100644 qcontext/qsource.c
diff --git a/include/qcontext/qsource.h b/include/qcontext/qsource.h
new file mode 100644
index 0000000..7c6dd75
--- /dev/null
+++ b/include/qcontext/qsource.h
@@ -0,0 +1,63 @@
+/*
+ * QSource: QEMU event source class
+ *
+ * Copyright IBM Corp. 2013
+ *
+ * Authors:
+ * Michael Roth <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef QSOURCE_H
+#define QSOURCE_H
+
+#include "qom/object.h"
+#include "qcontext/qcontext.h"
+
+typedef struct QSource QSource;
+
+typedef bool (*QSourceCB)(QSource *qsource);
+
+typedef struct QSourceFuncs {
+ bool (*prepare)(QSource *qsource, int *timeout);
+ bool (*check)(QSource *qsource);
+ bool (*dispatch)(QSource *qsource);
+ void (*finalize)(QSource *qsource);
+} QSourceFuncs;
+
+typedef struct QSourceClass {
+ ObjectClass parent_class;
+
+ void (*add_poll)(QSource *qsource, GPollFD *pfd);
+ void (*remove_poll)(QSource *qsource, GPollFD *pfd);
+ void (*set_source_funcs)(QSource *qsource, QSourceFuncs funcs);
+ QSourceCB (*get_callback_func)(QSource *qsource);
+ void (*set_callback_func)(QSource *qsource, QSourceCB cb);
+ void (*set_user_data)(QSource *qsource, void *user_data);
+ void *(*get_user_data)(QSource *qsource);
+} QSourceClass;
+
+struct QSource {
+ /* <private */
+ Object parent_obj;
+
+ QSourceFuncs source_funcs;
+ QSourceCB callback_func;
+ GArray *poll_fds;
+ void *user_data;
+ struct QContext *ctx;
+ char *name;
+
+ /* <public> */
+};
+
+#define TYPE_QSOURCE "qsource"
+#define QSOURCE(obj) OBJECT_CHECK(QSource, (obj), TYPE_QSOURCE)
+#define QSOURCE_CLASS(klass) OBJECT_CLASS_CHECK(QSourceClass, (klass),
TYPE_QSOURCE)
+#define QSOURCE_GET_CLASS(obj) OBJECT_GET_CLASS(QSourceClass, (obj),
TYPE_QSOURCE)
+
+QSource *qsource_new(QSourceFuncs source_funcs, QSourceCB cb, const char *name,
+ void *opaque);
+
+#endif /* QSOURCE_H */
diff --git a/qcontext/qsource.c b/qcontext/qsource.c
new file mode 100644
index 0000000..1f3dcb5
--- /dev/null
+++ b/qcontext/qsource.c
@@ -0,0 +1,143 @@
+/*
+ * QSource: QEMU event source class
+ *
+ * Copyright IBM Corp. 2013
+ *
+ * Authors:
+ * Michael Roth <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include <glib.h>
+#include "qom/object.h"
+#include "qcontext/qcontext.h"
+#include "qemu/module.h"
+
+/* FIXME: this basically causes us to destroy/rebuild an
+ * attached QSource/GSource every time we modify. What we
+ * should really have is an interface in the QContext for
+ * modifying an already attached source to avoid so much
+ * churn for simple action like adding poll fds to an
+ * source. The alternative is to require users to
+ * explicitly detach QSources before modifying them, but
+ * updating poll FDs/callbacks etc is a common operation
+ * for QSource/GSource callbacks so this limits functionality
+ * substantially
+ */
+static void qsource_update(QSource *qsource)
+{
+ QContext *ctx = qsource->ctx;
+
+ if (ctx) {
+ qcontext_detach(ctx, qsource, NULL);
+ qcontext_attach(ctx, qsource, NULL);
+ }
+}
+
+static void qsource_add_poll(QSource *qsource, GPollFD *pfd)
+{
+ g_array_append_val(qsource->poll_fds, pfd);
+ qsource_update(qsource);
+}
+
+static void qsource_remove_poll(QSource *qsource, GPollFD *pfd)
+{
+ bool done = false;
+
+ while (!done) {
+ done = true;
+ guint i;
+ for (i = 0; i < qsource->poll_fds->len; i++) {
+ if (g_array_index(qsource->poll_fds, GPollFD *, i) == pfd) {
+ g_array_remove_index(qsource->poll_fds, i);
+ /* iterate again to make sure we get them all */
+ done = false;
+ break;
+ }
+ }
+ }
+
+ qsource_update(qsource);
+}
+
+static void qsource_set_source_funcs(QSource *qsource, QSourceFuncs funcs)
+{
+ qsource->source_funcs = funcs;
+ qsource_update(qsource);
+}
+
+static QSourceCB qsource_get_callback_func(QSource *qsource)
+{
+ return qsource->callback_func;
+}
+
+static void qsource_set_callback_func(QSource *qsource, QSourceCB
callback_func)
+{
+ qsource->callback_func = callback_func;
+ qsource_update(qsource);
+}
+
+static void qsource_set_user_data(QSource *qsource, void *user_data)
+{
+ qsource->user_data = user_data;
+ qsource_update(qsource);
+}
+
+static void *qsource_get_user_data(QSource *qsource)
+{
+ return qsource->user_data;
+}
+
+static void qsource_initfn(Object *obj)
+{
+ QSource *qsource = QSOURCE(obj);
+ qsource->poll_fds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
+ qsource->ctx = NULL;
+}
+
+static void qsource_class_initfn(ObjectClass *class, void *data)
+{
+ QSourceClass *k = QSOURCE_CLASS(class);
+
+ k->add_poll = qsource_add_poll;
+ k->remove_poll = qsource_remove_poll;
+ k->set_source_funcs = qsource_set_source_funcs;
+ k->get_callback_func = qsource_get_callback_func;
+ k->set_callback_func = qsource_set_callback_func;
+ k->get_user_data = qsource_get_user_data;
+ k->set_user_data = qsource_set_user_data;
+}
+
+TypeInfo qsource_info = {
+ .name = TYPE_QSOURCE,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(QSource),
+ .class_size = sizeof(QSourceClass),
+ .instance_init = qsource_initfn,
+ .class_init = qsource_class_initfn,
+ .interfaces = (InterfaceInfo[]) {
+ { },
+ },
+};
+
+static void qsource_register_types(void)
+{
+ type_register_static(&qsource_info);
+}
+
+type_init(qsource_register_types)
+
+QSource *qsource_new(QSourceFuncs funcs, QSourceCB cb, const char *name, void
*opaque)
+{
+ QSource *qsource = QSOURCE(object_new(TYPE_QSOURCE));
+ QSourceClass *qsourcek = QSOURCE_GET_CLASS(qsource);
+
+ qsource->name = g_strdup(name);
+
+ qsourcek->set_source_funcs(qsource, funcs);
+ qsourcek->set_callback_func(qsource, cb);
+ qsourcek->set_user_data(qsource, opaque);
+
+ return qsource;
+}
--
1.7.9.5
- [Qemu-devel] [RFC 0/9] QContext: QOM class to support multiple event loops, Michael Roth, 2013/05/03
- [Qemu-devel] [PATCH 1/9] qom: add qom_init_completion, Michael Roth, 2013/05/03
- [Qemu-devel] [PATCH 3/9] QSource: QEMU event source object,
Michael Roth <=
- [Qemu-devel] [PATCH 5/9] GlibQContext: a QContext wrapper around GMainContexts, Michael Roth, 2013/05/03
- [Qemu-devel] [PATCH 4/9] QContext: QEMU event loop context, abstract base class, Michael Roth, 2013/05/03
- [Qemu-devel] [PATCH 6/9] QContext: add unit tests, Michael Roth, 2013/05/03
- [Qemu-devel] [PATCH 8/9] main-loop: drive main event loop via QContext, Michael Roth, 2013/05/03
- [Qemu-devel] [PATCH 7/9] iohandler: associate with main event loop via a QSource, Michael Roth, 2013/05/03
- [Qemu-devel] [PATCH 9/9] dataplane: use a QContext event loop in place of custom thread, Michael Roth, 2013/05/03