[glib] giomodule: When loading GIO_EXTRA_MODULES skip duplicates
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] giomodule: When loading GIO_EXTRA_MODULES skip duplicates
- Date: Fri, 26 Aug 2011 13:27:43 +0000 (UTC)
commit d789e78dff26d787b5a55c4b7f5858a7219d5a96
Author: Stef Walter <stefw collabora co uk>
Date: Fri Aug 26 15:27:19 2011 +0200
giomodule: When loading GIO_EXTRA_MODULES skip duplicates
* Load modules from paths listed in GIO_EXTRA_MODULES environment
variable first.
* Ignore duplicate modules based on module basename.
* Add the concept of GIOModuleScope which allows other callers to
skip duplicate loaded modules, or block specific modules based on
basename.
* Document behavior.
https://bugzilla.gnome.org/show_bug.cgi?id=656914
docs/reference/gio/gio-sections.txt | 5 +
gio/gio.symbols | 5 +
gio/gioenums.h | 16 +++
gio/giomodule.c | 202 ++++++++++++++++++++++++++++++++---
gio/giomodule.h | 12 ++
5 files changed, 224 insertions(+), 16 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 75f3ac8..d0c5e5d 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -1427,8 +1427,13 @@ g_desktop_app_info_lookup_get_type
<TITLE>GIOModule</TITLE>
GIOModule
g_io_module_new
+g_io_module_scope_block
+g_io_module_scope_free
+g_io_module_scope_new
g_io_modules_load_all_in_directory
+g_io_modules_load_all_in_directory_with_scope
g_io_modules_scan_all_in_directory
+g_io_modules_scan_all_in_directory_with_scope
g_io_module_load
g_io_module_unload
g_io_module_query
diff --git a/gio/gio.symbols b/gio/gio.symbols
index d6d78a5..b8dfb1a 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -503,8 +503,13 @@ g_io_error_from_win32_error
#endif
g_io_module_get_type
g_io_module_new
+g_io_module_scope_block
+g_io_module_scope_free
+g_io_module_scope_new
g_io_modules_scan_all_in_directory
+g_io_modules_scan_all_in_directory_with_scope
g_io_modules_load_all_in_directory
+g_io_modules_load_all_in_directory_with_scope
g_io_extension_point_register
g_io_extension_point_lookup
g_io_extension_point_set_required_type
diff --git a/gio/gioenums.h b/gio/gioenums.h
index c0ba757..2a23597 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -1498,6 +1498,22 @@ typedef enum {
G_TLS_DATABASE_LOOKUP_KEYPAIR = 1
} GTlsDatabaseLookupFlags;
+/**
+ * GIOModuleScopeFlags:
+ * @G_IO_MODULES_SCOPE_NONE: No module scan flags
+ * @G_IO_MODULES_SCOPE_BLOCK_DUPLICATES: When using this scope to load or
+ * scan modules, automatically block a modules which has the same base
+ * basename as previously loaded module.
+ *
+ * Flags for use with g_io_module_scope_new().
+ *
+ * Since: 2.30
+ */
+typedef enum {
+ G_IO_MODULE_SCOPE_NONE,
+ G_IO_MODULE_SCOPE_BLOCK_DUPLICATES
+} GIOModuleScopeFlags;
+
G_END_DECLS
#endif /* __GIO_ENUMS_H__ */
diff --git a/gio/giomodule.c b/gio/giomodule.c
index 4b77e3d..2b7e652 100644
--- a/gio/giomodule.c
+++ b/gio/giomodule.c
@@ -108,7 +108,103 @@
* see <link linkend="gio-querymodules">gio-querymodules</link>.
* You are expected to run this command after installing a
* GIO module.
+ *
+ * The <envar>GIO_EXTRA_MODULES</envar> environment variable can be
+ * used to specify additional directories to automatically load modules
+ * from. This environment variable has the same syntax as the
+ * <envar>PATH</envar>. If two modules have the same base name in different
+ * directories, then the latter one will be ignored. If additional
+ * directories are specified GIO will load modules from the built-in
+ * directory last.
+ */
+
+/**
+ * GIOModuleScope:
+ *
+ * Represents a scope for loading IO modules. A scope can be used for blocking
+ * duplicate modules, or blocking a module you don't want to load.
+ *
+ * The scope can be used with g_io_modules_load_all_in_directory_with_scope()
+ * or g_io_modules_scan_all_in_directory_with_scope().
+ *
+ * Since: 2.30
+ */
+struct _GIOModuleScope {
+ GIOModuleScopeFlags flags;
+ GHashTable *basenames;
+};
+
+/**
+ * g_io_module_scope_new:
+ * @flags: flags for the new scope
+ *
+ * Create a new scope for loading of IO modules. A scope can be used for
+ * blocking duplicate modules, or blocking a module you don't want to load.
+ *
+ * Specify the %G_IO_MODULES_SCOPE_BLOCK_DUPLICATES flag to block modules
+ * which have the same base name as a module that has already been seen
+ * in this scope.
+ *
+ * Returns: (transfer full): the new module scope
+ *
+ * Since: 2.30
+ */
+GIOModuleScope *
+g_io_module_scope_new (GIOModuleScopeFlags flags)
+{
+ GIOModuleScope *scope = g_new0 (GIOModuleScope, 1);
+ scope->flags = flags;
+ scope->basenames = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ return scope;
+}
+
+/**
+ * g_io_module_scope_free:
+ * @scope: a module loading scope
+ *
+ * Free a module scope.
+ *
+ * Since: 2.30
+ */
+void
+g_io_module_scope_free (GIOModuleScope *scope)
+{
+ if (!scope)
+ return;
+ g_hash_table_destroy (scope->basenames);
+ g_free (scope);
+}
+
+/**
+ * g_io_module_scope_block:
+ * @scope: a module loading scope
+ *
+ * Block modules with the given base name from being loaded when this scope
+ * is used with g_io_modules_scan_all_in_directory_with_scope() or
+ * g_io_modules_load_all_in_directory_with_scope().
+ *
+ * Since: 2.30
*/
+void
+g_io_module_scope_block (GIOModuleScope *scope,
+ const gchar *basename)
+{
+ gchar *key;
+
+ g_return_if_fail (scope != NULL);
+ g_return_if_fail (basename != NULL);
+
+ key = g_strdup (basename);
+ g_hash_table_insert (scope->basenames, key, key);
+}
+
+static gboolean
+_g_io_module_scope_contains (GIOModuleScope *scope,
+ const gchar *basename)
+{
+ return g_hash_table_lookup (scope->basenames, basename) ? TRUE : FALSE;
+}
+
struct _GIOModule {
GTypeModule parent_instance;
@@ -253,20 +349,36 @@ g_io_module_new (const gchar *filename)
}
static gboolean
-is_valid_module_name (const gchar *basename)
+is_valid_module_name (const gchar *basename,
+ GIOModuleScope *scope)
{
+ gboolean result;
+
#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
- return
- g_str_has_prefix (basename, "lib") &&
- g_str_has_suffix (basename, ".so");
+ if (!g_str_has_prefix (basename, "lib") ||
+ !g_str_has_suffix (basename, ".so"))
+ return FALSE;
#else
- return g_str_has_suffix (basename, ".dll");
+ if (!g_str_has_suffix (basename, ".dll"))
+ return FALSE;
#endif
+
+ result = TRUE;
+ if (scope)
+ {
+ result = _g_io_module_scope_contains (scope, basename) ? FALSE : TRUE;
+ if (result && (scope->flags & G_IO_MODULE_SCOPE_BLOCK_DUPLICATES))
+ g_io_module_scope_block (scope, basename);
+ }
+
+ return result;
}
+
/**
- * g_io_modules_scan_all_in_directory:
+ * g_io_modules_scan_all_in_directory_with_scope:
* @dirname: pathname for a directory containing modules to scan.
+ * @scope: a scope to use when scanning the modules
*
* Scans all the modules in the specified directory, ensuring that
* any extension point implemented by a module is registered.
@@ -280,10 +392,11 @@ is_valid_module_name (const gchar *basename)
* If you need to guarantee that all types are loaded in all the modules,
* use g_io_modules_load_all_in_directory().
*
- * Since: 2.24
+ * Since: 2.30
**/
void
-g_io_modules_scan_all_in_directory (const char *dirname)
+g_io_modules_scan_all_in_directory_with_scope (const char *dirname,
+ GIOModuleScope *scope)
{
const gchar *name;
char *filename;
@@ -353,7 +466,7 @@ g_io_modules_scan_all_in_directory (const char *dirname)
while ((name = g_dir_read_name (dir)))
{
- if (is_valid_module_name (name))
+ if (is_valid_module_name (name, scope))
{
GIOExtensionPoint *extension_point;
GIOModule *module;
@@ -404,10 +517,34 @@ g_io_modules_scan_all_in_directory (const char *dirname)
g_free (filename);
}
+/**
+ * g_io_modules_scan_all_in_directory:
+ * @dirname: pathname for a directory containing modules to scan.
+ *
+ * Scans all the modules in the specified directory, ensuring that
+ * any extension point implemented by a module is registered.
+ *
+ * This may not actually load and initialize all the types in each
+ * module, some modules may be lazily loaded and initialized when
+ * an extension point it implementes is used with e.g.
+ * g_io_extension_point_get_extensions() or
+ * g_io_extension_point_get_extension_by_name().
+ *
+ * If you need to guarantee that all types are loaded in all the modules,
+ * use g_io_modules_load_all_in_directory().
+ *
+ * Since: 2.24
+ **/
+void
+g_io_modules_scan_all_in_directory (const char *dirname)
+{
+ g_io_modules_scan_all_in_directory_with_scope (dirname, NULL);
+}
/**
- * g_io_modules_load_all_in_directory:
+ * g_io_modules_load_all_in_directory_with_scope:
* @dirname: pathname for a directory containing modules to load.
+ * @scope: a scope to use when scanning the modules.
*
* Loads all the modules in the specified directory.
*
@@ -421,9 +558,12 @@ g_io_modules_scan_all_in_directory (const char *dirname)
* unload them (enabling on-demand loading) you must call
* g_type_module_unuse() on all the modules. Free the list
* with g_list_free().
+ *
+ * Since: 2.30
**/
GList *
-g_io_modules_load_all_in_directory (const char *dirname)
+g_io_modules_load_all_in_directory_with_scope (const char *dirname,
+ GIOModuleScope *scope)
{
const gchar *name;
GDir *dir;
@@ -439,7 +579,7 @@ g_io_modules_load_all_in_directory (const char *dirname)
modules = NULL;
while ((name = g_dir_read_name (dir)))
{
- if (is_valid_module_name (name))
+ if (is_valid_module_name (name, scope))
{
GIOModule *module;
gchar *path;
@@ -466,6 +606,29 @@ g_io_modules_load_all_in_directory (const char *dirname)
return modules;
}
+/**
+ * g_io_modules_load_all_in_directory:
+ * @dirname: pathname for a directory containing modules to load.
+ *
+ * Loads all the modules in the specified directory.
+ *
+ * If don't require all modules to be initialized (and thus registering
+ * all gtypes) then you can use g_io_modules_scan_all_in_directory()
+ * which allows delayed/lazy loading of modules.
+ *
+ * Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
+ * from the directory,
+ * All the modules are loaded into memory, if you want to
+ * unload them (enabling on-demand loading) you must call
+ * g_type_module_unuse() on all the modules. Free the list
+ * with g_list_free().
+ **/
+GList *
+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 (registered_extensions);
G_LOCK_DEFINE_STATIC (loaded_dirs);
@@ -571,6 +734,7 @@ _g_io_modules_ensure_loaded (void)
{
static gboolean loaded_dirs = FALSE;
const char *module_path;
+ GIOModuleScope *scope;
_g_io_modules_ensure_extension_points_registered ();
@@ -579,11 +743,10 @@ _g_io_modules_ensure_loaded (void)
if (!loaded_dirs)
{
loaded_dirs = TRUE;
+ scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
- g_io_modules_scan_all_in_directory (GIO_MODULE_DIR);
-
+ /* First load any overrides, extras */
module_path = g_getenv ("GIO_EXTRA_MODULES");
-
if (module_path)
{
gchar **paths;
@@ -592,11 +755,18 @@ _g_io_modules_ensure_loaded (void)
paths = g_strsplit (module_path, ":", 0);
for (i = 0; paths[i] != NULL; i++)
- g_io_modules_scan_all_in_directory (paths[i]);
+ {
+ g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
+ }
g_strfreev (paths);
}
+ /* Then load the compiled in path */
+ g_io_modules_scan_all_in_directory_with_scope (GIO_MODULE_DIR, scope);
+
+ g_io_module_scope_free (scope);
+
/* Initialize types from built-in "modules" */
g_null_settings_backend_get_type ();
g_memory_settings_backend_get_type ();
diff --git a/gio/giomodule.h b/gio/giomodule.h
index 89619c8..5f04acb 100644
--- a/gio/giomodule.h
+++ b/gio/giomodule.h
@@ -32,6 +32,13 @@
G_BEGIN_DECLS
+typedef struct _GIOModuleScope GIOModuleScope;
+
+GIOModuleScope * g_io_module_scope_new (GIOModuleScopeFlags flags);
+void g_io_module_scope_free (GIOModuleScope *scope);
+void g_io_module_scope_block (GIOModuleScope *scope,
+ const gchar *basename);
+
#define G_IO_TYPE_MODULE (g_io_module_get_type ())
#define G_IO_MODULE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_IO_TYPE_MODULE, GIOModule))
#define G_IO_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_IO_TYPE_MODULE, GIOModuleClass))
@@ -52,6 +59,11 @@ GIOModule *g_io_module_new (const gchar
void g_io_modules_scan_all_in_directory (const char *dirname);
GList *g_io_modules_load_all_in_directory (const gchar *dirname);
+void g_io_modules_scan_all_in_directory_with_scope (const gchar *dirname,
+ GIOModuleScope *scope);
+GList *g_io_modules_load_all_in_directory_with_scope (const gchar *dirname,
+ GIOModuleScope *scope);
+
GIOExtensionPoint *g_io_extension_point_register (const char *name);
GIOExtensionPoint *g_io_extension_point_lookup (const char *name);
void g_io_extension_point_set_required_type (GIOExtensionPoint *extension_point,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]