mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 05:01:23 +00:00
registry: allow plugin and feature filter funcs to call registry API
Don't keep the registry locked whilst iterating over the plugins or features with a filter function. This would deadlock if the callback tried to access the registry from the function. Instead, make a copy of the feature/plugin list and then filter it without holding the registry lock. This is still considerably faster than the alternative which would be to use a GstIterator. https://bugzilla.gnome.org/show_bug.cgi?id=756738
This commit is contained in:
parent
2a023cdc14
commit
f02d09c362
1 changed files with 39 additions and 24 deletions
|
@ -148,6 +148,7 @@ struct _GstRegistryPrivate
|
||||||
GList *plugins;
|
GList *plugins;
|
||||||
GList *features;
|
GList *features;
|
||||||
|
|
||||||
|
guint n_plugins;
|
||||||
#if 0
|
#if 0
|
||||||
GList *paths;
|
GList *paths;
|
||||||
#endif
|
#endif
|
||||||
|
@ -271,6 +272,7 @@ gst_registry_finalize (GObject * object)
|
||||||
|
|
||||||
plugins = registry->priv->plugins;
|
plugins = registry->priv->plugins;
|
||||||
registry->priv->plugins = NULL;
|
registry->priv->plugins = NULL;
|
||||||
|
registry->priv->n_plugins = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (registry, "registry finalize");
|
GST_DEBUG_OBJECT (registry, "registry finalize");
|
||||||
p = plugins;
|
p = plugins;
|
||||||
|
@ -465,6 +467,7 @@ gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
|
||||||
}
|
}
|
||||||
registry->priv->plugins =
|
registry->priv->plugins =
|
||||||
g_list_remove (registry->priv->plugins, existing_plugin);
|
g_list_remove (registry->priv->plugins, existing_plugin);
|
||||||
|
--registry->priv->n_plugins;
|
||||||
if (G_LIKELY (existing_plugin->basename))
|
if (G_LIKELY (existing_plugin->basename))
|
||||||
g_hash_table_remove (registry->priv->basename_hash,
|
g_hash_table_remove (registry->priv->basename_hash,
|
||||||
existing_plugin->basename);
|
existing_plugin->basename);
|
||||||
|
@ -476,6 +479,8 @@ gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
|
||||||
plugin, GST_STR_NULL (plugin->filename));
|
plugin, GST_STR_NULL (plugin->filename));
|
||||||
|
|
||||||
registry->priv->plugins = g_list_prepend (registry->priv->plugins, plugin);
|
registry->priv->plugins = g_list_prepend (registry->priv->plugins, plugin);
|
||||||
|
++registry->priv->n_plugins;
|
||||||
|
|
||||||
if (G_LIKELY (plugin->basename))
|
if (G_LIKELY (plugin->basename))
|
||||||
g_hash_table_replace (registry->priv->basename_hash, plugin->basename,
|
g_hash_table_replace (registry->priv->basename_hash, plugin->basename,
|
||||||
plugin);
|
plugin);
|
||||||
|
@ -541,6 +546,7 @@ gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin)
|
||||||
|
|
||||||
GST_OBJECT_LOCK (registry);
|
GST_OBJECT_LOCK (registry);
|
||||||
registry->priv->plugins = g_list_remove (registry->priv->plugins, plugin);
|
registry->priv->plugins = g_list_remove (registry->priv->plugins, plugin);
|
||||||
|
--registry->priv->n_plugins;
|
||||||
if (G_LIKELY (plugin->basename))
|
if (G_LIKELY (plugin->basename))
|
||||||
g_hash_table_remove (registry->priv->basename_hash, plugin->basename);
|
g_hash_table_remove (registry->priv->basename_hash, plugin->basename);
|
||||||
gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
|
gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
|
||||||
|
@ -657,26 +663,30 @@ GList *
|
||||||
gst_registry_plugin_filter (GstRegistry * registry,
|
gst_registry_plugin_filter (GstRegistry * registry,
|
||||||
GstPluginFilter filter, gboolean first, gpointer user_data)
|
GstPluginFilter filter, gboolean first, gpointer user_data)
|
||||||
{
|
{
|
||||||
GList *list = NULL;
|
GstPlugin **plugins;
|
||||||
|
GList *walk, *list = NULL;
|
||||||
|
guint n_plugins, i;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
|
g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (registry);
|
GST_OBJECT_LOCK (registry);
|
||||||
{
|
n_plugins = registry->priv->n_plugins;
|
||||||
const GList *walk;
|
plugins = g_newa (GstPlugin *, n_plugins + 1);
|
||||||
|
for (walk = registry->priv->plugins, i = 0; walk != NULL; walk = walk->next)
|
||||||
|
plugins[i++] = gst_object_ref (walk->data);
|
||||||
|
GST_OBJECT_UNLOCK (registry);
|
||||||
|
|
||||||
for (walk = registry->priv->plugins; walk != NULL; walk = walk->next) {
|
for (i = 0; i < n_plugins; ++i) {
|
||||||
GstPlugin *plugin = walk->data;
|
if (filter == NULL || filter (plugins[i], user_data)) {
|
||||||
|
list = g_list_prepend (list, gst_object_ref (plugins[i]));
|
||||||
if (filter == NULL || filter (plugin, user_data)) {
|
|
||||||
list = g_list_prepend (list, gst_object_ref (plugin));
|
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
GST_OBJECT_UNLOCK (registry);
|
for (i = 0; i < n_plugins; ++i)
|
||||||
|
gst_object_unref (plugins[i]);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -830,26 +840,30 @@ GList *
|
||||||
gst_registry_feature_filter (GstRegistry * registry,
|
gst_registry_feature_filter (GstRegistry * registry,
|
||||||
GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
|
GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
|
||||||
{
|
{
|
||||||
GList *list = NULL;
|
GstPluginFeature **features;
|
||||||
|
GList *walk, *list = NULL;
|
||||||
|
guint n_features, i;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
|
g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (registry);
|
GST_OBJECT_LOCK (registry);
|
||||||
{
|
n_features = g_hash_table_size (registry->priv->feature_hash);
|
||||||
const GList *walk;
|
features = g_newa (GstPluginFeature *, n_features + 1);
|
||||||
|
for (walk = registry->priv->features, i = 0; walk != NULL; walk = walk->next)
|
||||||
|
features[i++] = gst_object_ref (walk->data);
|
||||||
|
GST_OBJECT_UNLOCK (registry);
|
||||||
|
|
||||||
for (walk = registry->priv->features; walk != NULL; walk = walk->next) {
|
for (i = 0; i < n_features; ++i) {
|
||||||
GstPluginFeature *feature = walk->data;
|
if (filter == NULL || filter (features[i], user_data)) {
|
||||||
|
list = g_list_prepend (list, gst_object_ref (features[i]));
|
||||||
if (filter == NULL || filter (feature, user_data)) {
|
|
||||||
list = g_list_prepend (list, gst_object_ref (feature));
|
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
GST_OBJECT_UNLOCK (registry);
|
for (i = 0; i < n_features; ++i)
|
||||||
|
gst_object_unref (features[i]);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -1533,6 +1547,7 @@ gst_registry_remove_cache_plugins (GstRegistry * registry)
|
||||||
GST_DEBUG_OBJECT (registry, "removing cached plugin \"%s\"",
|
GST_DEBUG_OBJECT (registry, "removing cached plugin \"%s\"",
|
||||||
GST_STR_NULL (plugin->filename));
|
GST_STR_NULL (plugin->filename));
|
||||||
registry->priv->plugins = g_list_delete_link (registry->priv->plugins, g);
|
registry->priv->plugins = g_list_delete_link (registry->priv->plugins, g);
|
||||||
|
--registry->priv->n_plugins;
|
||||||
if (G_LIKELY (plugin->basename))
|
if (G_LIKELY (plugin->basename))
|
||||||
g_hash_table_remove (registry->priv->basename_hash, plugin->basename);
|
g_hash_table_remove (registry->priv->basename_hash, plugin->basename);
|
||||||
gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
|
gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
|
||||||
|
|
Loading…
Reference in a new issue