add op invalidate stuff

still need to test and link to cache
This commit is contained in:
John Cupitt 2014-06-12 09:22:28 +01:00
parent 30eff079f1
commit a8d04a7dd1
6 changed files with 86 additions and 16 deletions

View File

@ -37,6 +37,7 @@
im_*mosaic1(), im_*merge1() redone as classes
- better filename tracking for globalbalance
- revised vips8 image load/save API, now simpler and more logical
- operations emit "invalidate" if any of their input images invalidate
6/3/14 started 7.38.6
- grey ramp minimum was wrong

8
TODO
View File

@ -1,3 +1,11 @@
- test operation invalidate
enable cache in nip2, find max using vips_call, try painting on the input
- cache needs to listen for invalidate
- can we use postbuild elsewhere? look at use of "preclose" / "written", etc.

View File

@ -283,6 +283,11 @@ typedef struct _VipsArgumentInstance {
* here.
*/
gulong close_id;
/* We need to listen for "invalidate" on input images and send our own
* "invalidate" out. If we go, we need to disconnect.
*/
gulong invalidate_id;
} VipsArgumentInstance;
/* Need to look up our VipsArgument structs from a pspec. Just hash the

View File

@ -92,12 +92,18 @@ typedef struct _VipsOperationClass {
*/
VipsOperationFlags (*get_flags)( VipsOperation * );
VipsOperationFlags flags;
/* One of our input images has signalled "invalidate". The cache uses
* VipsOperation::invalidate to drop dirty ops.
*/
void (*invalidate)( VipsOperation * );
} VipsOperationClass;
GType vips_operation_get_type( void );
VipsOperationFlags vips_operation_get_flags( VipsOperation *operation );
void vips_operation_class_print_usage( VipsOperationClass *operation_class );
void vips_operation_invalidate( VipsOperation *operation );
int vips_operation_call_valist( VipsOperation *operation, va_list ap );
VipsOperation *vips_operation_new( const char *name );

View File

@ -392,16 +392,34 @@ vips_object_rewind( VipsObject *object )
/* Extra stuff we track for properties to do our argument handling.
*/
static void
vips_argument_instance_detach( VipsArgumentInstance *argument_instance )
{
VipsObject *object = argument_instance->object;
if( argument_instance->close_id ) {
if( g_signal_handler_is_connected( object,
argument_instance->close_id ) )
g_signal_handler_disconnect( object,
argument_instance->close_id );
argument_instance->close_id = 0;
}
if( argument_instance->invalidate_id ) {
if( g_signal_handler_is_connected( object,
argument_instance->invalidate_id ) )
g_signal_handler_disconnect( object,
argument_instance->invalidate_id );
argument_instance->invalidate_id = 0;
}
}
/* Free a VipsArgumentInstance ... VipsArgumentClass can just be g_free()d.
*/
static void
vips_argument_instance_free( VipsArgumentInstance *argument_instance )
{
if( argument_instance->close_id ) {
g_signal_handler_disconnect( argument_instance->object,
argument_instance->close_id );
argument_instance->close_id = 0;
}
vips_argument_instance_detach( argument_instance );
g_free( argument_instance );
}
@ -580,6 +598,7 @@ vips_argument_init( VipsObject *object )
argument_class->flags &
VIPS_ARGUMENT_SET_ALWAYS;
argument_instance->close_id = 0;
argument_instance->invalidate_id = 0;
vips_argument_table_replace( object->argument_table,
(VipsArgument *) argument_instance );
@ -729,6 +748,8 @@ vips_object_clear_member( VipsObject *object, GParamSpec *pspec,
VipsArgumentInstance *argument_instance =
vips__argument_get_instance( argument_class, object );
vips_argument_instance_detach( argument_instance );
if( *member ) {
if( argument_class->flags & VIPS_ARGUMENT_INPUT ) {
#ifdef DEBUG_REF
@ -754,17 +775,6 @@ vips_object_clear_member( VipsObject *object, GParamSpec *pspec,
G_OBJECT( object )->ref_count - 1 );
#endif /*DEBUG_REF*/
/* The object reffed us. Stop listening link to the
* object's "close" signal. We can come here from
* object being closed, in which case the handler
* will already have been disconnected for us.
*/
if( g_signal_handler_is_connected( object,
argument_instance->close_id ) )
g_signal_handler_disconnect( object,
argument_instance->close_id );
argument_instance->close_id = 0;
g_object_unref( object );
}
@ -919,6 +929,13 @@ vips_object_finalize( GObject *gobject )
G_OBJECT_CLASS( vips_object_parent_class )->finalize( gobject );
}
static void
vips_object_arg_invalidate( GObject *argument,
VipsArgumentInstance *argument_instance )
{
vips_operation_invalidate( VIPS_OPERATION( argument ) );
}
static void
vips_object_arg_close( GObject *argument,
VipsArgumentInstance *argument_instance )
@ -968,6 +985,13 @@ vips__object_set_member( VipsObject *object, GParamSpec *pspec,
/* Ref the argument.
*/
g_object_ref( *member );
g_assert( !argument_instance->invalidate_id );
argument_instance->invalidate_id =
g_signal_connect( *member, "invalidate",
G_CALLBACK(
vips_object_arg_invalidate ),
argument_instance );
}
else if( argument_class->flags & VIPS_ARGUMENT_OUTPUT ) {
#ifdef DEBUG_REF

View File

@ -92,6 +92,15 @@
/* Abstract base class for operations.
*/
/* Our signals.
*/
enum {
SIG_INVALIDATE,
SIG_LAST
};
static guint vips_operation_signals[SIG_LAST] = { 0 };
G_DEFINE_ABSTRACT_TYPE( VipsOperation, vips_operation, VIPS_TYPE_OBJECT );
static void
@ -380,6 +389,14 @@ vips_operation_class_init( VipsOperationClass *class )
class->usage = vips_operation_usage;
class->get_flags = vips_operation_real_get_flags;
vips_operation_signals[SIG_INVALIDATE] = g_signal_new( "invalidate",
G_TYPE_FROM_CLASS( class ),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET( VipsOperationClass, invalidate ),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0 );
}
static void
@ -419,6 +436,15 @@ vips_operation_class_print_usage( VipsOperationClass *operation_class )
printf( "%s", vips_buf_all( &buf ) );
}
void
vips_operation_invalidate( VipsOperation *operation )
{
printf( "vips_operation_invalidate: %p\n", operation );
vips_object_print_summary( VIPS_OBJECT( operation ) );
g_signal_emit( operation, vips_operation_signals[SIG_INVALIDATE], 0 );
}
VipsOperation *
vips_operation_new( const char *name )
{