diff options
author | Alexander Larsson <alexl@redhat.com> | 2012-01-10 16:40:45 +0100 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2012-01-13 17:13:41 +0100 |
commit | 3fabc2d5def16638cd9c9bde8ac13aa507810dab (patch) | |
tree | 05b37a466e32c7960c8fd06755fed1fcb47251ed | |
parent | b1ef79eb0d93bbf5533ad2f0d612b9fba91faff4 (diff) | |
download | glib-wip/resources2.tar.gz |
Allow resources to work with unloadable GTypeModuleswip/resources2
-rw-r--r-- | gio/gio.symbols | 1 | ||||
-rw-r--r-- | gio/gresource.c | 58 | ||||
-rw-r--r-- | gio/gresource.h | 2 | ||||
-rw-r--r-- | gio/tests/resourceplugin.c | 4 | ||||
-rw-r--r-- | gio/tests/resources.c | 18 |
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); |