--- a/gplugin/gplugin-manager.c Thu Sep 23 23:19:13 2021 -0500
+++ b/gplugin/gplugin-manager.c Thu Sep 23 23:30:36 2021 -0500
@@ -80,7 +80,7 @@
GHashTable *plugins_filename_view;
GHashTable *loaders_by_extension;
@@ -92,6 +92,7 @@
*****************************************************************************/
GPluginManager *default_manager = NULL;
+GPluginLoader *native_loader = NULL; static guint signals[N_SIGNALS] = {
@@ -129,34 +130,6 @@
- * gplugin_manager_find_loader_by_type:
- * @manager: The #GPluginManager instance.
- * @type: The #GType of the loader to find.
- * Looks up a #GPluginLoader instance by its type.
- * Returns: (transfer none): The #GPluginLoader instance or %NULL.
-gplugin_manager_find_loader_by_type(GPluginManager *manager, GType type)
- GPluginManagerPrivate *priv = NULL;
- g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), NULL);
- g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), NULL);
- priv = gplugin_manager_get_instance_private(manager);
- for(l = priv->loaders; l; l = l->next) {
- if(G_OBJECT_TYPE(l->data) == type) {
- return GPLUGIN_LOADER(l->data);
gplugin_manager_foreach_unload_plugin(
@@ -304,8 +277,7 @@
g_clear_pointer(&priv->plugins_filename_view, g_hash_table_destroy);
/* clean up our list of loaders */
- g_slist_free_full(priv->loaders, g_object_unref);
+ g_clear_pointer(&priv->loaders, g_hash_table_destroy); /* free all the data in the loaders hash table and destroy it */
g_hash_table_foreach_remove(
@@ -475,6 +447,9 @@
priv->plugins_filename_view =
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
+ g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); /* The loaders_by_extension hash table is keyed on the supported extensions
* of the loader. Which means that a loader that supports multiple
* extensions will be in the table multiple times.
@@ -508,9 +483,11 @@
default_manager = g_object_new(GPLUGIN_TYPE_MANAGER, NULL);
if(register_native_loader) {
+ native_loader = gplugin_native_loader_new(); if(!gplugin_manager_register_loader(
- GPLUGIN_TYPE_NATIVE_LOADER,
g_error("failed to register loader: %s", error->message);
@@ -527,6 +504,8 @@
gplugin_manager_private_uninit(void)
+ g_clear_object(&native_loader); g_regex_unref(dependency_regex);
g_clear_object(&default_manager);
@@ -731,7 +710,7 @@
* gplugin_manager_register_loader:
* @manager: The #GPluginManager instance.
- * @type: #GType of a #GPluginLoader.
+ * @loader: The #GPluginLoader instance to register. * @error: (out) (nullable): The return address for a #GError.
* Registers @type as an available loader.
@@ -742,44 +721,32 @@
gplugin_manager_register_loader(
GPluginManagerPrivate *priv = NULL;
- GPluginLoader *loader = NULL;
+ GPluginLoader *found = NULL; GSList *l = NULL, *exts = NULL;
+ const gchar *id = NULL; g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), FALSE);
- g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), FALSE);
+ g_return_val_if_fail(GPLUGIN_IS_LOADER(loader), FALSE); + priv = gplugin_manager_get_instance_private(manager); - loader = gplugin_manager_find_loader_by_type(manager, type);
- if(GPLUGIN_IS_LOADER(loader)) {
+ id = gplugin_loader_get_id(loader); + found = g_hash_table_lookup(priv->loaders, id); + if(GPLUGIN_IS_LOADER(found)) { _("loader %s was already registered"),
- /* Create the loader instance first. If we can't create it, we bail */
- loader = g_object_new(type, NULL);
- if(!GPLUGIN_IS_LOADER(loader)) {
- _("failed to create loader instance for %s"),
- priv = gplugin_manager_get_instance_private(manager);
- g_slist_prepend(priv->loaders, g_object_ref(G_OBJECT(loader)));
+ g_hash_table_insert(priv->loaders, g_strdup(id), g_object_ref(loader)); exts = gplugin_loader_get_supported_extensions(loader);
for(l = exts; l; l = l->next) {
@@ -792,18 +759,19 @@
existing = g_hash_table_lookup(priv->loaders_by_extension, ext);
for(ll = existing; ll; ll = ll->next) {
- if(G_OBJECT_TYPE(ll->data) == type) {
- GPluginLoader *old = GPLUGIN_LOADER(ll->data);
+ GPluginLoader *iter = GPLUGIN_LOADER(ll->data); + const gchar *ext_id = gplugin_loader_get_id(iter); - existing = g_slist_remove(existing, old);
+ if(g_str_equal(id, ext_id)) { + existing = g_slist_remove(existing, iter); - g_object_unref(G_OBJECT(old));
- existing = g_slist_prepend(existing, g_object_ref(G_OBJECT(loader)));
+ existing = g_slist_prepend(existing, g_object_ref(loader)); /* Now insert the updated slist back into the hash table */
@@ -816,16 +784,13 @@
/* make a note that we need to refresh */
priv->refresh_needed = TRUE;
- /* we remove our initial reference from the loader now to avoid a leak */
- g_object_unref(G_OBJECT(loader));
* gplugin_manager_unregister_loader:
* @manager: The #GPluginManager instance.
- * @type: #GType of a #GPluginLoader.
+ * @loader: The #GPluginLoader instance to unregister. * @error: (out) (nullable): The return address for a #GError.
* Unregisters @type as an available loader.
@@ -836,30 +801,32 @@
gplugin_manager_unregister_loader(
GPluginManagerPrivate *priv = NULL;
- GPluginLoader *loader = NULL;
GSList *l = NULL, *exts = NULL;
+ const gchar *id = NULL; g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), FALSE);
- g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), FALSE);
+ g_return_val_if_fail(GPLUGIN_IS_LOADER(loader), FALSE); + priv = gplugin_manager_get_instance_private(manager); - loader = gplugin_manager_find_loader_by_type(manager, type);
+ id = gplugin_loader_get_id(loader); + loader = g_hash_table_lookup(priv->loaders, id); if(!GPLUGIN_IS_LOADER(loader)) {
_("loader %s is not registered"),
- priv = gplugin_manager_get_instance_private(manager);
exts = gplugin_loader_get_supported_extensions(loader);
for(l = exts; l; l = l->next) {
@@ -871,15 +838,16 @@
for(ll = los; ll; ll = ll->next) {
GPluginLoader *lo = GPLUGIN_LOADER(ll->data);
+ const gchar *lo_id = gplugin_loader_get_id(lo); /* check if this is not the loader we're looking for */
- if(G_OBJECT_TYPE(lo) != type)
+ if(!g_str_equal(id, lo_id)) { - /* at this point, the loader we're at is of the type we're
- * removing. So we'll remove it from the los SList. Then if the
- * SList is empty, we remove it from the hash table, otherwise we
+ /* At this point, we're at the loader that we're removing. So we'll + * remove it from the los SList. Then if the SList is empty, we + * remove it from the hash table, otherwise we just update it. los = g_slist_remove(los, lo);
@@ -892,7 +860,7 @@
/* kill our ref to the loader */
- g_object_unref(G_OBJECT(lo));
/* now move to the next extension to check */
@@ -900,8 +868,7 @@
- priv->loaders = g_slist_remove(priv->loaders, loader);
- g_object_unref(G_OBJECT(loader));
+ g_hash_table_remove(priv->loaders, id); @@ -912,10 +879,10 @@
* Returns a list of all registered #GPluginLoader's.
- * Returns: (element-type GPlugin.Loader) (transfer full): Returns a list of all
+ * Returns: (element-type GPlugin.Loader) (transfer container): Returns a list + * of all registered loaders.
gplugin_manager_get_loaders(GPluginManager *manager)
GPluginManagerPrivate *priv = NULL;
@@ -924,7 +891,7 @@
priv = gplugin_manager_get_instance_private(manager);
- return g_slist_copy_deep(priv->loaders, (GCopyFunc)g_object_ref, NULL);
+ return g_hash_table_get_values(priv->loaders); --- a/gplugin/tests/test-loader-registration.c Thu Sep 23 23:19:13 2021 -0500
+++ b/gplugin/tests/test-loader-registration.c Thu Sep 23 23:30:36 2021 -0500
@@ -88,6 +88,16 @@
loader_class->unload = test_gplugin_loader_unload;
+test_gplugin_loader_new(void) + return GPLUGIN_LOADER(g_object_new( + TEST_GPLUGIN_TYPE_LOADER, /******************************************************************************
*****************************************************************************/
@@ -95,33 +105,7 @@
test_gplugin_manager_loader_register_unregister(void)
GPluginManager *manager = NULL;
- gplugin_manager_private_uninit();
- gplugin_manager_private_init(TRUE);
- manager = gplugin_manager_get_default();
- ret = gplugin_manager_register_loader(
- TEST_GPLUGIN_TYPE_LOADER,
- g_assert_no_error(error);
- ret = gplugin_manager_unregister_loader(
- TEST_GPLUGIN_TYPE_LOADER,
- g_assert_no_error(error);
-test_gplugin_manager_loader_register_twice(void)
- GPluginManager *manager = NULL;
+ GPluginLoader *loader = NULL; @@ -130,33 +114,24 @@
manager = gplugin_manager_get_default();
- ret = gplugin_manager_register_loader(
- TEST_GPLUGIN_TYPE_LOADER,
+ loader = test_gplugin_loader_new(); + ret = gplugin_manager_register_loader(manager, loader, &error); g_assert_no_error(error);
- ret = gplugin_manager_register_loader(
- TEST_GPLUGIN_TYPE_LOADER,
- g_assert_error(error, GPLUGIN_DOMAIN, 0);
- ret = gplugin_manager_unregister_loader(
- TEST_GPLUGIN_TYPE_LOADER,
+ ret = gplugin_manager_unregister_loader(manager, loader, &error); g_assert_no_error(error);
+ g_clear_object(&loader); -test_gplugin_manager_loader_unregister_twice(void)
+test_gplugin_manager_loader_register_twice(void) GPluginManager *manager = NULL;
+ GPluginLoader *loader = NULL; @@ -165,27 +140,53 @@
manager = gplugin_manager_get_default();
- ret = gplugin_manager_register_loader(
- TEST_GPLUGIN_TYPE_LOADER,
+ loader = test_gplugin_loader_new(); + ret = gplugin_manager_register_loader(manager, loader, &error); + g_assert_no_error(error); + ret = gplugin_manager_register_loader(manager, loader, &error); + g_assert_error(error, GPLUGIN_DOMAIN, 0); + ret = gplugin_manager_unregister_loader(manager, loader, &error); g_assert_no_error(error);
- ret = gplugin_manager_unregister_loader(
- TEST_GPLUGIN_TYPE_LOADER,
+ g_clear_object(&loader); +test_gplugin_manager_loader_unregister_twice(void) + GPluginManager *manager = NULL; + GPluginLoader *loader = NULL; + gplugin_manager_private_uninit(); + gplugin_manager_private_init(TRUE); + manager = gplugin_manager_get_default(); + loader = test_gplugin_loader_new(); + ret = gplugin_manager_register_loader(manager, loader, &error); g_assert_no_error(error);
- ret = gplugin_manager_unregister_loader(
- TEST_GPLUGIN_TYPE_LOADER,
+ ret = gplugin_manager_unregister_loader(manager, loader, &error); + g_assert_no_error(error); + ret = gplugin_manager_unregister_loader(manager, loader, &error); g_assert_error(error, GPLUGIN_DOMAIN, 0);
+ g_clear_object(&loader); /******************************************************************************
--- a/tcc/gplugin-tcc-core.c Thu Sep 23 23:19:13 2021 -0500
+++ b/tcc/gplugin-tcc-core.c Thu Sep 23 23:30:36 2021 -0500
@@ -23,6 +23,8 @@
#include "gplugin-tcc-loader.h"
#include "gplugin-tcc-plugin.h"
+static GPluginLoader *loader = NULL; G_MODULE_EXPORT GPluginPluginInfo *
gplugin_query(G_GNUC_UNUSED GError **error)
@@ -50,10 +52,21 @@
gplugin_load(GPluginNativePlugin *plugin, GError **error)
+ GPluginManager *manager = NULL; gplugin_tcc_loader_register(plugin);
gplugin_tcc_plugin_register(plugin);
- return gplugin_manager_register_loader(GPLUGIN_TCC_TYPE_LOADER, error);
+ manager = gplugin_manager_get_default(); + loader = gplugin_tcc_loader_new(); + if(!gplugin_manager_register_loader(manager, loader, error)) { + g_clear_object(&loader);