From 635f7026b0406fc127719ca50cd6dee4232e6bd1 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 25 Aug 2011 18:31:05 +0200 Subject: [PATCH] io_thread: add helper functions --- src/io_thread.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ src/io_thread.h | 13 +++++++++ 2 files changed, 84 insertions(+) diff --git a/src/io_thread.c b/src/io_thread.c index 0942f9a40..a2249ae95 100644 --- a/src/io_thread.c +++ b/src/io_thread.c @@ -18,10 +18,14 @@ */ #include "io_thread.h" +#include "glib_compat.h" #include static struct { + GMutex *mutex; + GCond *cond; + GMainContext *context; GMainLoop *loop; GThread *thread; @@ -44,6 +48,8 @@ io_thread_init(void) assert(io.loop == NULL); assert(io.thread == NULL); + io.mutex = g_mutex_new(); + io.cond = g_cond_new(); io.context = g_main_context_new(); io.loop = g_main_loop_new(io.context, false); } @@ -77,6 +83,9 @@ io_thread_deinit(void) if (io.context != NULL) g_main_context_unref(io.context); + + g_cond_free(io.cond); + g_mutex_free(io.mutex); } GMainContext * @@ -85,3 +94,65 @@ io_thread_context(void) return io.context; } +guint +io_thread_idle_add(GSourceFunc function, gpointer data) +{ + GSource *source = g_idle_source_new(); + g_source_set_callback(source, function, data, NULL); + guint id = g_source_attach(source, io.context); + g_source_unref(source); + return id; +} + +guint +io_thread_timeout_add_seconds(guint interval, + GSourceFunc function, gpointer data) +{ + GSource *source = g_timeout_source_new_seconds(interval); + g_source_set_callback(source, function, data, NULL); + guint id = g_source_attach(source, io.context); + g_source_unref(source); + return id; +} + +struct call_data { + GThreadFunc function; + gpointer data; + bool done; + gpointer result; +}; + +static gboolean +io_thread_call_func(gpointer _data) +{ + struct call_data *data = _data; + + gpointer result = data->function(data->data); + + g_mutex_lock(io.mutex); + data->done = true; + data->result = result; + g_cond_broadcast(io.cond); + g_mutex_unlock(io.mutex); + + return false; +} + +gpointer +io_thread_call(GThreadFunc function, gpointer _data) +{ + struct call_data data = { + .function = function, + .data = _data, + .done = false, + }; + + io_thread_idle_add(io_thread_call_func, &data); + + g_mutex_lock(io.mutex); + while (!data.done) + g_cond_wait(io.cond, io.mutex); + g_mutex_unlock(io.mutex); + + return data.result; +} diff --git a/src/io_thread.h b/src/io_thread.h index 53b32f61f..2daddba86 100644 --- a/src/io_thread.h +++ b/src/io_thread.h @@ -36,4 +36,17 @@ G_GNUC_PURE GMainContext * io_thread_context(void); +guint +io_thread_idle_add(GSourceFunc function, gpointer data); + +guint +io_thread_timeout_add_seconds(guint interval, + GSourceFunc function, gpointer data); + +/** + * Call a function synchronously in the I/O thread. + */ +gpointer +io_thread_call(GThreadFunc function, gpointer data); + #endif