summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2012-01-10 16:40:45 +0100
committerAlexander Larsson <alexl@redhat.com>2012-01-13 17:13:41 +0100
commit3fabc2d5def16638cd9c9bde8ac13aa507810dab (patch)
tree05b37a466e32c7960c8fd06755fed1fcb47251ed
parentb1ef79eb0d93bbf5533ad2f0d612b9fba91faff4 (diff)
downloadglib-wip/resources2.tar.gz
Allow resources to work with unloadable GTypeModuleswip/resources2
-rw-r--r--gio/gio.symbols1
-rw-r--r--gio/gresource.c58
-rw-r--r--gio/gresource.h2
-rw-r--r--gio/tests/resourceplugin.c4
-rw-r--r--gio/tests/resources.c18
5 files changed, 76 insertions, 7 deletions
diff --git a/gio/gio.symbols b/gio/gio.symbols
index dcf9ec785..22a8af09d 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1685,6 +1685,7 @@ g_resource_lookup_flags_get_type
g_resource_new_from_data
g_resource_open_stream
g_resource_ref
+g_resource_set_module
g_resource_unref
g_resources_enumerate_children
g_resources_get_info
diff --git a/gio/gresource.c b/gio/gresource.c
index d659df0cc..be377fd5e 100644
--- a/gio/gresource.c
+++ b/gio/gresource.c
@@ -36,6 +36,7 @@ struct _GResource
int ref_count;
GvdbTable *table;
+ GTypeModule *module;
};
G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
@@ -115,8 +116,10 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
*
* Note that resource data can point directly into the data segment of e.g. a library, so if you are unloading libraries
* during runtime you need to be very careful with keeping around pointers to data from a resource, as this goes away
- * when the library is unloaded. However, in practice this is not generally a problem, since most resource accesses
- * is for your own resources, and resource data is often used once, during parsing, and then released.
+ * when the library is unloaded. For modules using #GTypeModule we support disallowing unload while resources are
+ * outstanding by using g_resource_set_module(), but not all libraries might use this. However, in practice this is
+ * not generally a problem, since most resource accesses is for your own resources, and resource data is often
+ * used once, during parsing, and then released.
*
* Since: 2.32
*/
@@ -176,6 +179,51 @@ g_resource_unref (GResource *resource)
}
/**
+ * g_resource_set_module:
+ * @resource: A #GResource.
+ * @type_module: (allow-none): A #GTypeModule, or %NULL.
+ *
+ * Allows setting a #GTypeModule to be associated with the
+ * resource. As long as any reference to data from the
+ * resource is outstanding the GTypeModule is used, and
+ * thus will not be unloaded.
+ *
+ * This is useful if you link a resource into a module
+ * and want to ensure that its not unloaded while there
+ * is outstanding pointers into the linked in data.
+ *
+ * Since: 2.32
+ **/
+void
+g_resource_set_module (GResource *resource,
+ GTypeModule *type_module)
+{
+ if (resource->module)
+ g_object_unref (resource->module);
+
+ resource->module = type_module;
+
+ if (resource->module)
+ g_object_ref (resource->module);
+}
+
+static GResource *
+g_resource_use (GResource *resource)
+{
+ if (resource->module)
+ g_type_module_use (resource->module);
+ return g_resource_ref (resource);
+}
+
+static void
+g_resource_unuse (GResource *resource)
+{
+ if (resource->module)
+ g_type_module_unuse (resource->module);
+ g_resource_unref (resource);
+}
+
+/**
* g_resource_new_from_data:
* @data: A #GBytes.
* @error: return location for a #GError, or %NULL.
@@ -367,8 +415,8 @@ g_resource_open_stream (GResource *resource,
stream = g_memory_input_stream_new_from_data (data, data_size, NULL);
g_object_set_data_full (G_OBJECT (stream), "g-resource",
- g_resource_ref (resource),
- (GDestroyNotify)g_resource_unref);
+ g_resource_use (resource),
+ (GDestroyNotify)g_resource_unuse);
if (flags & G_RESOURCE_FLAGS_COMPRESSED)
{
@@ -474,7 +522,7 @@ g_resource_lookup_data (GResource *resource,
return g_bytes_new_take (uncompressed, size);
}
else
- return g_bytes_new_with_free_func (data, data_size, (GDestroyNotify)g_resource_unref, g_resource_ref (resource));
+ return g_bytes_new_with_free_func (data, data_size, (GDestroyNotify)g_resource_unuse, g_resource_use (resource));
}
/**
diff --git a/gio/gresource.h b/gio/gresource.h
index f1a8c8ee2..4691057b1 100644
--- a/gio/gresource.h
+++ b/gio/gresource.h
@@ -74,6 +74,8 @@ gboolean g_resource_get_info (GResource *resource,
gsize *size,
guint32 *flags,
GError **error);
+void g_resource_set_module (GResource *resource,
+ GTypeModule *type_module);
void g_resources_register (GResource *resource);
void g_resources_unregister (GResource *resource);
diff --git a/gio/tests/resourceplugin.c b/gio/tests/resourceplugin.c
index b66d54142..c1626ecaa 100644
--- a/gio/tests/resourceplugin.c
+++ b/gio/tests/resourceplugin.c
@@ -1,8 +1,11 @@
#include <gio/gio.h>
+extern GResource *_g_plugin_resource;
+
void
g_io_module_load (GIOModule *module)
{
+ g_resource_set_module (_g_plugin_resource, G_TYPE_MODULE (module));
}
void
@@ -15,4 +18,3 @@ g_io_module_query (void)
{
return NULL;
}
-
diff --git a/gio/tests/resources.c b/gio/tests/resources.c
index ed6a24964..bf3bd9f43 100644
--- a/gio/tests/resources.c
+++ b/gio/tests/resources.c
@@ -411,6 +411,8 @@ test_resource_module (void)
error = NULL;
+ /* Module is not loaded yet */
+
found = g_resources_get_info ("/resourceplugin/test1.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE,
&size, &flags, &error);
@@ -418,6 +420,8 @@ test_resource_module (void)
g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
g_clear_error (&error);
+ /* Load the module */
+
g_type_module_use (G_TYPE_MODULE (module));
found = g_resources_get_info ("/resourceplugin/test1.txt",
@@ -436,13 +440,25 @@ test_resource_module (void)
size = g_bytes_get_size (data);
g_assert (size == 6);
g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
- g_bytes_unref (data);
+ /* Don't unref data, should keep the module in use */
+
+ /* Unuse the module */
g_type_module_unuse (G_TYPE_MODULE (module));
found = g_resources_get_info ("/resourceplugin/test1.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE,
&size, &flags, &error);
+ g_assert (found);
+ g_assert_no_error (error);
+
+
+ /* Unref the data, should unload the module */
+ g_bytes_unref (data);
+
+ found = g_resources_get_info ("/resourceplugin/test1.txt",
+ G_RESOURCE_LOOKUP_FLAGS_NONE,
+ &size, &flags, &error);
g_assert (!found);
g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
g_clear_error (&error);