/** * vips_cache_operation_lookup: * @operation: (transfer none): 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 ) ); g_assert( !VIPS_OBJECT( operation )->constructed ); #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: (transfer none): pointer to operation to add * * Add a built operation to the cache. The cache will ref the operation. */ void vips_cache_operation_add( VipsOperation *operation ) { g_assert( VIPS_OBJECT( operation )->constructed ); 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 ) ) { VipsOperationFlags flags = vips_operation_get_flags( operation ); gboolean nocache = flags & VIPS_OPERATION_NOCACHE; /* Has to be after _build() so we can see output args. */ if( vips__cache_trace ) { if( nocache ) printf( "vips cache : " ); else printf( "vips cache+: " ); vips_object_print_summary( VIPS_OBJECT( operation ) ); } if( !nocache ) vips_cache_insert( operation ); } g_mutex_unlock( vips_cache_lock ); vips_cache_trim(); }
/* Print header, or parts of header. */ static int print_header( IMAGE *im, gboolean many ) { if( !main_option_field ) { printf( "%s: ", im->filename ); vips_object_print_summary( VIPS_OBJECT( im ) ); if( main_option_all ) (void) vips_image_map( im, print_field_fn, &many ); } else if( strcmp( main_option_field, "getext" ) == 0 ) { if( im__has_extension_block( im ) ) { void *buf; int size; if( !(buf = im__read_extension_block( im, &size )) ) return( -1 ); printf( "%s", (char *) buf ); im_free( buf ); } } else if( strcmp( main_option_field, "Hist" ) == 0 ) printf( "%s", im_history_get( im ) ); else { GValue value = { 0 }; GType type; if( im_header_get( im, main_option_field, &value ) ) return( -1 ); /* Display the save form, if there is one. This way we display * something useful for ICC profiles, xml fields, etc. */ type = G_VALUE_TYPE( &value ); if( g_value_type_transformable( type, IM_TYPE_SAVE_STRING ) ) { GValue save_value = { 0 }; g_value_init( &save_value, IM_TYPE_SAVE_STRING ); if( !g_value_transform( &value, &save_value ) ) return( -1 ); printf( "%s\n", im_save_string_get( &save_value ) ); g_value_unset( &save_value ); } else { char *str_value; str_value = g_strdup_value_contents( &value ); printf( "%s\n", str_value ); g_free( str_value ); } g_value_unset( &value ); } return( 0 ); }
/** * vips_cache_operation_buildp: (skip) * @operation: pointer to operation to lookup * * Look up @operation in the cache. If we get a hit, unref @operation, ref the * old one and return that through the argument pointer. * * If we miss, build and add @operation. * * Returns: 0 on success, or -1 on error. */ int vips_cache_operation_buildp( VipsOperation **operation ) { VipsOperation *hit; g_assert( VIPS_IS_OPERATION( *operation ) ); #ifdef VIPS_DEBUG printf( "vips_cache_operation_build: " ); vips_object_print_dump( VIPS_OBJECT( *operation ) ); #endif /*VIPS_DEBUG*/ vips_cache_trim(); 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( hit ) ); } /* Ref before unref in case *operation == hit. */ vips_cache_ref( hit ); g_object_unref( *operation ); *operation = hit; } g_mutex_unlock( vips_cache_lock ); if( !hit ) { if( vips_object_build( VIPS_OBJECT( *operation ) ) ) return( -1 ); /* 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 ) ); } g_mutex_lock( vips_cache_lock ); if( !(vips_operation_get_flags( *operation ) & VIPS_OPERATION_NOCACHE) ) { vips_cache_ref( *operation ); g_hash_table_insert( vips_cache_table, *operation, *operation ); } g_mutex_unlock( vips_cache_lock ); } return( 0 ); }