[PATCH 16/25] efw-downloader: node_dispatcher: add event dispatcher utilizing GLib MainContext/MainLoop

Takashi Sakamoto o-takashi at sakamocchi.jp
Fri Aug 21 09:31:02 CEST 2020


HinawaFwNode creates GSource for GLib MainContext. It's easy to GLib
MainLoop as event dispatcher.

This commit adds local application of GLib MainContext/MainLoop to dispatch
events for HinawaFwNode.

Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
 efw-downloader/src/meson.build       |  2 +
 efw-downloader/src/node-dispatcher.c | 86 ++++++++++++++++++++++++++++
 efw-downloader/src/node-dispatcher.h | 21 +++++++
 efw-downloader/src/subcmd-device.c   | 10 ++++
 4 files changed, 119 insertions(+)
 create mode 100644 efw-downloader/src/node-dispatcher.c
 create mode 100644 efw-downloader/src/node-dispatcher.h

diff --git a/efw-downloader/src/meson.build b/efw-downloader/src/meson.build
index c006c8b..c43c332 100644
--- a/efw-downloader/src/meson.build
+++ b/efw-downloader/src/meson.build
@@ -15,12 +15,14 @@ sources = [
   'main.c',
   'efw-proto.c',
   'config-rom.c',
+  'node-dispatcher.c',
   'subcmd-device.c',
 ]
 
 headers = [
   'efw-proto.h',
   'config-rom.h',
+  'node-dispatcher.h',
   'subcmds.h',
 ]
 
diff --git a/efw-downloader/src/node-dispatcher.c b/efw-downloader/src/node-dispatcher.c
new file mode 100644
index 0000000..8394600
--- /dev/null
+++ b/efw-downloader/src/node-dispatcher.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// Copyright (c) 2020 Takashi Sakamoto
+#include "node-dispatcher.h"
+#include <time.h>
+
+struct thread_arg {
+    GMainLoop *loop;
+    GCond cond;
+    GMutex mutex;
+};
+
+static gpointer run_node_dispatcher(gpointer data)
+{
+    struct thread_arg *args = (struct thread_arg *)data;
+
+    g_mutex_lock(&args->mutex);
+    g_cond_signal(&args->cond);
+    g_mutex_unlock(&args->mutex);
+
+    g_main_loop_run(args->loop);
+
+    return NULL;
+}
+
+void node_dispatcher_start(struct node_dispatcher *dispatcher, HinawaFwNode *node, GError **error)
+{
+    struct thread_arg args;
+    GSource *src;
+
+    dispatcher->ctx = g_main_context_new();
+
+    hinawa_fw_node_create_source(node, &src, error);
+    if (*error != NULL)
+        return;
+
+    g_source_attach(src, dispatcher->ctx);
+    g_source_unref(src);
+
+    dispatcher->loop = g_main_loop_new(dispatcher->ctx, FALSE);
+
+    args.loop = dispatcher->loop;
+    g_cond_init(&args.cond);
+    g_mutex_init(&args.mutex);
+
+    dispatcher->th = g_thread_try_new("node-dispatcher", run_node_dispatcher, &args, error);
+    if (*error != NULL) {
+        g_main_loop_quit(dispatcher->loop);
+        g_main_loop_unref(dispatcher->loop);
+        dispatcher->loop = NULL;
+
+        g_main_context_unref(dispatcher->ctx);
+        dispatcher->ctx = NULL;
+
+        goto end;
+    }
+
+    g_mutex_lock(&args.mutex);
+    while (!g_main_loop_is_running(dispatcher->loop))
+        g_cond_wait(&args.cond, &args.mutex);
+    g_mutex_unlock(&args.mutex);
+end:
+    g_cond_clear(&args.cond);
+    g_mutex_clear(&args.mutex);
+}
+
+void node_dispatcher_stop(struct node_dispatcher *dispatcher)
+{
+    if (dispatcher->loop != NULL)
+        g_main_loop_quit(dispatcher->loop);
+
+    if (dispatcher->th != NULL) {
+        g_thread_join(dispatcher->th);
+        g_thread_unref(dispatcher->th);
+        dispatcher->th = NULL;
+    }
+
+    if (dispatcher->loop != NULL) {
+        g_main_loop_unref(dispatcher->loop);
+        dispatcher->loop = NULL;
+    }
+
+    if (dispatcher->ctx != NULL) {
+        g_main_context_unref(dispatcher->ctx);
+        dispatcher->ctx = NULL;
+    }
+}
diff --git a/efw-downloader/src/node-dispatcher.h b/efw-downloader/src/node-dispatcher.h
new file mode 100644
index 0000000..9e47e00
--- /dev/null
+++ b/efw-downloader/src/node-dispatcher.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// Copyright (c) 2020 Takashi Sakamoto
+#ifndef __NODE_DISPATCHER_H__
+#define __NODE_DISPATCHER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <libhinawa/fw_node.h>
+#include <libhinawa/fw_resp.h>
+
+struct node_dispatcher {
+    GMainContext *ctx;
+    GMainLoop *loop;
+    GThread *th;
+};
+
+void node_dispatcher_start(struct node_dispatcher *dispatcher, HinawaFwNode *node, GError **error);
+void node_dispatcher_stop(struct node_dispatcher *dispatcher);
+
+#endif
diff --git a/efw-downloader/src/subcmd-device.c b/efw-downloader/src/subcmd-device.c
index 1bfa1f2..5ac0ac6 100644
--- a/efw-downloader/src/subcmd-device.c
+++ b/efw-downloader/src/subcmd-device.c
@@ -7,6 +7,7 @@
 
 #include "efw-proto.h"
 #include "config-rom.h"
+#include "node-dispatcher.h"
 
 #define report_error(error, msg)                                                    \
         fprintf(stderr, "Fail to %s: %s %d %s\n",                                   \
@@ -60,6 +61,7 @@ int subcmd_device(int argc, char **argv)
     gsize length;
     guint32 vendor_id, model_id;
     EfwProto *proto;
+    struct node_dispatcher dispatcher = {0};
     int err;
     int i;
 
@@ -116,8 +118,16 @@ int subcmd_device(int argc, char **argv)
         goto err_node;
     }
 
+    node_dispatcher_start(&dispatcher, node, &error);
+    if (error != NULL) {
+        report_error(error, "begin dispatcher");
+        goto err_proto;
+    }
+
     entry->op(argc, argv, proto, &error);
 
+    node_dispatcher_stop(&dispatcher);
+err_proto:
     efw_proto_unbind(proto);
     g_object_unref(proto);
 err_node:
-- 
2.25.1



More information about the Alsa-devel mailing list