cache in and working, at a basic level

reverted the switch thing as well, annoying
This commit is contained in:
John Cupitt 2011-09-09 17:01:29 +01:00
parent d9883cbd8e
commit e7cd1147ce
7 changed files with 95 additions and 111 deletions

6
TODO
View File

@ -1,11 +1,9 @@
- cache
vips_object_build() needs a new type ... should return the
VipsObject it makes
should the cache be thread-private?
- im_init_world() fallback is not working
only cache operation_new()?
need to go back to multiple ifs in object.c

View File

@ -57,6 +57,13 @@ im_open( const char *filename, const char *mode )
{
VipsImage *image;
/* Pass in a nonsense name for argv0 ... this init path is only here
* for old programs which are missing an vips_init() call. We need
* i18n set up before we can translate.
*/
if( vips_init( "giant_banana" ) )
vips_error_clear();
if( !(image = vips_image_new_mode( filename, mode )) )
return( NULL );

View File

@ -355,7 +355,7 @@ vips_wrap7_object_set_property( GObject *gobject,
*/
if( argument_class->flags & VIPS_ARGUMENT_CONSTRUCT &&
object->constructed &&
!vips_value_is_null( value ) ) {
!vips_value_is_null( pspec, value ) ) {
g_warning( "%s: %s can't assign '%s' after construct",
G_STRLOC,
G_OBJECT_TYPE_NAME( gobject ),
@ -367,7 +367,7 @@ vips_wrap7_object_set_property( GObject *gobject,
*/
if( argument_class->flags & VIPS_ARGUMENT_SET_ONCE &&
argument_instance->assigned &&
!vips_value_is_null( value ) ) {
!vips_value_is_null( pspec, value ) ) {
g_warning( "%s: %s can only assign '%s' once",
G_STRLOC,
G_OBJECT_TYPE_NAME( gobject ),

View File

@ -313,7 +313,7 @@ struct _VipsObjectClass {
GSList *argument_table_traverse;
};
gboolean vips_value_is_null( const GValue *value );
gboolean vips_value_is_null( GParamSpec *psoec, const GValue *value );
void vips_object_set_property( GObject *gobject,
guint property_id, const GValue *value, GParamSpec *pspec );
void vips_object_get_property( GObject *gobject,
@ -368,7 +368,7 @@ void vips_object_sanity_all( void );
void vips_object_rewind( VipsObject *object );
VipsObject *vips_cache_lookup( VipsObject *object );
int vips_object_build_cache( VipsObject **object );
#ifdef __cplusplus
}

View File

@ -28,9 +28,25 @@
*/
/*
#define VIPS_DEBUG
TODO
vips_object_build() needs a new type ... should return the
VipsObject it makes
should the cache be thread-private? or lock? or say operations can
only be made from the main thread?
only cache operation_new()? (this is what we do now)
listen for invalidate
*/
/*
*/
#define VIPS_DEBUG
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
@ -343,7 +359,7 @@ vips_object_validate_arg( VipsObject *object,
g_value_init( &value, type );
g_object_get_property( G_OBJECT( object ), name, &value );
null = vips_value_is_null( &value );
null = vips_value_is_null( pspec, &value );
g_value_unset( &value );
if( null )
@ -407,38 +423,47 @@ vips_cache_remove( void *data, GObject *object )
}
/* Look up an object in the cache. If we get a hit, unref the new one, ref the
* old one and return that. If we miss, add this object and a weakref so we
* old one and return that.
*
* If we miss, build, add this object and weakref so we
* will drop it when it's unreffed.
*/
VipsObject *
vips_cache_lookup( VipsObject *object )
int
vips_object_build_cache( VipsObject **object )
{
VipsObject *hit;
VIPS_DEBUG_MSG( "vips_object_build_cache: %p\n", *object );
if( !vips_object_cache )
vips_object_cache = g_hash_table_new(
(GHashFunc) vips_object_hash,
(GEqualFunc) vips_object_equal );
if( (hit = g_hash_table_lookup( vips_object_cache, object )) ) {
VIPS_DEBUG_MSG( "vips_cache_lookup: hit for %p\n", hit );
if( (hit = g_hash_table_lookup( vips_object_cache, *object )) ) {
VIPS_DEBUG_MSG( "\thit %p\n", hit );
if( vips_object_validate( hit ) ) {
g_object_unref( object );
g_object_unref( *object );
g_object_ref( hit );
vips_object_ref_outputs( hit );
*object = hit;
return( hit );
return( 0 );
}
VIPS_DEBUG_MSG( "\tvalidation failed, dropping\n" );
g_hash_table_remove( vips_object_cache, hit );
}
VIPS_DEBUG_MSG( "vips_cache_lookup: adding %p\n", object );
VIPS_DEBUG_MSG( "\tmiss, building\n" );
g_hash_table_insert( vips_object_cache, object, object );
g_object_weak_ref( G_OBJECT( object ), vips_cache_remove, NULL );
if( vips_object_build( *object ) )
return( -1 );
return( object );
VIPS_DEBUG_MSG( "\tadding\n" );
g_hash_table_insert( vips_object_cache, *object, *object );
g_object_weak_ref( G_OBJECT( *object ), vips_cache_remove, NULL );
return( 0 );
}

View File

@ -664,26 +664,26 @@ vips__object_set_member( VipsObject *object, GParamSpec *pspec,
}
/* Is a value NULL? We allow multiple sets of NULL so props can be cleared.
* The pspec gives the value type, for consistency with the way value types
* are detected in set and get.
*/
gboolean
vips_value_is_null( const GValue *value )
vips_value_is_null( GParamSpec *pspec, const GValue *value )
{
switch( G_VALUE_TYPE( value ) ) {
case G_TYPE_STRING:
return( !g_value_get_string( value ) );
if( G_IS_PARAM_SPEC_STRING( pspec ) &&
!g_value_get_string( value ) )
return( TRUE );
if( G_IS_PARAM_SPEC_OBJECT( pspec ) &&
!g_value_get_object( value ) )
return( TRUE );
if( G_IS_PARAM_SPEC_POINTER( pspec ) &&
!g_value_get_pointer( value ) )
return( TRUE );
if( G_IS_PARAM_SPEC_BOXED( pspec ) &&
!g_value_get_boxed( value ) )
return( TRUE );
case G_TYPE_OBJECT:
return( !g_value_get_object( value ) );
case G_TYPE_POINTER:
return( !g_value_get_pointer( value ) );
case G_TYPE_BOXED:
return( !g_value_get_boxed( value ) );
default:
return( FALSE );
}
return( FALSE );
}
/* Also used by subclasses, so not static.
@ -727,7 +727,7 @@ vips_object_set_property( GObject *gobject,
*/
if( argument_class->flags & VIPS_ARGUMENT_CONSTRUCT &&
object->constructed &&
!vips_value_is_null( value ) ) {
!vips_value_is_null( pspec, value ) ) {
g_warning( "%s: %s can't assign '%s' after construct",
G_STRLOC,
G_OBJECT_TYPE_NAME( gobject ),
@ -739,7 +739,7 @@ vips_object_set_property( GObject *gobject,
*/
if( argument_class->flags & VIPS_ARGUMENT_SET_ONCE &&
argument_instance->assigned &&
!vips_value_is_null( value ) ) {
!vips_value_is_null( pspec, value ) ) {
g_warning( "%s: %s can only assign '%s' once",
G_STRLOC,
G_OBJECT_TYPE_NAME( gobject ),
@ -747,73 +747,53 @@ vips_object_set_property( GObject *gobject,
return;
}
switch( G_PARAM_SPEC_TYPE( pspec ) ) {
case G_TYPE_STRING:
{
/* We can't use a switch since some param specs don't have fundamental
* types and are hence not compile-time constants, argh.
*/
if( G_IS_PARAM_SPEC_STRING( pspec ) ) {
char **member = &G_STRUCT_MEMBER( char *, object,
argument_class->offset );
VIPS_SETSTR( *member, g_value_get_string( value ) );
}
break;
case G_TYPE_OBJECT:
{
else if( G_IS_PARAM_SPEC_OBJECT( pspec ) ) {
GObject **member = &G_STRUCT_MEMBER( GObject *, object,
argument_class->offset );
vips__object_set_member( object, pspec, member,
g_value_get_object( value ) );
}
break;
case G_TYPE_INT:
{
else if( G_IS_PARAM_SPEC_INT( pspec ) ) {
int *member = &G_STRUCT_MEMBER( int, object,
argument_class->offset );
*member = g_value_get_int( value );
}
break;
case G_TYPE_BOOLEAN:
{
else if( G_IS_PARAM_SPEC_BOOLEAN( pspec ) ) {
gboolean *member = &G_STRUCT_MEMBER( gboolean, object,
argument_class->offset );
*member = g_value_get_boolean( value );
}
break;
case G_TYPE_ENUM:
{
else if( G_IS_PARAM_SPEC_ENUM( pspec ) ) {
int *member = &G_STRUCT_MEMBER( int, object,
argument_class->offset );
*member = g_value_get_enum( value );
}
break;
case G_TYPE_POINTER:
{
else if( G_IS_PARAM_SPEC_POINTER( pspec ) ) {
gpointer *member = &G_STRUCT_MEMBER( gpointer, object,
argument_class->offset );
*member = g_value_get_pointer( value );
}
break;
case G_TYPE_DOUBLE:
{
else if( G_IS_PARAM_SPEC_DOUBLE( pspec ) ) {
double *member = &G_STRUCT_MEMBER( double, object,
argument_class->offset );
*member = g_value_get_double( value );
}
break;
case G_TYPE_BOXED:
{
else if( G_IS_PARAM_SPEC_BOXED( pspec ) ) {
gpointer *member = &G_STRUCT_MEMBER( gpointer, object,
argument_class->offset );
@ -828,9 +808,7 @@ vips_object_set_property( GObject *gobject,
*/
*member = g_value_dup_boxed( value );
}
break;
default:
else {
g_warning( "%s: %s unimplemented property type %s",
G_STRLOC,
G_OBJECT_TYPE_NAME( gobject ),
@ -871,72 +849,49 @@ vips_object_get_property( GObject *gobject,
return;
}
switch( G_PARAM_SPEC_TYPE( pspec ) ) {
case G_TYPE_STRING:
{
if( G_IS_PARAM_SPEC_STRING( pspec ) ) {
char *member = G_STRUCT_MEMBER( char *, object,
argument_class->offset );
g_value_set_string( value, member );
}
break;
case G_TYPE_OBJECT:
{
else if( G_IS_PARAM_SPEC_OBJECT( pspec ) ) {
GObject **member = &G_STRUCT_MEMBER( GObject *, object,
argument_class->offset );
g_value_set_object( value, *member );
}
break;
case G_TYPE_INT:
{
else if( G_IS_PARAM_SPEC_INT( pspec ) ) {
int *member = &G_STRUCT_MEMBER( int, object,
argument_class->offset );
g_value_set_int( value, *member );
}
break;
case G_TYPE_BOOLEAN:
{
else if( G_IS_PARAM_SPEC_BOOLEAN( pspec ) ) {
gboolean *member = &G_STRUCT_MEMBER( gboolean, object,
argument_class->offset );
g_value_set_boolean( value, *member );
}
break;
case G_TYPE_ENUM:
{
else if( G_IS_PARAM_SPEC_ENUM( pspec ) ) {
int *member = &G_STRUCT_MEMBER( int, object,
argument_class->offset );
g_value_set_enum( value, *member );
}
break;
case G_TYPE_POINTER:
{
else if( G_IS_PARAM_SPEC_POINTER( pspec ) ) {
gpointer *member = &G_STRUCT_MEMBER( gpointer, object,
argument_class->offset );
g_value_set_pointer( value, *member );
}
break;
case G_TYPE_DOUBLE:
{
else if( G_IS_PARAM_SPEC_DOUBLE( pspec ) ) {
double *member = &G_STRUCT_MEMBER( double, object,
argument_class->offset );
g_value_set_double( value, *member );
}
break;
case G_TYPE_BOXED:
{
else if( G_IS_PARAM_SPEC_BOXED( pspec ) ) {
gpointer *member = &G_STRUCT_MEMBER( gpointer, object,
argument_class->offset );
@ -945,9 +900,7 @@ vips_object_get_property( GObject *gobject,
*/
g_value_set_boxed( value, *member );
}
break;
default:
else {
g_warning( "%s: %s unimplemented property type %s",
G_STRLOC,
G_OBJECT_TYPE_NAME( gobject ),

View File

@ -484,12 +484,13 @@ vips_call_required_optional( VipsOperation *operation,
va_copy( a, required );
va_copy( b, optional );
result = vips_operation_set_valist_required( operation, a ) ||
vips_operation_set_valist_optional( operation, b ) ||
vips_object_build( VIPS_OBJECT( operation ) );
vips_operation_set_valist_optional( operation, b );
va_end( a );
va_end( b );
if( result )
/* Build from cache.
*/
if( vips_object_build_cache( (VipsObject **) &operation ) )
return( -1 );
/* Walk args again, writing output.