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
This commit is contained in:
John Cupitt 2012-12-19 09:58:35 +00:00
parent c3a9f9cda5
commit 8b67d53e56
4 changed files with 30 additions and 4 deletions

View File

@ -32,6 +32,7 @@
- added vips_bandbool(), with vips_bandand(), _bandor(), _bandeor() as - added vips_bandbool(), with vips_bandand(), _bandor(), _bandeor() as
convenience functions convenience functions
- added scRGB colourspace, linear light float space with sRGB primaries - added scRGB colourspace, linear light float space with sRGB primaries
- VipsArea is threadsafe
14/11/12 started 7.30.6 14/11/12 started 7.30.6
- capture tiff warnings earlier - capture tiff warnings earlier

View File

@ -1046,6 +1046,17 @@ vips_foreign_save_dz_build( VipsObject *object )
VIPS_SETSTR( dz->suffix, ".jpg" ); 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 || if( dz->overlap >= dz->tile_size ||
dz->overlap >= dz->tile_size ) { dz->overlap >= dz->tile_size ) {
vips_error( "dzsave", vips_error( "dzsave",
@ -1231,9 +1242,6 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
dz->overlap = 1; dz->overlap = 1;
dz->tile_size = 256; dz->tile_size = 256;
dz->tile_count = 0; 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; dz->depth = VIPS_FOREIGN_DZ_DEPTH_1PIXEL;
} }

View File

@ -66,9 +66,13 @@ typedef struct _VipsArea {
/*< private >*/ /*< 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; int count;
GMutex *lock;
/* Things like ICC profiles need their own free functions. /* Things like ICC profiles need their own free functions.
*/ */

View File

@ -147,6 +147,8 @@ static int vips_area_number = 0;
VipsArea * VipsArea *
vips_area_copy( VipsArea *area ) vips_area_copy( VipsArea *area )
{ {
g_mutex_lock( area->lock );
g_assert( area->count >= 0 ); g_assert( area->count >= 0 );
area->count += 1; area->count += 1;
@ -155,12 +157,16 @@ vips_area_copy( VipsArea *area )
printf( "vips_area_copy: %p count = %d\n", area, area->count ); printf( "vips_area_copy: %p count = %d\n", area, area->count );
#endif /*DEBUG*/ #endif /*DEBUG*/
g_mutex_unlock( area->lock );
return( area ); return( area );
} }
void void
vips_area_unref( VipsArea *area ) vips_area_unref( VipsArea *area )
{ {
g_mutex_lock( area->lock );
g_assert( area->count > 0 ); g_assert( area->count > 0 );
area->count -= 1; area->count -= 1;
@ -176,6 +182,10 @@ vips_area_unref( VipsArea *area )
area->free_fn = NULL; area->free_fn = NULL;
} }
g_mutex_unlock( area->lock );
VIPS_FREEF( vips_g_mutex_free, area->lock );
g_free( area ); g_free( area );
#ifdef DEBUG #ifdef DEBUG
@ -184,6 +194,8 @@ vips_area_unref( VipsArea *area )
vips_area_number ); vips_area_number );
#endif /*DEBUG*/ #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 = g_new( VipsArea, 1 );
area->count = 1; area->count = 1;
area->lock = vips_g_mutex_new();
area->length = 0; area->length = 0;
area->data = data; area->data = data;
area->free_fn = free_fn; area->free_fn = free_fn;