From 37131e583490d1b09ade7ac34766d4c7ed472012 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 6 Jun 2016 11:03:31 +0100 Subject: [PATCH] not working tests --- TODO | 7 +++++++ libvips/iofuncs/buffer.c | 45 ++++++++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/TODO b/TODO index d9dd6ffd..d537ca22 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,10 @@ +- freeing buffer caches on image close does not work well, since we free regions + after images (strangely) + + can we free images earlier? + + vips_region_dispose() unrefs the buffer before it unrefs the image .. odd! + - below does not work for sharp .... we must free all buffers on close - we free buffers on vips__buffer_shutdown(), called from thread shutdown, diff --git a/libvips/iofuncs/buffer.c b/libvips/iofuncs/buffer.c index bb7f7ec7..c52c2e5c 100644 --- a/libvips/iofuncs/buffer.c +++ b/libvips/iofuncs/buffer.c @@ -178,10 +178,12 @@ buffer_thread_free( VipsBufferThread *buffer_thread ) } static void -buffer_cache_free( VipsBufferCache *cache ) +buffer_cache_image_postclose( VipsImage *im, VipsBufferCache *cache ) { GSList *p; + printf( "buffer_cache_image_postclose: im = %p\n", im ); + #ifdef DEBUG_CREATE g_mutex_lock( vips__global_lock ); vips__buffer_cache_all = @@ -194,16 +196,6 @@ buffer_cache_free( VipsBufferCache *cache ) g_slist_length( vips__buffer_cache_all ) ); #endif /*DEBUG_CREATE*/ - /* Need to mark undone so we don't try and take them off this hash on - * unref. - */ - for( p = cache->buffers; p; p = p->next ) { - VipsBuffer *buffer = (VipsBuffer *) p->data; - - buffer->done = FALSE; - } - VIPS_FREEF( g_slist_free, cache->buffers ); - for( p = cache->reserve; p; p = p->next ) { VipsBuffer *buffer = (VipsBuffer *) p->data; @@ -226,6 +218,13 @@ buffer_cache_new( VipsBufferThread *buffer_thread, VipsImage *im ) cache->buffer_thread = buffer_thread; cache->reserve = NULL; cache->n_reserve = 0; + + /* Free memory on image close. We can't do this on thread exit since + * some buffers will be made from the main thread and that won't exit + * until program termination. + */ + g_signal_connect( im, "postclose", + G_CALLBACK( buffer_cache_image_postclose ), cache ); #ifdef DEBUG_CREATE g_mutex_lock( vips__global_lock ); @@ -242,6 +241,22 @@ buffer_cache_new( VipsBufferThread *buffer_thread, VipsImage *im ) return( cache ); } +static void +buffer_cache_unlink( VipsBufferCache *cache ) +{ + GSList *p; + + /* Need to mark undone so we don't try and take them off this cache on + * unref. + */ + for( p = cache->buffers; p; p = p->next ) { + VipsBuffer *buffer = (VipsBuffer *) p->data; + + buffer->done = FALSE; + } + VIPS_FREEF( g_slist_free, cache->buffers ); +} + static VipsBufferThread * buffer_thread_new( void ) { @@ -250,7 +265,7 @@ buffer_thread_new( void ) buffer_thread = g_new( VipsBufferThread, 1 ); buffer_thread->hash = g_hash_table_new_full( g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) buffer_cache_free ); + NULL, (GDestroyNotify) buffer_cache_unlink ); buffer_thread->thread = g_thread_self(); return( buffer_thread ); @@ -582,7 +597,7 @@ vips_buffer_print( VipsBuffer *buffer ) } static void -vips__buffer_init_cb( VipsBufferThread *buffer_thread ) +buffer_thread_destroy_notify( VipsBufferThread *buffer_thread ) { /* We only come here if vips_thread_shutdown() was not called for this * thread. Do our best to clean up. @@ -599,13 +614,13 @@ vips__buffer_init( void ) { #ifdef HAVE_PRIVATE_INIT static GPrivate private = - G_PRIVATE_INIT( (GDestroyNotify) vips__buffer_init_cb ); + G_PRIVATE_INIT( (GDestroyNotify) buffer_thread_destroy_notify ); buffer_thread_key = &private; #else if( !buffer_thread_key ) buffer_thread_key = g_private_new( - (GDestroyNotify) vips__buffer_init_cb ); + (GDestroyNotify) buffer_thread_destroy_notify ); #endif if( buffer_cache_max_reserve < 1 )