From eb5fee5e65f677342f0fd5df7d45a481d84fdbe1 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 1 Feb 2015 17:56:48 +0000 Subject: [PATCH] add lower-level cache access --- ChangeLog | 1 + libvips/include/vips/operation.h | 2 + libvips/iofuncs/cache.c | 132 ++++++++++++++++++++----------- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index a6b54000..1f6e1e95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ - fix some small leaks - faster openslide load, thanks Benjamin - add VInterpolate class to cplusplus binding, thanks Lovell +- add lower-level operation cache access 24/12/14 started 7.42.1 - add gobject-2.0 to Requires: in vips and vips-cpp .pc files diff --git a/libvips/include/vips/operation.h b/libvips/include/vips/operation.h index 2252d27a..3b732f6e 100644 --- a/libvips/include/vips/operation.h +++ b/libvips/include/vips/operation.h @@ -112,6 +112,8 @@ void vips_call_options( GOptionGroup *group, VipsOperation *operation ); int vips_call_argv( VipsOperation *operation, int argc, char **argv ); void vips_cache_drop_all( void ); +VipsOperation *vips_cache_operation_lookup( VipsOperation *operation ); +void vips_cache_operation_add( VipsOperation *operation ); int vips_cache_operation_buildp( VipsOperation **operation ); VipsOperation *vips_cache_operation_build( VipsOperation *operation ); void vips_cache_print( void ); diff --git a/libvips/iofuncs/cache.c b/libvips/iofuncs/cache.c index f275d82e..50fad7f7 100644 --- a/libvips/iofuncs/cache.c +++ b/libvips/iofuncs/cache.c @@ -728,6 +728,84 @@ vips_cache_trim( void ) g_mutex_unlock( vips_cache_lock ); } +/** + * vips_cache_operation_lookup: + * @operation: pointer to operation to lookup + * + * Look up an unbuilt @operation in the cache. If we get a hit, ref and + * return the old operation. If there's no hit, return NULL. + * + * Returns: (transfer full): the cache hit, if any. + */ +VipsOperation * +vips_cache_operation_lookup( VipsOperation *operation ) +{ + VipsOperationCacheEntry *hit; + VipsOperation *result; + + g_assert( VIPS_IS_OPERATION( operation ) ); + +#ifdef VIPS_DEBUG + printf( "vips_cache_operation_lookup: " ); + vips_object_print_dump( VIPS_OBJECT( operation ) ); +#endif /*VIPS_DEBUG*/ + + g_mutex_lock( vips_cache_lock ); + + result = NULL; + + if( (hit = g_hash_table_lookup( vips_cache_table, operation )) ) { + if( vips__cache_trace ) { + printf( "vips cache-: " ); + vips_object_print_summary( VIPS_OBJECT( operation ) ); + } + + result = hit->operation; + vips_cache_ref( result ); + } + + g_mutex_unlock( vips_cache_lock ); + + return( result ); +} + +/** + * vips_cache_operation_add: + * @operation: pointer to operation to lookup + * + * Add a built operation to the cache. + */ +void +vips_cache_operation_add( VipsOperation *operation ) +{ + g_mutex_lock( vips_cache_lock ); + + /* If two threads call the same operation at the same time, + * we can get multiple adds. Let the first one win. See + * https://github.com/jcupitt/libvips/pull/181 + */ + if( !g_hash_table_lookup( vips_cache_table, operation ) ) { + /* Has to be after _build() so we can see output args. + */ + if( vips__cache_trace ) { + if( vips_operation_get_flags( operation ) & + VIPS_OPERATION_NOCACHE ) + printf( "vips cache : " ); + else + printf( "vips cache+: " ); + vips_object_print_summary( VIPS_OBJECT( operation ) ); + } + + if( !(vips_operation_get_flags( operation ) & + VIPS_OPERATION_NOCACHE) ) + vips_cache_insert( operation ); + } + + g_mutex_unlock( vips_cache_lock ); + + vips_cache_trim(); +} + /** * vips_cache_operation_buildp: (skip) * @operation: pointer to operation to lookup @@ -742,68 +820,26 @@ vips_cache_trim( void ) int vips_cache_operation_buildp( VipsOperation **operation ) { - VipsOperationCacheEntry *hit; + VipsOperation *hit; g_assert( VIPS_IS_OPERATION( *operation ) ); #ifdef VIPS_DEBUG - printf( "vips_cache_operation_build: " ); + printf( "vips_cache_operation_buildp: " ); vips_object_print_dump( VIPS_OBJECT( *operation ) ); #endif /*VIPS_DEBUG*/ - g_mutex_lock( vips_cache_lock ); - - if( (hit = g_hash_table_lookup( vips_cache_table, *operation )) ) { - if( vips__cache_trace ) { - printf( "vips cache-: " ); - vips_object_print_summary( VIPS_OBJECT( *operation ) ); - } - - /* Ref before unref in case *operation == hit. - */ - vips_cache_ref( hit->operation ); + if( (hit = vips_cache_operation_lookup( *operation )) ) { g_object_unref( *operation ); - - *operation = hit->operation; + *operation = hit; } - - /* We have to unlock between search and add so that more than one - * _build() can run at once. - */ - g_mutex_unlock( vips_cache_lock ); - - if( !hit ) { + else { if( vips_object_build( VIPS_OBJECT( *operation ) ) ) return( -1 ); - g_mutex_lock( vips_cache_lock ); - - /* If two threads call the same operation at the same time, - * we can get multiple adds. Let the first one win. See - * https://github.com/jcupitt/libvips/pull/181 - */ - if( !g_hash_table_lookup( vips_cache_table, *operation ) ) { - /* Has to be after _build() so we can see output args. - */ - if( vips__cache_trace ) { - if( vips_operation_get_flags( *operation ) & - VIPS_OPERATION_NOCACHE ) - printf( "vips cache : " ); - else - printf( "vips cache+: " ); - vips_object_print_summary( - VIPS_OBJECT( *operation ) ); - } - - if( !(vips_operation_get_flags( *operation ) & - VIPS_OPERATION_NOCACHE) ) - vips_cache_insert( *operation ); - } - - g_mutex_unlock( vips_cache_lock ); + vips_cache_operation_add( *operation ); } - vips_cache_trim(); return( 0 ); }