void _g_io_modules_ensure_extension_points_registered (void);
void _g_io_modules_ensure_loaded (void);
+typedef gboolean (*GIOModuleVerifyFunc) (gpointer);
+gpointer _g_io_module_get_default (const gchar *extension_point,
+ const gchar *envvar,
+ GIOModuleVerifyFunc verify_func);
+
G_END_DECLS
#endif /* __G_IO_MODULE_PRIV_H__ */
return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
}
+G_LOCK_DEFINE_STATIC (default_modules);
+GHashTable *default_modules;
+
+static gpointer
+try_implementation (GIOExtension *extension,
+ GIOModuleVerifyFunc verify_func)
+{
+ GType type = g_io_extension_get_type (extension);
+ gpointer impl;
+
+ if (g_type_is_a (type, G_TYPE_INITABLE))
+ return g_initable_new (type, NULL, NULL, NULL);
+ else
+ {
+ impl = g_object_new (type, NULL);
+ if (!verify_func || verify_func (impl))
+ return impl;
+
+ g_object_unref (impl);
+ return NULL;
+ }
+}
+
+/**
+ * _g_io_module_get_default:
+ * @extension_point: the name of an extension point
+ * @envvar: (allow-none): the name of an environment variable to
+ * override the default implementation.
+ * @verify_func: (allow-none): a function to call to verify that
+ * a given implementation is usable in the current environment.
+ *
+ * Retrieves the default object implementing @extension_point.
+ *
+ * If @envvar is not %NULL, and the environment variable with that
+ * name is set, then the implementation it specifies will be tried
+ * first. After that, or if @envvar is not set, all other
+ * implementations will be tried in order of decreasing priority.
+ *
+ * If an extension point implementation implements #GInitable, then
+ * that implementation will only be used if it initializes
+ * successfully. Otherwise, if @verify_func is not %NULL, then it will
+ * be called on each candidate implementation after construction, to
+ * check if it is actually usable or not.
+ *
+ * The result is cached after it is generated the first time, and
+ * the function is thread-safe.
+ *
+ * Return value: (transfer none): an object implementing
+ * @extension_point, or %NULL if there are no usable
+ * implementations.
+ */
+gpointer
+_g_io_module_get_default (const gchar *extension_point,
+ const gchar *envvar,
+ GIOModuleVerifyFunc verify_func)
+{
+ const char *use_this;
+ GList *l;
+ GIOExtensionPoint *ep;
+ GIOExtension *extension, *preferred;
+ gpointer impl;
+
+ G_LOCK (default_modules);
+ if (default_modules)
+ {
+ gpointer key;
+
+ if (g_hash_table_lookup_extended (default_modules, extension_point,
+ &key, &impl))
+ {
+ G_UNLOCK (default_modules);
+ return impl;
+ }
+ }
+ else
+ {
+ default_modules = g_hash_table_new (g_str_hash, g_str_equal);
+ }
+
+ _g_io_modules_ensure_loaded ();
+ ep = g_io_extension_point_lookup (extension_point);
+
+ if (!ep)
+ {
+ g_warn_if_reached ();
+ G_UNLOCK (default_modules);
+ return NULL;
+ }
+
+ use_this = envvar ? g_getenv (envvar) : NULL;
+ if (use_this)
+ {
+ preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
+ if (preferred)
+ {
+ impl = try_implementation (preferred, verify_func);
+ if (impl)
+ goto done;
+ }
+ else
+ g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
+ }
+ else
+ preferred = NULL;
+
+ for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
+ {
+ extension = l->data;
+ if (extension == preferred)
+ continue;
+
+ impl = try_implementation (extension, verify_func);
+ if (impl)
+ goto done;
+ }
+
+ impl = NULL;
+
+ done:
+ g_hash_table_insert (default_modules,
+ g_strdup (extension_point),
+ impl ? g_object_ref (impl) : NULL);
+ G_UNLOCK (default_modules);
+
+ return impl;
+}
+
G_LOCK_DEFINE_STATIC (registered_extensions);
G_LOCK_DEFINE_STATIC (loaded_dirs);
{
}
-static gpointer
-get_default_proxy_resolver (gpointer arg)
-{
- const gchar *use_this;
- GProxyResolver *resolver;
- GList *l;
- GIOExtensionPoint *ep;
- GIOExtension *extension;
-
-
- use_this = g_getenv ("GIO_USE_PROXY_RESOLVER");
-
- /* Ensure proxy-resolver modules loaded */
- _g_io_modules_ensure_loaded ();
-
- ep = g_io_extension_point_lookup (G_PROXY_RESOLVER_EXTENSION_POINT_NAME);
-
- if (use_this)
- {
- extension = g_io_extension_point_get_extension_by_name (ep, use_this);
- if (extension)
- {
- resolver = g_object_new (g_io_extension_get_type (extension), NULL);
-
- if (g_proxy_resolver_is_supported (resolver))
- return resolver;
-
- g_object_unref (resolver);
- }
- }
-
- for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
- {
- extension = l->data;
-
- resolver = g_object_new (g_io_extension_get_type (extension), NULL);
-
- if (g_proxy_resolver_is_supported (resolver))
- return resolver;
-
- g_object_unref (resolver);
- }
-
- return NULL;
-}
-
/**
* g_proxy_resolver_get_default:
*
GProxyResolver *
g_proxy_resolver_get_default (void)
{
- static GOnce once_init = G_ONCE_INIT;
-
- return g_once (&once_init, get_default_proxy_resolver, NULL);
+ return _g_io_module_get_default (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
+ "GIO_USE_PROXY_RESOLVER",
+ (GIOModuleVerifyFunc)g_proxy_resolver_is_supported);
}
/**
g_free, g_settings_backend_variant_unref0);
}
+static gboolean
+g_settings_backend_verify (gpointer impl)
+{
+ GSettingsBackend *backend = impl;
+
+ if (strcmp (G_OBJECT_TYPE_NAME (backend), "GMemorySettingsBackend") == 0 &&
+ g_strcmp0 (g_getenv ("GSETTINGS_BACKEND"), "memory") != 0)
+ {
+ g_message ("Using the 'memory' GSettings backend. Your settings "
+ "will not be saved or shared with other applications.");
+ }
+
+ g_settings_has_backend = TRUE;
+ return TRUE;
+}
+
/**
* g_settings_backend_get_default:
* @returns: (transfer full): the default #GSettingsBackend
GSettingsBackend *
g_settings_backend_get_default (void)
{
- static gsize backend;
-
- if (g_once_init_enter (&backend))
- {
- GSettingsBackend *instance;
- GIOExtensionPoint *point;
- GIOExtension *extension;
- GType extension_type;
- GList *extensions;
- const gchar *env;
-
- _g_io_modules_ensure_loaded ();
-
- point = g_io_extension_point_lookup (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME);
- extension = NULL;
-
- if ((env = getenv ("GSETTINGS_BACKEND")))
- {
- extension = g_io_extension_point_get_extension_by_name (point, env);
-
- if (extension == NULL)
- g_warning ("Can't find GSettings backend '%s' given in "
- "GSETTINGS_BACKEND environment variable", env);
- }
-
- if (extension == NULL)
- {
- extensions = g_io_extension_point_get_extensions (point);
- extension = extensions->data;
-
- if (strcmp (g_io_extension_get_name (extension), "memory") == 0)
- g_message ("Using the 'memory' GSettings backend. Your settings "
- "will not be saved or shared with other applications.");
- }
-
- extension_type = g_io_extension_get_type (extension);
- instance = g_object_new (extension_type, NULL);
- g_settings_has_backend = TRUE;
-
- g_once_init_leave (&backend, (gsize) instance);
- }
+ GSettingsBackend *backend;
- return g_object_ref ((void *) backend);
+ backend = _g_io_module_get_default (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME,
+ "GSETTINGS_BACKEND",
+ g_settings_backend_verify);
+ return g_object_ref (backend);
}
/*< private >
{
}
-static gpointer
-get_default_tls_backend (gpointer arg)
-{
- const char *use_this;
- GList *extensions;
- GIOExtensionPoint *ep;
- GIOExtension *extension;
-
- _g_io_modules_ensure_loaded ();
-
- ep = g_io_extension_point_lookup (G_TLS_BACKEND_EXTENSION_POINT_NAME);
-
- use_this = g_getenv ("GIO_USE_TLS");
- if (use_this)
- {
- extension = g_io_extension_point_get_extension_by_name (ep, use_this);
- if (extension)
- return g_object_new (g_io_extension_get_type (extension), NULL);
- }
-
- extensions = g_io_extension_point_get_extensions (ep);
- if (extensions)
- {
- extension = extensions->data;
- return g_object_new (g_io_extension_get_type (extension), NULL);
- }
-
- return NULL;
-}
-
/**
* g_tls_backend_get_default:
*
GTlsBackend *
g_tls_backend_get_default (void)
{
- static GOnce once_init = G_ONCE_INIT;
-
- return g_once (&once_init, get_default_tls_backend, NULL);
+ return _g_io_module_get_default (G_TLS_BACKEND_EXTENSION_POINT_NAME,
+ "GIO_USE_TLS", NULL);
}
/**
return (* class->parse_name) (vfs, parse_name);
}
-static gpointer
-get_default_vfs (gpointer arg)
-{
- const char *use_this;
- GVfs *vfs;
- GList *l;
- GIOExtensionPoint *ep;
- GIOExtension *extension;
-
-
- use_this = g_getenv ("GIO_USE_VFS");
-
- /* Ensure vfs in modules loaded */
- _g_io_modules_ensure_loaded ();
-
- ep = g_io_extension_point_lookup (G_VFS_EXTENSION_POINT_NAME);
-
- if (use_this)
- {
- extension = g_io_extension_point_get_extension_by_name (ep, use_this);
- if (extension)
- {
- vfs = g_object_new (g_io_extension_get_type (extension), NULL);
-
- if (g_vfs_is_active (vfs))
- return vfs;
-
- g_object_unref (vfs);
- }
- }
-
- for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
- {
- extension = l->data;
-
- vfs = g_object_new (g_io_extension_get_type (extension), NULL);
-
- if (g_vfs_is_active (vfs))
- return vfs;
-
- g_object_unref (vfs);
- }
-
-
- return NULL;
-}
-
/**
* g_vfs_get_default:
*
GVfs *
g_vfs_get_default (void)
{
- static GOnce once_init = G_ONCE_INIT;
-
- return g_once (&once_init, get_default_vfs, NULL);
+ return _g_io_module_get_default (G_VFS_EXTENSION_POINT_NAME,
+ "GIO_USE_VFS",
+ (GIOModuleVerifyFunc)g_vfs_is_active);
}
/**