[libpeas] Make the C plugin loader thread-safe
- From: Garrett Regier <gregier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libpeas] Make the C plugin loader thread-safe
- Date: Tue, 18 Nov 2014 18:38:12 +0000 (UTC)
commit b3e33c431e73c9d594b90f75d6f62d551d31445c
Author: Garrett Regier <garrett regier riftio com>
Date: Sat Nov 8 07:49:56 2014 -0800
Make the C plugin loader thread-safe
https://bugzilla.gnome.org/show_bug.cgi?id=739619
libpeas/peas-plugin-info-priv.h | 4 ++
libpeas/peas-plugin-info.c | 2 +
libpeas/peas-plugin-loader-c.c | 100 +++++++++++++++++----------------------
3 files changed, 49 insertions(+), 57 deletions(-)
---
diff --git a/libpeas/peas-plugin-info-priv.h b/libpeas/peas-plugin-info-priv.h
index 60c9096..5ecda81 100644
--- a/libpeas/peas-plugin-info-priv.h
+++ b/libpeas/peas-plugin-info-priv.h
@@ -29,6 +29,10 @@ struct _PeasPluginInfo {
/*< private >*/
gint refcount;
+ /* Used and managed by PeasPluginLoader */
+ gpointer loader_data;
+
+ gchar *filename;
gchar *module_dir;
gchar *data_dir;
diff --git a/libpeas/peas-plugin-info.c b/libpeas/peas-plugin-info.c
index 8124540..b580916 100644
--- a/libpeas/peas-plugin-info.c
+++ b/libpeas/peas-plugin-info.c
@@ -80,6 +80,7 @@ _peas_plugin_info_unref (PeasPluginInfo *info)
if (!g_atomic_int_dec_and_test (&info->refcount))
return;
+ g_free (info->filename);
g_free (info->module_dir);
g_free (info->data_dir);
g_free (info->module_name);
@@ -269,6 +270,7 @@ _peas_plugin_info_new (const gchar *filename,
g_key_file_free (plugin_file);
+ info->filename = g_strdup (filename);
info->module_dir = g_strdup (module_dir);
info->data_dir = g_build_filename (data_dir, info->module_name, NULL);
diff --git a/libpeas/peas-plugin-loader-c.c b/libpeas/peas-plugin-loader-c.c
index c5a488d..3961138 100644
--- a/libpeas/peas-plugin-loader-c.c
+++ b/libpeas/peas-plugin-loader-c.c
@@ -29,8 +29,11 @@
#include "peas-extension-base.h"
#include "peas-object-module.h"
+#include "peas-plugin-info-priv.h"
struct _PeasPluginLoaderCPrivate {
+ GMutex lock;
+
GHashTable *loaded_plugins;
};
@@ -41,34 +44,43 @@ peas_plugin_loader_c_load (PeasPluginLoader *loader,
PeasPluginInfo *info)
{
PeasPluginLoaderC *cloader = PEAS_PLUGIN_LOADER_C (loader);
- PeasObjectModule *module;
- const gchar *module_name;
- module_name = peas_plugin_info_get_module_name (info);
- module = (PeasObjectModule *) g_hash_table_lookup (cloader->priv->loaded_plugins,
- module_name);
+ g_mutex_lock (&cloader->priv->lock);
- if (module == NULL)
+ if (!g_hash_table_lookup_extended (cloader->priv->loaded_plugins,
+ info->filename,
+ NULL, (gpointer *) &info->loader_data))
{
+ const gchar *module_name, *module_dir;
+
+ module_name = peas_plugin_info_get_module_name (info);
+ module_dir = peas_plugin_info_get_module_dir (info);
+
/* Force all C modules to be resident in case they
* use libraries that do not deal well with reloading
*/
- module = peas_object_module_new (module_name,
- peas_plugin_info_get_module_dir (info),
- TRUE);
+ info->loader_data = peas_object_module_new (module_name,
+ module_dir, TRUE);
+
+ if (!g_type_module_use (G_TYPE_MODULE (info->loader_data)))
+ g_clear_object (&info->loader_data);
g_hash_table_insert (cloader->priv->loaded_plugins,
- g_strdup (module_name), module);
+ g_strdup (info->filename), info->loader_data);
}
- if (!g_type_module_use (G_TYPE_MODULE (module)))
- {
- g_object_unref (module);
- g_hash_table_remove (cloader->priv->loaded_plugins, module_name);
- return FALSE;
- }
+ g_mutex_unlock (&cloader->priv->lock);
+ return info->loader_data != NULL;
+}
- return TRUE;
+static void
+peas_plugin_loader_c_unload (PeasPluginLoader *loader,
+ PeasPluginInfo *info)
+{
+ /* Don't bother unloading the plugin's
+ * GTypeModule as it is always resident
+ */
+ info->loader_data = NULL;
}
static gboolean
@@ -76,15 +88,7 @@ peas_plugin_loader_c_provides_extension (PeasPluginLoader *loader,
PeasPluginInfo *info,
GType exten_type)
{
- PeasPluginLoaderC *cloader = PEAS_PLUGIN_LOADER_C (loader);
- PeasObjectModule *module;
- const gchar *module_name;
-
- module_name = peas_plugin_info_get_module_name (info);
- module = (PeasObjectModule *) g_hash_table_lookup (cloader->priv->loaded_plugins,
- module_name);
-
- return peas_object_module_provides_object (module, exten_type);
+ return peas_object_module_provides_object (info->loader_data, exten_type);
}
static PeasExtension *
@@ -94,15 +98,8 @@ peas_plugin_loader_c_create_extension (PeasPluginLoader *loader,
guint n_parameters,
GParameter *parameters)
{
- PeasPluginLoaderC *cloader = PEAS_PLUGIN_LOADER_C (loader);
- PeasObjectModule *module;
GParameter *exten_parameters;
gpointer instance;
- const gchar *module_name;
-
- module_name = peas_plugin_info_get_module_name (info);
- module = (PeasObjectModule *) g_hash_table_lookup (cloader->priv->loaded_plugins,
- module_name);
/* We want to add a "plugin-info" property so we can pass it to
* the extension if it inherits from PeasExtensionBase. No need to
@@ -121,7 +118,7 @@ peas_plugin_loader_c_create_extension (PeasPluginLoader *loader,
g_value_init (&exten_parameters[n_parameters].value, PEAS_TYPE_PLUGIN_INFO);
g_value_set_boxed (&exten_parameters[n_parameters].value, info);
- instance = peas_object_module_create_object (module,
+ instance = peas_object_module_create_object (info->loader_data,
exten_type,
n_parameters + 1,
exten_parameters);
@@ -145,32 +142,19 @@ peas_plugin_loader_c_create_extension (PeasPluginLoader *loader,
}
static void
-peas_plugin_loader_c_unload (PeasPluginLoader *loader,
- PeasPluginInfo *info)
+peas_plugin_loader_c_init (PeasPluginLoaderC *loader)
{
- PeasPluginLoaderC *cloader = PEAS_PLUGIN_LOADER_C (loader);
- PeasObjectModule *module;
- const gchar *module_name;
-
- module_name = peas_plugin_info_get_module_name (info);
- module = (PeasObjectModule *) g_hash_table_lookup (cloader->priv->loaded_plugins,
- module_name);
+ loader->priv = G_TYPE_INSTANCE_GET_PRIVATE (loader,
+ PEAS_TYPE_PLUGIN_LOADER_C,
+ PeasPluginLoaderCPrivate);
- g_type_module_unuse (G_TYPE_MODULE (module));
-}
+ g_mutex_init (&loader->priv->lock);
-static void
-peas_plugin_loader_c_init (PeasPluginLoaderC *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- PEAS_TYPE_PLUGIN_LOADER_C,
- PeasPluginLoaderCPrivate);
-
- /* loaded_plugins maps PeasPluginInfo:module-name to a PeasObjectModule */
- self->priv->loaded_plugins = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- NULL);
+ /* loaded_plugins maps PeasPluginInfo:filename to a PeasObjectModule */
+ loader->priv->loaded_plugins = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
}
static void
@@ -178,6 +162,8 @@ peas_plugin_loader_c_finalize (GObject *object)
{
PeasPluginLoaderC *cloader = PEAS_PLUGIN_LOADER_C (object);
+ g_mutex_clear (&cloader->priv->lock);
+
g_hash_table_destroy (cloader->priv->loaded_plugins);
G_OBJECT_CLASS (peas_plugin_loader_c_parent_class)->finalize (object);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]