[gnome-software: 1/29] gs-plugin: Bind initialize/destroy to the GsPlugin lifetime




commit 6d60933fbc5054e637f6b2af490b81784b0aa7c6
Author: Philip Withnall <pwithnall endlessos org>
Date:   Thu May 20 19:58:12 2021 +0100

    gs-plugin: Bind initialize/destroy to the GsPlugin lifetime
    
    This is a step towards having a `GsPlugin` subclass per plugin, which
    will allow the vfuncs to be class methods, and avoid a load of `dlsym()`
    calls on every plugin job. It will also allow the C type system to be
    used, rather than a load of dynamic function pointer casting in
    `gs-plugin-loader.c`. Finally, it will prevent the perennial issue of
    identically-named symbols from multiple modules being conflicting in the
    process’ function name space, and being difficult to grep in the source
    code.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>

 lib/gs-plugin-loader.c | 69 ++++++++++++++------------------------------------
 lib/gs-plugin-types.h  |  7 ++---
 lib/gs-plugin-vfuncs.h | 31 ++++++++++-------------
 lib/gs-plugin.c        | 34 ++++++++++++-------------
 4 files changed, 51 insertions(+), 90 deletions(-)
---
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index 7f5859a05..8278bc2e9 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -617,13 +617,6 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderHelper *helper,
        if (gs_plugin_job_get_interactive (helper->plugin_job))
                gs_plugin_interactive_inc (plugin);
        switch (action) {
-       case GS_PLUGIN_ACTION_INITIALIZE:
-       case GS_PLUGIN_ACTION_DESTROY:
-               {
-                       GsPluginFunc plugin_func = func;
-                       plugin_func (plugin);
-               }
-               break;
        case GS_PLUGIN_ACTION_SETUP:
                {
                        GsPluginSetupFunc plugin_func = func;
@@ -843,8 +836,6 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderHelper *helper,
                GLogLevelFlags log_level;
 
                switch (action) {
-               case GS_PLUGIN_ACTION_INITIALIZE:
-               case GS_PLUGIN_ACTION_DESTROY:
                case GS_PLUGIN_ACTION_SETUP:
                        if (g_getenv ("GS_SELF_TEST_PLUGIN_ERROR_FAIL_HARD") == NULL)
                                log_level = G_LOG_LEVEL_WARNING;
@@ -2406,11 +2397,6 @@ gs_plugin_loader_clear_caches (GsPluginLoader *plugin_loader)
 void
 gs_plugin_loader_setup_again (GsPluginLoader *plugin_loader)
 {
-       GsPluginAction actions[] = {
-               GS_PLUGIN_ACTION_DESTROY,
-               GS_PLUGIN_ACTION_INITIALIZE,
-               GS_PLUGIN_ACTION_SETUP,
-               GS_PLUGIN_ACTION_UNKNOWN };
 #ifdef HAVE_SYSPROF
        gint64 begin_time_nsec G_GNUC_UNUSED = SYSPROF_CAPTURE_CURRENT_TIME;
 #endif
@@ -2421,28 +2407,23 @@ gs_plugin_loader_setup_again (GsPluginLoader *plugin_loader)
        /* remove any events */
        gs_plugin_loader_remove_events (plugin_loader);
 
-       /* call in order */
-       for (guint j = 0; actions[j] != GS_PLUGIN_ACTION_UNKNOWN; j++) {
-               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;
+       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 (actions[j], 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;
-                       }
-                       if (actions[j] == GS_PLUGIN_ACTION_DESTROY)
-                               gs_plugin_clear_data (plugin);
+               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;
                }
        }
 
@@ -2588,12 +2569,6 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
                }
        }
 
-       /* run the plugins */
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INITIALIZE, NULL);
-       helper = gs_plugin_loader_helper_new (plugin_loader, plugin_job);
-       if (!gs_plugin_loader_run_results (helper, cancellable, error))
-               return FALSE;
-
        /* order by deps */
        do {
                changes = FALSE;
@@ -2714,8 +2689,8 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
        } while (changes);
 
        /* run setup */
-       gs_plugin_job_set_action (helper->plugin_job, GS_PLUGIN_ACTION_SETUP);
-       helper->function_name = "gs_plugin_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);
@@ -2815,11 +2790,7 @@ gs_plugin_loader_dispose (GObject *object)
        GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (object);
 
        if (plugin_loader->plugins != NULL) {
-               g_autoptr(GsPluginLoaderHelper) helper = NULL;
-               g_autoptr(GsPluginJob) plugin_job = NULL;
-               plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_DESTROY, NULL);
-               helper = gs_plugin_loader_helper_new (plugin_loader, plugin_job);
-               gs_plugin_loader_run_results (helper, NULL, NULL);
+               /* FIXME: call a ->stop() (or similar) method on every plugin */
                g_clear_pointer (&plugin_loader->plugins, g_ptr_array_unref);
        }
        if (plugin_loader->updates_changed_id != 0) {
@@ -3396,10 +3367,8 @@ gs_plugin_loader_process_thread_cb (GTask *task,
 
        /* some functions are really required for proper operation */
        switch (action) {
-       case GS_PLUGIN_ACTION_DESTROY:
        case GS_PLUGIN_ACTION_GET_INSTALLED:
        case GS_PLUGIN_ACTION_GET_UPDATES:
-       case GS_PLUGIN_ACTION_INITIALIZE:
        case GS_PLUGIN_ACTION_INSTALL:
        case GS_PLUGIN_ACTION_DOWNLOAD:
        case GS_PLUGIN_ACTION_LAUNCH:
diff --git a/lib/gs-plugin-types.h b/lib/gs-plugin-types.h
index 4674ad228..db6c5b8e0 100644
--- a/lib/gs-plugin-types.h
+++ b/lib/gs-plugin-types.h
@@ -175,7 +175,8 @@ typedef enum {
  * @GS_PLUGIN_RULE_BETTER_THAN:                Results are better than another
  *
  * The rules used for ordering plugins.
- * Plugins are expected to add rules in gs_plugin_initialize().
+ * Plugins are expected to add rules in the init function for their #GsPlugin
+ * subclass.
  **/
 typedef enum {
        GS_PLUGIN_RULE_CONFLICTS,
@@ -216,8 +217,6 @@ typedef enum {
  * @GS_PLUGIN_ACTION_URL_TO_APP:               Convert the URI to an application
  * @GS_PLUGIN_ACTION_GET_RECENT:               Get the apps recently released
  * @GS_PLUGIN_ACTION_GET_UPDATES_HISTORICAL:    Get the list of historical updates
- * @GS_PLUGIN_ACTION_INITIALIZE:               Initialize the plugin
- * @GS_PLUGIN_ACTION_DESTROY:                  Destroy the plugin
  * @GS_PLUGIN_ACTION_DOWNLOAD:                 Download an application
  * @GS_PLUGIN_ACTION_GET_ALTERNATES:           Get the alternates for a specific application
  * @GS_PLUGIN_ACTION_GET_LANGPACKS:            Get appropriate language pack
@@ -258,8 +257,6 @@ typedef enum {
        GS_PLUGIN_ACTION_URL_TO_APP,
        GS_PLUGIN_ACTION_GET_RECENT,
        GS_PLUGIN_ACTION_GET_UPDATES_HISTORICAL,
-       GS_PLUGIN_ACTION_INITIALIZE,
-       GS_PLUGIN_ACTION_DESTROY,
        GS_PLUGIN_ACTION_DOWNLOAD,
        GS_PLUGIN_ACTION_GET_ALTERNATES,
        GS_PLUGIN_ACTION_GET_LANGPACKS,
diff --git a/lib/gs-plugin-vfuncs.h b/lib/gs-plugin-vfuncs.h
index 23b7829db..f4073312c 100644
--- a/lib/gs-plugin-vfuncs.h
+++ b/lib/gs-plugin-vfuncs.h
@@ -29,26 +29,21 @@
 G_BEGIN_DECLS
 
 /**
- * gs_plugin_initialize:
- * @plugin: a #GsPlugin
+ * gs_plugin_query_type:
  *
- * Checks if the plugin should run, and if initializes it. If the plugin should
- * not be run then gs_plugin_set_enabled() should be called.
- * This is also the place to call gs_plugin_alloc_data() if private data is
- * required for the plugin.
+ * Returns the #GType for a subclass of #GsPlugin provided by this plugin
+ * module. It should not do any other computation.
  *
- * NOTE: Do not do any failable actions in this function; use gs_plugin_setup()
- * instead.
- **/
-void            gs_plugin_initialize                   (GsPlugin       *plugin);
-
-/**
- * gs_plugin_destroy:
- * @plugin: a #GsPlugin
+ * The init function for that type should initialize the plugin. If the plugin
+ * should not be run then gs_plugin_set_enabled() should be called from the
+ * init function.
  *
- * Called when the plugin should destroy any private data.
- **/
-void            gs_plugin_destroy                      (GsPlugin       *plugin);
+ * NOTE: Do not do any failable actions in the plugin class’ init function; use
+ * gs_plugin_setup() instead.
+ *
+ * Since: 42
+ */
+GType           gs_plugin_query_type                   (void);
 
 /**
  * gs_plugin_adopt_app:
@@ -164,7 +159,7 @@ gboolean     gs_plugin_add_alternates               (GsPlugin       *plugin,
  * gs_app_set_progress() if they will take more than tens of milliseconds
  * to complete.
  *
- * This function will also not be called if gs_plugin_initialize() self-disabled.
+ * This function will also not be called if the plugin is disabled.
  *
  * Returns: %TRUE for success
  **/
diff --git a/lib/gs-plugin.c b/lib/gs-plugin.c
index 186bf3159..ee4844f15 100644
--- a/lib/gs-plugin.c
+++ b/lib/gs-plugin.c
@@ -165,6 +165,9 @@ gs_plugin_create (const gchar *filename, GError **error)
        GsPlugin *plugin = NULL;
        GsPluginPrivate *priv;
        g_autofree gchar *basename = NULL;
+       GModule *module = NULL;
+       GType (*query_type_function) (void) = NULL;
+       GType plugin_type;
 
        /* get the plugin name from the basename */
        basename = g_path_get_basename (filename);
@@ -179,17 +182,26 @@ gs_plugin_create (const gchar *filename, GError **error)
        g_strdelimit (basename, ".", '\0');
 
        /* create new plugin */
-       plugin = gs_plugin_new ();
-       priv = gs_plugin_get_instance_private (plugin);
-       priv->module = g_module_open (filename, 0);
-       if (priv->module == NULL) {
+       module = g_module_open (filename, 0);
+       if (module == NULL ||
+           !g_module_symbol (module, "gs_plugin_query_type", (gpointer *) &query_type_function)) {
                g_set_error (error,
                             GS_PLUGIN_ERROR,
                             GS_PLUGIN_ERROR_FAILED,
                             "failed to open plugin %s: %s",
                             filename, g_module_error ());
+               if (module != NULL)
+                       g_module_close (module);
                return NULL;
        }
+
+       plugin_type = query_type_function ();
+       g_assert (g_type_is_a (plugin_type, GS_TYPE_PLUGIN));
+
+       plugin = g_object_new (plugin_type, NULL);
+       priv = gs_plugin_get_instance_private (plugin);
+       priv->module = g_steal_pointer (&module);
+
        gs_plugin_set_name (plugin, basename + 13);
        return plugin;
 }
@@ -344,7 +356,7 @@ gs_plugin_get_enabled (GsPlugin *plugin)
  * @enabled: the enabled state
  *
  * Enables or disables a plugin.
- * This is normally only called from gs_plugin_initialize().
+ * This is normally only called from the init function for a #GsPlugin instance.
  *
  * Since: 3.22
  **/
@@ -1638,10 +1650,6 @@ gs_plugin_action_to_function_name (GsPluginAction action)
                return "gs_plugin_add_categories";
        if (action == GS_PLUGIN_ACTION_SETUP)
                return "gs_plugin_setup";
-       if (action == GS_PLUGIN_ACTION_INITIALIZE)
-               return "gs_plugin_initialize";
-       if (action == GS_PLUGIN_ACTION_DESTROY)
-               return "gs_plugin_destroy";
        if (action == GS_PLUGIN_ACTION_GET_ALTERNATES)
                return "gs_plugin_add_alternates";
        if (action == GS_PLUGIN_ACTION_GET_LANGPACKS)
@@ -1728,10 +1736,6 @@ gs_plugin_action_to_string (GsPluginAction action)
                return "get-recent";
        if (action == GS_PLUGIN_ACTION_GET_UPDATES_HISTORICAL)
                return "get-updates-historical";
-       if (action == GS_PLUGIN_ACTION_INITIALIZE)
-               return "initialize";
-       if (action == GS_PLUGIN_ACTION_DESTROY)
-               return "destroy";
        if (action == GS_PLUGIN_ACTION_GET_ALTERNATES)
                return "get-alternates";
        if (action == GS_PLUGIN_ACTION_GET_LANGPACKS)
@@ -1818,10 +1822,6 @@ gs_plugin_action_from_string (const gchar *action)
                return GS_PLUGIN_ACTION_GET_RECENT;
        if (g_strcmp0 (action, "get-updates-historical") == 0)
                return GS_PLUGIN_ACTION_GET_UPDATES_HISTORICAL;
-       if (g_strcmp0 (action, "initialize") == 0)
-               return GS_PLUGIN_ACTION_INITIALIZE;
-       if (g_strcmp0 (action, "destroy") == 0)
-               return GS_PLUGIN_ACTION_DESTROY;
        if (g_strcmp0 (action, "get-alternates") == 0)
                return GS_PLUGIN_ACTION_GET_ALTERNATES;
        if (g_strcmp0 (action, "get-langpacks") == 0)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]