mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 23:46:17 +01:00
giomodule: add a new "get default" function
_gio_module_get_default() is a very convenient function for modules implementing a singleton -- it finds the default module by priority subject to override by a given environment variable name, instantiates it, and caches the instance for future calls. It also has the ability to query instances for being 'active' using a callback. It doesn't work very well for non-singletons (like file monitors). Add a new function _gio_module_get_default_type() that skips the instantiation, returning the GType instead. As a replacement for the 'active' callback, a vtable offset can be given for a virtual function to use to query if a particular backend is supported. https://bugzilla.gnome.org/show_bug.cgi?id=592211
This commit is contained in:
parent
ca58dae277
commit
3a7b44c007
@ -35,6 +35,10 @@ gpointer _g_io_module_get_default (const gchar *extension_point,
|
|||||||
const gchar *envvar,
|
const gchar *envvar,
|
||||||
GIOModuleVerifyFunc verify_func);
|
GIOModuleVerifyFunc verify_func);
|
||||||
|
|
||||||
|
GType _g_io_module_get_default_type (const gchar *extension_point,
|
||||||
|
const gchar *envvar,
|
||||||
|
guint is_supported_offset);
|
||||||
|
|
||||||
#ifdef G_PLATFORM_WIN32
|
#ifdef G_PLATFORM_WIN32
|
||||||
void *_g_io_win32_get_module (void);
|
void *_g_io_win32_get_module (void);
|
||||||
#endif
|
#endif
|
||||||
|
120
gio/giomodule.c
120
gio/giomodule.c
@ -628,8 +628,122 @@ g_io_modules_load_all_in_directory (const char *dirname)
|
|||||||
return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
|
return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRecMutex default_modules_lock;
|
static gpointer
|
||||||
GHashTable *default_modules;
|
try_class (GIOExtension *extension,
|
||||||
|
guint is_supported_offset)
|
||||||
|
{
|
||||||
|
GType type = g_io_extension_get_type (extension);
|
||||||
|
typedef gboolean (*verify_func) (void);
|
||||||
|
gpointer class;
|
||||||
|
|
||||||
|
class = g_type_class_ref (type);
|
||||||
|
if (!is_supported_offset || (* G_STRUCT_MEMBER(verify_func, class, is_supported_offset)) ())
|
||||||
|
return class;
|
||||||
|
|
||||||
|
g_type_class_unref (class);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _g_io_module_get_default_type:
|
||||||
|
* @extension_point: the name of an extension point
|
||||||
|
* @envvar: (allow-none): the name of an environment variable to
|
||||||
|
* override the default implementation.
|
||||||
|
* @is_supported_offset: a vtable offset, or zero
|
||||||
|
*
|
||||||
|
* Retrieves the default class 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 @is_supported_offset is non-zero, then it is the offset into the
|
||||||
|
* class vtable at which there is a function that takes no arguments and
|
||||||
|
* returns a boolean. This function will be called on each candidate
|
||||||
|
* implementation 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.
|
||||||
|
*/
|
||||||
|
GType
|
||||||
|
_g_io_module_get_default_type (const gchar *extension_point,
|
||||||
|
const gchar *envvar,
|
||||||
|
guint is_supported_offset)
|
||||||
|
{
|
||||||
|
static GRecMutex default_modules_lock;
|
||||||
|
static GHashTable *default_modules;
|
||||||
|
const char *use_this;
|
||||||
|
GList *l;
|
||||||
|
GIOExtensionPoint *ep;
|
||||||
|
GIOExtension *extension, *preferred;
|
||||||
|
gpointer impl;
|
||||||
|
|
||||||
|
g_rec_mutex_lock (&default_modules_lock);
|
||||||
|
if (default_modules)
|
||||||
|
{
|
||||||
|
gpointer key;
|
||||||
|
|
||||||
|
if (g_hash_table_lookup_extended (default_modules, extension_point, &key, &impl))
|
||||||
|
{
|
||||||
|
g_rec_mutex_unlock (&default_modules_lock);
|
||||||
|
return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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_rec_mutex_unlock (&default_modules_lock);
|
||||||
|
return G_TYPE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_class (preferred, is_supported_offset);
|
||||||
|
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_class (extension, is_supported_offset);
|
||||||
|
if (impl)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl = NULL;
|
||||||
|
|
||||||
|
done:
|
||||||
|
g_hash_table_insert (default_modules, g_strdup (extension_point), impl);
|
||||||
|
g_rec_mutex_unlock (&default_modules_lock);
|
||||||
|
|
||||||
|
return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
try_implementation (GIOExtension *extension,
|
try_implementation (GIOExtension *extension,
|
||||||
@ -684,6 +798,8 @@ _g_io_module_get_default (const gchar *extension_point,
|
|||||||
const gchar *envvar,
|
const gchar *envvar,
|
||||||
GIOModuleVerifyFunc verify_func)
|
GIOModuleVerifyFunc verify_func)
|
||||||
{
|
{
|
||||||
|
static GRecMutex default_modules_lock;
|
||||||
|
static GHashTable *default_modules;
|
||||||
const char *use_this;
|
const char *use_this;
|
||||||
GList *l;
|
GList *l;
|
||||||
GIOExtensionPoint *ep;
|
GIOExtensionPoint *ep;
|
||||||
|
Loading…
Reference in New Issue
Block a user