From 8b67d53e5643482bd9368923b6548bead7380959 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 19 Dec 2012 09:58:35 +0000 Subject: [PATCH] make VipsArea threadsafe google maps output needs threaded create / destroy of VipsArea (used to hold the background colour). We need a lock on VipsArea::count. Fixes https://github.com/jcupitt/libvips/issues/46 Thanks fuho --- ChangeLog | 1 + libvips/foreign/dzsave.c | 14 +++++++++++--- libvips/include/vips/type.h | 6 +++++- libvips/iofuncs/type.c | 13 +++++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 64a3b0fb..5ba57ca4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -32,6 +32,7 @@ - added vips_bandbool(), with vips_bandand(), _bandor(), _bandeor() as convenience functions - added scRGB colourspace, linear light float space with sRGB primaries +- VipsArea is threadsafe 14/11/12 started 7.30.6 - capture tiff warnings earlier diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index e8bd1af3..fd6fa07a 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -1046,6 +1046,17 @@ vips_foreign_save_dz_build( VipsObject *object ) VIPS_SETSTR( dz->suffix, ".jpg" ); } + /* Default to white background. + */ + if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE && + !vips_object_argument_isset( object, "background" ) ) { + VipsArrayDouble *background; + + background = vips_array_double_newv( 1, 255.0 ); + g_object_set( object, "background", background, NULL ); + vips_area_unref( background ); + } + if( dz->overlap >= dz->tile_size || dz->overlap >= dz->tile_size ) { vips_error( "dzsave", @@ -1231,9 +1242,6 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz ) dz->overlap = 1; dz->tile_size = 256; dz->tile_count = 0; - dz->background = - vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), 1 ); - ((double *) (dz->background->data))[0] = 255; dz->depth = VIPS_FOREIGN_DZ_DEPTH_1PIXEL; } diff --git a/libvips/include/vips/type.h b/libvips/include/vips/type.h index 053ff11e..be96829d 100644 --- a/libvips/include/vips/type.h +++ b/libvips/include/vips/type.h @@ -66,9 +66,13 @@ typedef struct _VipsArea { /*< private >*/ - /* Reference count. + /* Reference count and lock. + * + * We could use an atomic int, but this is not a high-traffic data + * structure, so a simple GMutex is OK. */ int count; + GMutex *lock; /* Things like ICC profiles need their own free functions. */ diff --git a/libvips/iofuncs/type.c b/libvips/iofuncs/type.c index dfe68915..cd80bfb1 100644 --- a/libvips/iofuncs/type.c +++ b/libvips/iofuncs/type.c @@ -147,6 +147,8 @@ static int vips_area_number = 0; VipsArea * vips_area_copy( VipsArea *area ) { + g_mutex_lock( area->lock ); + g_assert( area->count >= 0 ); area->count += 1; @@ -155,12 +157,16 @@ vips_area_copy( VipsArea *area ) printf( "vips_area_copy: %p count = %d\n", area, area->count ); #endif /*DEBUG*/ + g_mutex_unlock( area->lock ); + return( area ); } void vips_area_unref( VipsArea *area ) { + g_mutex_lock( area->lock ); + g_assert( area->count > 0 ); area->count -= 1; @@ -176,6 +182,10 @@ vips_area_unref( VipsArea *area ) area->free_fn = NULL; } + g_mutex_unlock( area->lock ); + + VIPS_FREEF( vips_g_mutex_free, area->lock ); + g_free( area ); #ifdef DEBUG @@ -184,6 +194,8 @@ vips_area_unref( VipsArea *area ) vips_area_number ); #endif /*DEBUG*/ } + else + g_mutex_unlock( area->lock ); } /** @@ -205,6 +217,7 @@ vips_area_new( VipsCallbackFn free_fn, void *data ) area = g_new( VipsArea, 1 ); area->count = 1; + area->lock = vips_g_mutex_new(); area->length = 0; area->data = data; area->free_fn = free_fn;