[gnome-software: 24/29] gs-plugin-loader: Call async setup functions on plugins
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software: 24/29] gs-plugin-loader: Call async setup functions on plugins
- Date: Mon, 6 Dec 2021 10:24:18 +0000 (UTC)
commit 50f24e9e9091824369ee6f55e3f849a6172198db
Author: Philip Withnall <pwithnall endlessos org>
Date: Wed Nov 24 16:19:53 2021 +0000
gs-plugin-loader: Call async setup functions on plugins
If a plugin implements an async setup function, call it.
Signed-off-by: Philip Withnall <pwithnall endlessos org>
Helps: #1472
lib/gs-plugin-loader.c | 127 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 94 insertions(+), 33 deletions(-)
---
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index d70466354..260f5332a 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -2394,6 +2394,97 @@ gs_plugin_loader_clear_caches (GsPluginLoader *plugin_loader)
}
}
+typedef struct {
+ GsPluginLoader *plugin_loader; /* (unowned) */
+ GMainContext *context; /* (owned) */
+ guint n_pending;
+#ifdef HAVE_SYSPROF
+ gint64 setup_begin_time_nsec;
+#endif
+} SetupData;
+
+static void plugin_setup_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void
+gs_plugin_loader_call_setup (GsPluginLoader *plugin_loader,
+ GCancellable *cancellable)
+{
+ SetupData setup_data;
+
+ setup_data.plugin_loader = plugin_loader;
+ setup_data.n_pending = 1; /* incremented until all operations have been started */
+ setup_data.context = g_main_context_new ();
+#ifdef HAVE_SYSPROF
+ setup_data.setup_begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME;
+#endif
+
+ g_main_context_push_thread_default (setup_data.context);
+
+ for (guint i = 0; i < plugin_loader->plugins->len; i++) {
+ GsPlugin *plugin = GS_PLUGIN (plugin_loader->plugins->pdata[i]);
+
+ if (!gs_plugin_get_enabled (plugin))
+ continue;
+
+ if (GS_PLUGIN_GET_CLASS (plugin)->setup_async != NULL) {
+ GS_PLUGIN_GET_CLASS (plugin)->setup_async (plugin, cancellable,
+ plugin_setup_cb, &setup_data);
+ setup_data.n_pending++;
+ }
+ }
+
+ /* Wait for setup to complete in all plugins.
+ * Nested iteration of the main context is not generally good practice,
+ * but we expect gs_plugin_loader_setup() to only ever be executed early
+ * in the process’ lifetime, so it’s probably OK. This could be
+ * refactored in future. */
+ setup_data.n_pending--;
+
+ while (setup_data.n_pending > 0)
+ g_main_context_iteration (setup_data.context, TRUE);
+
+ g_main_context_pop_thread_default (setup_data.context);
+ g_clear_pointer (&setup_data.context, g_main_context_unref);
+}
+
+static void
+plugin_setup_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GsPlugin *plugin = GS_PLUGIN (source_object);
+ SetupData *data = user_data;
+ g_autoptr(GError) local_error = NULL;
+
+ g_assert (GS_PLUGIN_GET_CLASS (plugin)->setup_finish != NULL);
+
+ if (!GS_PLUGIN_GET_CLASS (plugin)->setup_finish (plugin, result, &local_error)) {
+ g_debug ("disabling %s as setup failed: %s",
+ gs_plugin_get_name (plugin),
+ local_error->message);
+ gs_plugin_set_enabled (plugin, FALSE);
+ }
+
+#ifdef HAVE_SYSPROF
+ if (data->plugin_loader->sysprof_writer != NULL) {
+ sysprof_capture_writer_add_mark (data->plugin_loader->sysprof_writer,
+ data->setup_begin_time_nsec,
+ sched_getcpu (),
+ getpid (),
+ SYSPROF_CAPTURE_CURRENT_TIME - data->setup_begin_time_nsec,
+ "gnome-software",
+ "setup-plugin",
+ NULL);
+ }
+#endif /* HAVE_SYSPROF */
+
+ /* Indicate this plugin has finished setting up. */
+ data->n_pending--;
+ g_main_context_wakeup (data->context);
+}
+
/**
* gs_plugin_loader_setup_again:
* @plugin_loader: a #GsPluginLoader
@@ -2414,25 +2505,8 @@ gs_plugin_loader_setup_again (GsPluginLoader *plugin_loader)
/* remove any events */
gs_plugin_loader_remove_events (plugin_loader);
- for (guint i = 0; i < plugin_loader->plugins->len; i++) {
- g_autoptr(GError) error_local = NULL;
- g_autoptr(GsPluginLoaderHelper) helper = NULL;
- g_autoptr(GsPluginJob) plugin_job = NULL;
- GsPlugin *plugin = g_ptr_array_index (plugin_loader->plugins, i);
- if (!gs_plugin_get_enabled (plugin))
- continue;
-
- plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SETUP, NULL);
- helper = gs_plugin_loader_helper_new (plugin_loader, plugin_job);
- if (!gs_plugin_loader_call_vfunc (helper, plugin, NULL, NULL,
- GS_PLUGIN_REFINE_FLAGS_DEFAULT,
- NULL, &error_local)) {
- g_warning ("resetup of %s failed: %s",
- gs_plugin_get_name (plugin),
- error_local->message);
- break;
- }
- }
+ /* Start all the plugins setting up again in parallel. */
+ gs_plugin_loader_call_setup (plugin_loader, NULL);
#ifdef HAVE_SYSPROF
if (plugin_loader->sysprof_writer != NULL) {
@@ -2696,20 +2770,7 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
} while (changes);
/* run setup */
- plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SETUP, NULL);
- helper = gs_plugin_loader_helper_new (plugin_loader, plugin_job);
- for (i = 0; i < plugin_loader->plugins->len; i++) {
- g_autoptr(GError) error_local = NULL;
- plugin = g_ptr_array_index (plugin_loader->plugins, i);
- if (!gs_plugin_loader_call_vfunc (helper, plugin, NULL, NULL,
- GS_PLUGIN_REFINE_FLAGS_DEFAULT,
- cancellable, &error_local)) {
- g_debug ("disabling %s as setup failed: %s",
- gs_plugin_get_name (plugin),
- error_local->message);
- gs_plugin_set_enabled (plugin, FALSE);
- }
- }
+ gs_plugin_loader_call_setup (plugin_loader, cancellable);
/* now we can load the install-queue */
if (!load_install_queue (plugin_loader, error))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]