diff options
author | Matthias Clasen <mclasen@redhat.com> | 2004-11-12 05:34:31 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-11-12 05:34:31 +0000 |
commit | cb918cdb02c1c1fed54a86776a0888e236d2e198 (patch) | |
tree | a606b43b376cd1eeb9d3586634f20493d2b84635 /gdk-pixbuf/gdk-pixbuf-io.c | |
parent | 26cbda1b88e5e57533468cde10d51cd5baeeb871 (diff) | |
download | gtk+-cb918cdb02c1c1fed54a86776a0888e236d2e198.tar.gz |
Changes to make gdk-pixbuf threadsafe (#157310, #157306, Colin Walters):
2004-11-12 Matthias Clasen <mclasen@redhat.com>
Changes to make gdk-pixbuf threadsafe (#157310, #157306,
Colin Walters):
* gdk-pixbuf-io.h (enum GdkPixbufFormatFlags): Add
GDK_PIXBUF_FORMAT_THREADSAFE to indicate that an image loader
is threadsafe.
* gdk-pixbuf-io.c (get_file_formats, _gdk_pixbuf_load_module):
Use a lock to make initialization of global data structures
threadsafe.
* gdk-pixbuf-private.h:
* gdk-pixbuf-io.c (_gdk_pixbuf_lock, _gdk_pixbuf_unlock):
Auxiliary functions which use another lock to protect
threadunsafe image loaders.
* gdk-pixbuf-io.c (gdk_pixbuf_real_save):
(save_to_callback_with_tmp_file):
(gdk_pixbuf_real_save_to_callback):
(gdk_pixbuf_new_from_xpm_data):
(_gdk_pixbuf_generic_image_load):
* gdk-pixbuf-animation.c (gdk_pixbuf_animation_new_from_file):
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_load_module):
(gdk_pixbuf_loader_close):
(gdk_pixbuf_loader_finalize):
Use _gdk_pixbuf_lock() and _gdk_pixbuf_unlock().
* io-ani.c, io-bmp.c, io-gif.c, io-ico.c:
* io-jpeg.c, io-pcx.c, io-png.c, io-pnm.c:
* io-ras.c, io-tga.c, io-wbmp.c, io-xbm.c:
* io-xpm.c: Mark as threadsafe.
* io-tiff.c: Remove pointless locking, mark as
threadunsafe.
Diffstat (limited to 'gdk-pixbuf/gdk-pixbuf-io.c')
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-io.c | 201 |
1 files changed, 126 insertions, 75 deletions
diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c index 7e12ee6e16..9ad408748e 100644 --- a/gdk-pixbuf/gdk-pixbuf-io.c +++ b/gdk-pixbuf/gdk-pixbuf-io.c @@ -76,6 +76,25 @@ format_check (GdkPixbufModule *module, guchar *buffer, int size) return 0; } +G_LOCK_DEFINE_STATIC (init_lock); +G_LOCK_DEFINE_STATIC (threadunsafe_loader_lock); + +void +_gdk_pixbuf_lock (GdkPixbufModule *image_module) +{ + if (!(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) { + G_LOCK (threadunsafe_loader_lock); + } +} + +void +_gdk_pixbuf_unlock (GdkPixbufModule *image_module) +{ + if (!(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) { + G_UNLOCK (threadunsafe_loader_lock); + } +} + static GSList *file_formats = NULL; static void gdk_pixbuf_io_init (); @@ -83,8 +102,10 @@ static void gdk_pixbuf_io_init (); static GSList * get_file_formats (void) { + G_LOCK (init_lock); if (file_formats == NULL) gdk_pixbuf_io_init (); + G_UNLOCK (init_lock); return file_formats; } @@ -396,9 +417,9 @@ gdk_pixbuf_io_init (void) /* actually load the image handler - gdk_pixbuf_get_module only get a */ /* reference to the module to load, it doesn't actually load it */ /* perhaps these actions should be combined in one function */ -gboolean -_gdk_pixbuf_load_module (GdkPixbufModule *image_module, - GError **error) +static gboolean +_gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module, + GError **error) { char *path; GModule *module; @@ -433,6 +454,19 @@ _gdk_pixbuf_load_module (GdkPixbufModule *image_module, return FALSE; } } + +gboolean +_gdk_pixbuf_load_module (GdkPixbufModule *image_module, + GError **error) +{ + gboolean ret; + + G_LOCK (init_lock); + ret = _gdk_pixbuf_load_module_unlocked (image_module, error); + G_UNLOCK (init_lock); + + return ret; +} #else #define module(type) \ @@ -593,11 +627,11 @@ gdk_pixbuf_io_init () }; gchar **name; GdkPixbufModule *module = NULL; - + for (name = included_formats; *name; name++) { module = g_new0 (GdkPixbufModule, 1); module->module_name = *name; - if (_gdk_pixbuf_load_module (module, NULL)) + if (_gdk_pixbuf_load_module_unlocked (module, NULL)) file_formats = g_slist_prepend (file_formats, module); else g_free (module); @@ -703,37 +737,37 @@ _gdk_pixbuf_generic_image_load (GdkPixbufModule *module, GdkPixbufAnimation *animation = NULL; gpointer context; - if (module->load != NULL) - return (* module->load) (f, error); - - if (module->begin_load != NULL) { + _gdk_pixbuf_lock (module); + + if (module->load != NULL) { + pixbuf = (* module->load) (f, error); + } else if (module->begin_load != NULL) { context = module->begin_load (NULL, prepared_notify, NULL, &pixbuf, error); if (!context) - return NULL; + goto out; while (!feof (f) && !ferror (f)) { length = fread (buffer, 1, sizeof (buffer), f); if (length > 0) if (!module->load_increment (context, buffer, length, error)) { module->stop_load (context, NULL); - if (pixbuf != NULL) + if (pixbuf != NULL) { g_object_unref (pixbuf); - return NULL; + pixbuf = NULL; + } + goto out; } } if (!module->stop_load (context, error)) { - if (pixbuf != NULL) + if (pixbuf != NULL) { g_object_unref (pixbuf); - return NULL; + pixbuf = NULL; + } } - - return pixbuf; - } - - if (module->load_animation != NULL) { + } else if (module->load_animation != NULL) { animation = (* module->load_animation) (f, error); if (animation != NULL) { pixbuf = gdk_pixbuf_animation_get_static_image (animation); @@ -741,12 +775,12 @@ _gdk_pixbuf_generic_image_load (GdkPixbufModule *module, g_object_ref (pixbuf); g_object_unref (animation); - - return pixbuf; } } - return NULL; + out: + _gdk_pixbuf_unlock (module); + return pixbuf; } /** @@ -1134,14 +1168,18 @@ gdk_pixbuf_new_from_xpm_data (const char **data) return NULL; } } - + + _gdk_pixbuf_lock (xpm_module); + if (xpm_module->load_xpm_data == NULL) { g_warning ("gdk-pixbuf XPM module lacks XPM data capability"); - return NULL; - } else + pixbuf = NULL; + } else { load_xpm_data = xpm_module->load_xpm_data; + pixbuf = (* load_xpm_data) (data); + } - pixbuf = (* load_xpm_data) (data); + _gdk_pixbuf_unlock (xpm_module); return pixbuf; } @@ -1210,39 +1248,43 @@ gdk_pixbuf_real_save (GdkPixbuf *pixbuf, gchar **values, GError **error) { - GdkPixbufModule *image_module = NULL; + gboolean ret; + GdkPixbufModule *image_module = NULL; - image_module = _gdk_pixbuf_get_named_module (type, error); + image_module = _gdk_pixbuf_get_named_module (type, error); - if (image_module == NULL) - return FALSE; + if (image_module == NULL) + return FALSE; - if (image_module->module == NULL) - if (!_gdk_pixbuf_load_module (image_module, error)) - return FALSE; + if (image_module->module == NULL) + if (!_gdk_pixbuf_load_module (image_module, error)) + return FALSE; - if (image_module->save) { - /* save normally */ - return (* image_module->save) (filehandle, pixbuf, + _gdk_pixbuf_lock (image_module); + + if (image_module->save) { + /* save normally */ + ret = (* image_module->save) (filehandle, pixbuf, keys, values, error); - } - else if (image_module->save_to_callback) { - /* save with simple callback */ - return (* image_module->save_to_callback) (save_to_file_callback, + } else if (image_module->save_to_callback) { + /* save with simple callback */ + ret = (* image_module->save_to_callback) (save_to_file_callback, filehandle, pixbuf, keys, values, error); - } - else { - /* can't save */ - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION, - _("This build of gdk-pixbuf does not support saving the image format: %s"), - type); - return FALSE; - } + } else { + /* can't save */ + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION, + _("This build of gdk-pixbuf does not support saving the image format: %s"), + type); + ret = FALSE; + } + + _gdk_pixbuf_unlock (image_module); + return ret; } #define TMP_FILE_BUF_SIZE 4096 @@ -1283,8 +1325,13 @@ save_to_callback_with_tmp_file (GdkPixbufModule *image_module, _("Failed to open temporary file")); goto end; } - if (!(* image_module->save) (f, pixbuf, keys, values, error)) + + _gdk_pixbuf_lock (image_module); + retval = (image_module->save) (f, pixbuf, keys, values, error); + _gdk_pixbuf_unlock (image_module); + if (!retval) goto end; + rewind (f); for (;;) { n = fread (buf, 1, TMP_FILE_BUF_SIZE, f); @@ -1326,39 +1373,43 @@ gdk_pixbuf_real_save_to_callback (GdkPixbuf *pixbuf, gchar **values, GError **error) { - GdkPixbufModule *image_module = NULL; + gboolean ret; + GdkPixbufModule *image_module = NULL; - image_module = _gdk_pixbuf_get_named_module (type, error); + image_module = _gdk_pixbuf_get_named_module (type, error); - if (image_module == NULL) - return FALSE; + if (image_module == NULL) + return FALSE; - if (image_module->module == NULL) - if (!_gdk_pixbuf_load_module (image_module, error)) - return FALSE; + if (image_module->module == NULL) + if (!_gdk_pixbuf_load_module (image_module, error)) + return FALSE; + + _gdk_pixbuf_lock (image_module); - if (image_module->save_to_callback) { - /* save normally */ - return (* image_module->save_to_callback) (save_func, user_data, + if (image_module->save_to_callback) { + /* save normally */ + ret = (* image_module->save_to_callback) (save_func, user_data, pixbuf, keys, values, error); - } - else if (image_module->save) { - /* use a temporary file */ - return save_to_callback_with_tmp_file (image_module, pixbuf, + } else if (image_module->save) { + /* use a temporary file */ + ret = save_to_callback_with_tmp_file (image_module, pixbuf, save_func, user_data, keys, values, error); - } - else { - /* can't save */ - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION, - _("This build of gdk-pixbuf does not support saving the image format: %s"), - type); - return FALSE; - } + } else { + /* can't save */ + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION, + _("This build of gdk-pixbuf does not support saving the image format: %s"), + type); + ret = FALSE; + } + + _gdk_pixbuf_unlock (image_module); + return ret; } |