qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]