diff options
author | Dan Winship <danw@gnome.org> | 2011-06-21 18:21:27 -0400 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2011-10-04 13:20:34 -0400 |
commit | 1481b7bca3c24149a2970758bc8762e1318f361e (patch) | |
tree | f2c9a026703eb65ea4ec724a385d4bff483a4f20 /gio/giomodule.c | |
parent | 38d21f6d8a761cf211c0e0ca21c394b4824d13f2 (diff) | |
download | glib-1481b7bca3c24149a2970758bc8762e1318f361e.tar.gz glib-1481b7bca3c24149a2970758bc8762e1318f361e.tar.bz2 glib-1481b7bca3c24149a2970758bc8762e1318f361e.zip |
Add _g_io_module_get_default(), use to simplify other *_get_default()s
Add _g_io_module_get_default(), which implements the
figure-out-the-best-available-module-that-is-actually-usable logic,
and use that to simplify g_proxy_resolver_get_default(),
g_settings_backend_get_default(), g_tls_backend_get_default(), and
g_vfs_get_default().
https://bugzilla.gnome.org/show_bug.cgi?id=620932
Diffstat (limited to 'gio/giomodule.c')
-rw-r--r-- | gio/giomodule.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/gio/giomodule.c b/gio/giomodule.c index 2763a98a8..61638c08f 100644 --- a/gio/giomodule.c +++ b/gio/giomodule.c @@ -630,6 +630,133 @@ g_io_modules_load_all_in_directory (const char *dirname) 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); |