cache in and working, at a basic level
reverted the switch thing as well, annoying
This commit is contained in:
parent
d9883cbd8e
commit
e7cd1147ce
6
TODO
6
TODO
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 ),
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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 ),
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user