[gnome-software: 2/3] gs-app: Make list of addons immutable




commit 8ece9b796541c6568717e6e84898389435fc8c37
Author: Philip Withnall <pwithnall endlessos org>
Date:   Wed Apr 13 15:56:05 2022 +0100

    gs-app: Make list of addons immutable
    
    Change `gs_app_add_addons()` to use the read-copy-update approach, so
    that any lists of addons returned by previous calls to
    `gs_app_dup_addons()` are not modified.
    
    While we’re at it, make it operate on a list of addons, rather than a
    single addon, which should reduce the number of read-copy-update cycles
    needed in `gs-appstream.c`.
    
    Finally, avoid allocating an internal list of addons in a `GsApp` until
    the first addon is added. This should avoid carrying an empty allocated
    `GsAppList` around in various apps which will never have addons. It
    should save a small amount of memory.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #1721

 lib/gs-app.c       | 31 ++++++++++++++++++++++---------
 lib/gs-app.h       |  5 +++--
 lib/gs-appstream.c | 17 +++++++++++++----
 lib/gs-self-test.c |  9 ++++++---
 4 files changed, 44 insertions(+), 18 deletions(-)
---
diff --git a/lib/gs-app.c b/lib/gs-app.c
index 52153c3e9..efbdb5eed 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -3886,25 +3886,37 @@ gs_app_dup_addons (GsApp *app)
 }
 
 /**
- * gs_app_add_addon:
+ * gs_app_add_addons:
  * @app: a #GsApp
- * @addon: a #GsApp
+ * @addons: (transfer none) (not nullable): a list of #GsApps
  *
- * Adds an addon to the list of application addons.
+ * Adds zero or more addons to the list of application addons.
  *
- * Since: 3.22
+ * Since: 43
  **/
 void
-gs_app_add_addon (GsApp *app, GsApp *addon)
+gs_app_add_addons (GsApp     *app,
+                   GsAppList *addons)
 {
        GsAppPrivate *priv = gs_app_get_instance_private (app);
        g_autoptr(GMutexLocker) locker = NULL;
+       g_autoptr(GsAppList) new_addons = NULL;
 
        g_return_if_fail (GS_IS_APP (app));
-       g_return_if_fail (GS_IS_APP (addon));
+       g_return_if_fail (GS_IS_APP_LIST (addons));
+
+       if (gs_app_list_length (addons) == 0)
+               return;
 
        locker = g_mutex_locker_new (&priv->mutex);
-       gs_app_list_add (priv->addons, addon);
+
+       if (priv->addons != NULL)
+               new_addons = gs_app_list_copy (priv->addons);
+       else
+               new_addons = gs_app_list_new ();
+       gs_app_list_add_list (new_addons, addons);
+
+       g_set_object (&priv->addons, new_addons);
 }
 
 /**
@@ -3924,7 +3936,9 @@ gs_app_remove_addon (GsApp *app, GsApp *addon)
        g_return_if_fail (GS_IS_APP (app));
        g_return_if_fail (GS_IS_APP (addon));
        locker = g_mutex_locker_new (&priv->mutex);
-       gs_app_list_remove (priv->addons, addon);
+
+       if (priv->addons != NULL)
+               gs_app_list_remove (priv->addons, addon);
 }
 
 /**
@@ -5586,7 +5600,6 @@ gs_app_init (GsApp *app)
        priv->sources = g_ptr_array_new_with_free_func (g_free);
        priv->source_ids = g_ptr_array_new_with_free_func (g_free);
        priv->categories = g_ptr_array_new_with_free_func (g_free);
-       priv->addons = gs_app_list_new ();
        priv->related = gs_app_list_new ();
        priv->history = gs_app_list_new ();
        priv->screenshots = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
diff --git a/lib/gs-app.h b/lib/gs-app.h
index 325dfd86d..1fa75b266 100644
--- a/lib/gs-app.h
+++ b/lib/gs-app.h
@@ -19,6 +19,7 @@ G_BEGIN_DECLS
 
 /* Dependency loop means we can’t include the header. */
 typedef struct _GsPlugin GsPlugin;
+typedef struct _GsAppList GsAppList;
 
 #define GS_TYPE_APP (gs_app_get_type ())
 
@@ -428,8 +429,8 @@ guint64              gs_app_get_size_download_dependencies
                                                (GsApp          *app);
 void            gs_app_add_related             (GsApp          *app,
                                                 GsApp          *app2);
-void            gs_app_add_addon               (GsApp          *app,
-                                                GsApp          *addon);
+void            gs_app_add_addons              (GsApp          *app,
+                                                GsAppList      *addons);
 void            gs_app_add_history             (GsApp          *app,
                                                 GsApp          *app2);
 guint64                 gs_app_get_install_date        (GsApp          *app);
diff --git a/lib/gs-appstream.c b/lib/gs-appstream.c
index b0aea1f3e..cdaa86e5c 100644
--- a/lib/gs-appstream.c
+++ b/lib/gs-appstream.c
@@ -290,6 +290,7 @@ gs_appstream_refine_add_addons (GsPlugin *plugin,
        g_autofree gchar *xpath = NULL;
        g_autoptr(GError) error_local = NULL;
        g_autoptr(GPtrArray) addons = NULL;
+       g_autoptr(GsAppList) addons_list = NULL;
 
        /* get all components */
        xpath = g_strdup_printf ("components/component/extends[text()='%s']/..",
@@ -303,14 +304,22 @@ gs_appstream_refine_add_addons (GsPlugin *plugin,
                g_propagate_error (error, g_steal_pointer (&error_local));
                return FALSE;
        }
+
+       addons_list = gs_app_list_new ();
+
        for (guint i = 0; i < addons->len; i++) {
                XbNode *addon = g_ptr_array_index (addons, i);
-               g_autoptr(GsApp) app2 = NULL;
-               app2 = gs_appstream_create_app (plugin, silo, addon, error);
-               if (app2 == NULL)
+               g_autoptr(GsApp) addon_app = NULL;
+
+               addon_app = gs_appstream_create_app (plugin, silo, addon, error);
+               if (addon_app == NULL)
                        return FALSE;
-               gs_app_add_addon (app, app2);
+
+               gs_app_list_add (addons_list, addon_app);
        }
+
+       gs_app_add_addons (app, addons_list);
+
        return TRUE;
 }
 
diff --git a/lib/gs-self-test.c b/lib/gs-self-test.c
index 9a75d5b12..24dddd061 100644
--- a/lib/gs-self-test.c
+++ b/lib/gs-self-test.c
@@ -564,12 +564,15 @@ static void
 gs_app_addons_func (void)
 {
        g_autoptr(GsApp) app = gs_app_new ("test.desktop");
-       GsApp *addon;
+       g_autoptr(GsApp) addon = NULL;
+       g_autoptr(GsAppList) addons_list = NULL;
 
        /* create, add then drop ref, so @app has the only refcount of addon */
        addon = gs_app_new ("test.desktop");
-       gs_app_add_addon (app, addon);
-       g_object_unref (addon);
+       addons_list = gs_app_list_new ();
+       gs_app_list_add (addons_list, addon);
+
+       gs_app_add_addons (app, addons_list);
 
        gs_app_remove_addon (app, addon);
 }


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