From e83f805b8fa34db8ac0b885d3fb78c0e6437c908 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 10 Jan 2013 19:13:00 +0100 Subject: Main, IOThread: move GMainLoop setup code to class EventLoop --- Makefile.am | 3 +- src/ClientEvent.cxx | 3 +- src/IOThread.cxx | 60 +++++++----------------------- src/IOThread.hxx | 18 ++------- src/InotifyQueue.cxx | 7 +++- src/Main.cxx | 11 +++--- src/Main.hxx | 4 +- src/SignalHandlers.cxx | 3 +- src/StateFile.cxx | 8 ++-- src/event/Loop.hxx | 86 +++++++++++++++++++++++++++++++++++++++++++ src/input/CurlInputPlugin.cxx | 4 +- src/input/SoupInputPlugin.cxx | 3 +- test/run_inotify.cxx | 11 +++--- 13 files changed, 139 insertions(+), 82 deletions(-) create mode 100644 src/event/Loop.hxx diff --git a/Makefile.am b/Makefile.am index 170e74dc0..777fdd537 100644 --- a/Makefile.am +++ b/Makefile.am @@ -353,7 +353,8 @@ libutil_a_SOURCES = \ # Event loop library libevent_a_SOURCES = \ - src/event/WakeFD.cxx + src/event/WakeFD.cxx src/event/WakeFD.hxx \ + src/event/Loop.hxx # PCM library diff --git a/src/ClientEvent.cxx b/src/ClientEvent.cxx index aacd01cfe..fe967f93b 100644 --- a/src/ClientEvent.cxx +++ b/src/ClientEvent.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "ClientInternal.hxx" #include "Main.hxx" +#include "event/Loop.hxx" #include @@ -83,7 +84,7 @@ client_in_event(G_GNUC_UNUSED GIOChannel *source, GIOCondition condition, case COMMAND_RETURN_KILL: client_close(client); - g_main_loop_quit(main_loop); + main_loop->Break(); return false; case COMMAND_RETURN_CLOSE: diff --git a/src/IOThread.cxx b/src/IOThread.cxx index 2ab2fe913..192d4cc49 100644 --- a/src/IOThread.cxx +++ b/src/IOThread.cxx @@ -17,9 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "IOThread.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" +#include "event/Loop.hxx" #include @@ -27,8 +29,7 @@ static struct { Mutex mutex; Cond cond; - GMainContext *context; - GMainLoop *loop; + EventLoop *loop; GThread *thread; } io; @@ -36,10 +37,9 @@ void io_thread_run(void) { assert(io_thread_inside()); - assert(io.context != NULL); assert(io.loop != NULL); - g_main_loop_run(io.loop); + io.loop->Run(); } static gpointer @@ -57,18 +57,15 @@ io_thread_func(G_GNUC_UNUSED gpointer arg) void io_thread_init(void) { - assert(io.context == NULL); assert(io.loop == NULL); assert(io.thread == NULL); - io.context = g_main_context_new(); - io.loop = g_main_loop_new(io.context, false); + io.loop = new EventLoop(); } bool io_thread_start(GError **error_r) { - assert(io.context != NULL); assert(io.loop != NULL); assert(io.thread == NULL); @@ -86,7 +83,7 @@ io_thread_quit(void) { assert(io.loop != NULL); - g_main_loop_quit(io.loop); + io.loop->Break(); } void @@ -98,17 +95,15 @@ io_thread_deinit(void) g_thread_join(io.thread); } - if (io.loop != NULL) - g_main_loop_unref(io.loop); - - if (io.context != NULL) - g_main_context_unref(io.context); + delete io.loop; } -GMainContext * -io_thread_context(void) +EventLoop & +io_thread_get() { - return io.context; + assert(io.loop != nullptr); + + return *io.loop; } bool @@ -117,35 +112,6 @@ io_thread_inside(void) return io.thread != NULL && g_thread_self() == io.thread; } -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; -} - -GSource * -io_thread_timeout_add(guint interval_ms, GSourceFunc function, gpointer data) -{ - GSource *source = g_timeout_source_new(interval_ms); - g_source_set_callback(source, function, data, NULL); - g_source_attach(source, io.context); - return source; -} - -GSource * -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); - g_source_attach(source, io.context); - return source; -} - struct call_data { GThreadFunc function; gpointer data; @@ -186,7 +152,7 @@ io_thread_call(GThreadFunc function, gpointer _data) nullptr, }; - io_thread_idle_add(io_thread_call_func, &data); + io.loop->AddIdle(io_thread_call_func, &data); io.mutex.lock(); while (!data.done) diff --git a/src/IOThread.hxx b/src/IOThread.hxx index b1731c263..a9401dc7f 100644 --- a/src/IOThread.hxx +++ b/src/IOThread.hxx @@ -24,6 +24,8 @@ #include +class EventLoop; + void io_thread_init(void); @@ -50,8 +52,8 @@ void io_thread_deinit(void); gcc_pure -GMainContext * -io_thread_context(void); +EventLoop & +io_thread_get(); /** * Is the current thread the I/O thread? @@ -60,18 +62,6 @@ gcc_pure bool io_thread_inside(void); -guint -io_thread_idle_add(GSourceFunc function, gpointer data); - -gcc_malloc -GSource * -io_thread_timeout_add(guint interval_ms, GSourceFunc function, gpointer data); - -gcc_malloc -GSource * -io_thread_timeout_add_seconds(guint interval, - GSourceFunc function, gpointer data); - /** * Call a function synchronously in the I/O thread. */ diff --git a/src/InotifyQueue.cxx b/src/InotifyQueue.cxx index 0d19ff083..b94abeaaa 100644 --- a/src/InotifyQueue.cxx +++ b/src/InotifyQueue.cxx @@ -20,6 +20,8 @@ #include "config.h" #include "InotifyQueue.hxx" #include "UpdateGlue.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" #include #include @@ -93,8 +95,9 @@ mpd_inotify_enqueue(const char *uri_utf8) { if (queue_source_id != 0) g_source_remove(queue_source_id); - queue_source_id = g_timeout_add_seconds(INOTIFY_UPDATE_DELAY_S, - mpd_inotify_run_update, NULL); + queue_source_id = main_loop->AddTimeoutSeconds(INOTIFY_UPDATE_DELAY_S, + mpd_inotify_run_update, + nullptr); for (auto i = inotify_queue.begin(), end = inotify_queue.end(); i != end;) { diff --git a/src/Main.cxx b/src/Main.cxx index 1c58e0e40..f9062cccb 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -45,6 +45,7 @@ #include "Log.hxx" #include "GlobalEvents.hxx" #include "InputInit.hxx" +#include "event/Loop.hxx" #include "IOThread.hxx" extern "C" { @@ -96,7 +97,7 @@ enum { }; GThread *main_task; -GMainLoop *main_loop; +EventLoop *main_loop; Partition *global_partition; @@ -332,7 +333,7 @@ idle_event_emitted(void) static void shutdown_event_emitted(void) { - g_main_loop_quit(main_loop); + main_loop->Break(); } int main(int argc, char *argv[]) @@ -401,7 +402,7 @@ int mpd_main(int argc, char *argv[]) daemonize_set_user(); main_task = g_thread_self(); - main_loop = g_main_loop_new(NULL, FALSE); + main_loop = new EventLoop(EventLoop::Default()); GlobalEvents::Initialize(); GlobalEvents::Register(GlobalEvents::IDLE, idle_event_emitted); @@ -504,7 +505,7 @@ int mpd_main(int argc, char *argv[]) #endif /* run the main loop */ - g_main_loop_run(main_loop); + main_loop->Run(); #ifdef WIN32 win32_app_stopping(); @@ -512,7 +513,7 @@ int mpd_main(int argc, char *argv[]) /* cleanup */ - g_main_loop_unref(main_loop); + delete main_loop; #ifdef ENABLE_INOTIFY mpd_inotify_finish(); diff --git a/src/Main.hxx b/src/Main.hxx index 7047cced8..6ce079434 100644 --- a/src/Main.hxx +++ b/src/Main.hxx @@ -22,9 +22,11 @@ #include +class EventLoop; + extern GThread *main_task; -extern GMainLoop *main_loop; +extern EventLoop *main_loop; extern struct Partition *global_partition; diff --git a/src/SignalHandlers.cxx b/src/SignalHandlers.cxx index 4fd7675ff..a1938c737 100644 --- a/src/SignalHandlers.cxx +++ b/src/SignalHandlers.cxx @@ -24,6 +24,7 @@ #include "Log.hxx" #include "Main.hxx" +#include "event/Loop.hxx" #include "GlobalEvents.hxx" #include "mpd_error.h" @@ -35,7 +36,7 @@ static void exit_signal_handler(G_GNUC_UNUSED int signum) { - g_main_loop_quit(main_loop); + main_loop->Break(); } static void reload_signal_handler(G_GNUC_UNUSED int signum) diff --git a/src/StateFile.cxx b/src/StateFile.cxx index 29a560c75..a153a6263 100644 --- a/src/StateFile.cxx +++ b/src/StateFile.cxx @@ -24,6 +24,8 @@ #include "TextFile.hxx" #include "Partition.hxx" #include "Volume.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" #include #include @@ -137,9 +139,9 @@ state_file_init(const char *path, Partition &partition) state_file_path = g_strdup(path); state_file_read(partition); - save_state_source_id = g_timeout_add_seconds(5 * 60, - timer_save_state_file, - &partition); + save_state_source_id = + main_loop->AddTimeoutSeconds(5 * 60, timer_save_state_file, + &partition); } void diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx new file mode 100644 index 000000000..9c139e08e --- /dev/null +++ b/src/event/Loop.hxx @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_EVENT_LOOP_HXX +#define MPD_EVENT_LOOP_HXX + +#include "check.h" +#include "gcc.h" + +#include + +class EventLoop { + GMainContext *context; + GMainLoop *loop; + +public: + EventLoop() + :context(g_main_context_new()), + loop(g_main_loop_new(context, false)) {} + + struct Default {}; + EventLoop(gcc_unused Default _dummy) + :context(g_main_context_ref(g_main_context_default())), + loop(g_main_loop_new(context, false)) {} + + ~EventLoop() { + g_main_loop_unref(loop); + g_main_context_unref(context); + } + + GMainContext *GetContext() { + return context; + } + + void Break() { + g_main_loop_quit(loop); + } + + void Run() { + g_main_loop_run(loop); + } + + guint AddIdle(GSourceFunc function, gpointer data) { + GSource *source = g_idle_source_new(); + g_source_set_callback(source, function, data, NULL); + guint id = g_source_attach(source, GetContext()); + g_source_unref(source); + return id; + } + + guint AddTimeout(guint interval_ms, + GSourceFunc function, gpointer data) { + GSource *source = g_timeout_source_new(interval_ms); + g_source_set_callback(source, function, data, nullptr); + guint id = g_source_attach(source, GetContext()); + g_source_unref(source); + return id; + } + + guint AddTimeoutSeconds(guint interval_s, + GSourceFunc function, gpointer data) { + GSource *source = g_timeout_source_new_seconds(interval_s); + g_source_set_callback(source, function, data, nullptr); + guint id = g_source_attach(source, GetContext()); + g_source_unref(source); + return id; + } +}; + +#endif /* MAIN_NOTIFY_H */ diff --git a/src/input/CurlInputPlugin.cxx b/src/input/CurlInputPlugin.cxx index be919bb0e..27662d871 100644 --- a/src/input/CurlInputPlugin.cxx +++ b/src/input/CurlInputPlugin.cxx @@ -28,6 +28,7 @@ extern "C" { #include "input_internal.h" } +#include "event/Loop.hxx" #include "IOThread.hxx" #include "glib_compat.h" @@ -716,7 +717,8 @@ input_curl_init(const struct config_param *param, } curl.source = g_source_new(&curl_source_funcs, sizeof(*curl.source)); - curl.source_id = g_source_attach(curl.source, io_thread_context()); + curl.source_id = g_source_attach(curl.source, + io_thread_get().GetContext()); return true; } diff --git a/src/input/SoupInputPlugin.cxx b/src/input/SoupInputPlugin.cxx index a591a292c..5a60fa725 100644 --- a/src/input/SoupInputPlugin.cxx +++ b/src/input/SoupInputPlugin.cxx @@ -26,6 +26,7 @@ extern "C" { } #include "IOThread.hxx" +#include "event/Loop.hxx" #include "conf.h" extern "C" { @@ -105,7 +106,7 @@ input_soup_init(const struct config_param *param, GError **error_r) soup_session_async_new_with_options(SOUP_SESSION_PROXY_URI, soup_proxy, SOUP_SESSION_ASYNC_CONTEXT, - io_thread_context(), + io_thread_get().GetContext(), NULL); return true; diff --git a/test/run_inotify.cxx b/test/run_inotify.cxx index 2b77130d8..7052210b1 100644 --- a/test/run_inotify.cxx +++ b/test/run_inotify.cxx @@ -19,18 +19,19 @@ #include "config.h" #include "InotifySource.hxx" +#include "event/Loop.hxx" #include #include #include -static GMainLoop *main_loop; +static EventLoop *event_loop; static void exit_signal_handler(G_GNUC_UNUSED int signum) { - g_main_loop_quit(main_loop); + event_loop->Break(); } enum { @@ -78,7 +79,7 @@ int main(int argc, char **argv) return 2; } - main_loop = g_main_loop_new(NULL, false); + event_loop = new EventLoop(EventLoop::Default()); struct sigaction sa; sa.sa_flags = 0; @@ -87,8 +88,8 @@ int main(int argc, char **argv) sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); - g_main_loop_run(main_loop); - g_main_loop_unref(main_loop); + event_loop->Run(); mpd_inotify_source_free(source); + delete event_loop; } -- cgit v1.2.3