summaryrefslogtreecommitdiff
path: root/libpeas/peas-utils.c
diff options
context:
space:
mode:
authorGarrett Regier <garrettregier@gmail.com>2017-06-09 18:32:51 -0700
committerGarrett Regier <garrettregier@gmail.com>2017-06-09 18:32:51 -0700
commitbcc8644b83a3d514f242cfa933371c329edf16f5 (patch)
treea352cbec54718596b15b0acab29dd7ac409328ba /libpeas/peas-utils.c
parentedbdfb1671716e0977fbab129c914816d8be43a6 (diff)
downloadlibpeas-bcc8644b83a3d514f242cfa933371c329edf16f5.tar.gz
Cache an extension type's base class and interfaces
Diffstat (limited to 'libpeas/peas-utils.c')
-rw-r--r--libpeas/peas-utils.c114
1 files changed, 72 insertions, 42 deletions
diff --git a/libpeas/peas-utils.c b/libpeas/peas-utils.c
index 7d3bd91..8436301 100644
--- a/libpeas/peas-utils.c
+++ b/libpeas/peas-utils.c
@@ -49,6 +49,10 @@ G_STATIC_ASSERT (G_N_ELEMENTS (all_plugin_loaders) == PEAS_UTILS_N_LOADERS);
G_STATIC_ASSERT (G_N_ELEMENTS (all_plugin_loader_modules) == PEAS_UTILS_N_LOADERS);
G_STATIC_ASSERT (G_N_ELEMENTS (conflicting_plugin_loaders) == PEAS_UTILS_N_LOADERS);
+static
+G_DEFINE_QUARK (peas-extension-base-class-and-interfaces-cache,
+ exten_type_cache)
+
static void
add_all_prerequisites (GType iface_type,
GType *base_type,
@@ -91,51 +95,87 @@ add_all_prerequisites (GType iface_type,
g_free (prereq);
}
-static GPtrArray *
-find_base_type_and_interfaces (GType exten_type,
- GType *base_type)
+static gpointer *
+find_base_class_and_interfaces (GType exten_type)
{
- GPtrArray *ifaces;
- GType *interfaces;
- gint i;
+ GPtrArray *results;
+ GType base_type = G_TYPE_INVALID;
+ static GMutex cache_lock;
+ gpointer *data, *cached_data;
+
+ results = g_ptr_array_new ();
- ifaces = g_ptr_array_new ();
- g_ptr_array_set_free_func (ifaces,
- (GDestroyNotify) g_type_default_interface_unref);
+ /* This is used for the GObjectClass of the base_type */
+ g_ptr_array_add (results, NULL);
if (G_TYPE_IS_INTERFACE (exten_type))
{
- add_all_prerequisites (exten_type, base_type, ifaces);
- return ifaces;
+ add_all_prerequisites (exten_type, &base_type, results);
}
+ else
+ {
+ gint i;
+ GType *interfaces;
+
+ interfaces = g_type_interfaces (exten_type, NULL);
+ for (i = 0; interfaces[i] != G_TYPE_INVALID; ++i)
+ add_all_prerequisites (interfaces[i], &base_type, results);
- interfaces = g_type_interfaces (exten_type, NULL);
- for (i = 0; interfaces[i] != G_TYPE_INVALID; ++i)
- add_all_prerequisites (exten_type, base_type, ifaces);
+ base_type = exten_type;
- *base_type = exten_type;
+ g_free (interfaces);
+ }
- g_free (interfaces);
- return ifaces;
+ if (base_type != G_TYPE_INVALID)
+ g_ptr_array_index (results, 0) = g_type_class_ref (base_type);
+
+ g_ptr_array_add (results, NULL);
+ data = g_ptr_array_free (results, FALSE);
+
+ g_mutex_lock (&cache_lock);
+ cached_data = g_type_get_qdata (exten_type, exten_type_cache_quark ());
+
+ if (cached_data != NULL)
+ {
+ g_free (data);
+ data = cached_data;
+ }
+ else
+ {
+ g_type_set_qdata (exten_type, exten_type_cache_quark (), data);
+ }
+
+ g_mutex_unlock (&cache_lock);
+ return data;
}
-static GParamSpec *
+static inline gpointer *
+get_base_class_and_interfaces (GType exten_type,
+ GObjectClass **base_class)
+{
+ gpointer *data;
+
+ data = g_type_get_qdata (exten_type, exten_type_cache_quark ());
+ if (G_UNLIKELY (data == NULL))
+ data = find_base_class_and_interfaces (exten_type);
+
+ *base_class = data[0];
+ return &data[1];
+}
+
+static inline GParamSpec *
find_param_spec_for_prerequisites (const gchar *name,
- GObjectClass *klass,
- GPtrArray *ifaces)
+ GObjectClass *base_class,
+ gpointer *ifaces)
{
guint i;
GParamSpec *pspec = NULL;
- if (klass != NULL)
- pspec = g_object_class_find_property (klass, name);
-
- for (i = 0; i < ifaces->len && pspec == NULL; ++i)
- {
- gpointer iface = g_ptr_array_index (ifaces, i);
+ if (base_class != NULL)
+ pspec = g_object_class_find_property (base_class, name);
- pspec = g_object_interface_find_property (iface, name);
- }
+ for (i = 0; ifaces[i] != NULL && pspec == NULL; ++i)
+ pspec = g_object_interface_find_property (ifaces[i], name);
return pspec;
}
@@ -147,19 +187,15 @@ peas_utils_valist_to_parameter_list (GType exten_type,
GParameter **params,
guint *n_params)
{
- GPtrArray *ifaces;
- GType base_type = G_TYPE_INVALID;
- GObjectClass *klass = NULL;
+ gpointer *ifaces;
+ GObjectClass *base_class;
const gchar *name;
guint n_allocated_params;
g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) ||
G_TYPE_IS_OBJECT (exten_type), FALSE);
- ifaces = find_base_type_and_interfaces (exten_type, &base_type);
-
- if (base_type != G_TYPE_INVALID)
- klass = g_type_class_ref (base_type);
+ ifaces = get_base_class_and_interfaces (exten_type, &base_class);
*n_params = 0;
n_allocated_params = 16;
@@ -171,7 +207,7 @@ peas_utils_valist_to_parameter_list (GType exten_type,
gchar *error_msg = NULL;
GParamSpec *pspec;
- pspec = find_param_spec_for_prerequisites (name, klass, ifaces);
+ pspec = find_param_spec_for_prerequisites (name, base_class, ifaces);
if (!pspec)
{
@@ -204,9 +240,6 @@ peas_utils_valist_to_parameter_list (GType exten_type,
name = va_arg (args, gchar*);
}
- g_ptr_array_unref (ifaces);
- g_clear_pointer (&klass, g_type_class_unref);
-
return TRUE;
error:
@@ -215,9 +248,6 @@ error:
g_value_unset (&(*params)[*n_params].value);
g_free (*params);
- g_ptr_array_unref (ifaces);
- g_clear_pointer (&klass, g_type_class_unref);
-
return FALSE;
}