added postclose callbacks

This commit is contained in:
John Cupitt 2010-01-10 21:28:38 +00:00
parent 88779a7e3b
commit 157e01bb4c
16 changed files with 91 additions and 55 deletions

View File

@ -12,6 +12,7 @@
- im_flood() and friends rewritten, typically 4x faster
- removed --with-cimg option, added --disable-cxx
- added im_system_image() (thanks Roland)
- added postclose callbacks
26/11/09 started 7.20.3
- updated en_GB.po translation

View File

@ -27,7 +27,7 @@ echo " by" `header -f Ysize temp.v` "pixels"
echo "starting benchmark ..."
echo "chain=$chain"
for cpus in 1 2 ; do
for cpus in 1 2 3 4 5 6 ; do
export IM_CONCURRENCY=$cpus
echo IM_CONCURRENCY=$IM_CONCURRENCY

View File

@ -92,26 +92,30 @@ static int
system_image_vec( im_object *argv )
{
IMAGE *in = argv[0];
char *in_format = argv[1];
char *out_format = argv[2];
char *cmd = argv[3];
char **log = (char **) &argv[4];
char **out_file = (char **) &argv[5];
IMAGE *out = argv[1];
char *in_format = argv[2];
char *out_format = argv[3];
char *cmd = argv[4];
char **log = (char **) &argv[5];
*out_file = im_system_image( in, in_format, out_format, cmd, log );
if( !*out_file )
*out_file = im_strdup( NULL, "" );
IMAGE *out_image;
if( (out_image = im_system_image( in,
in_format, out_format, cmd, log )) )
im_copy_file( out_image, out );
/* We always succeed, but out may be invalid.
*/
return( 0 );
}
static im_arg_desc system_image_args[] = {
IM_INPUT_IMAGE( "im" ),
IM_INPUT_IMAGE( "in" ),
IM_OUTPUT_IMAGE( "out" ),
IM_INPUT_STRING( "in_format" ),
IM_INPUT_STRING( "out_format" ),
IM_INPUT_STRING( "command" ),
IM_OUTPUT_STRING( "log" ),
IM_OUTPUT_STRING( "out_file" )
IM_OUTPUT_STRING( "log" )
};
static im_function system_image_desc = {

View File

@ -60,7 +60,7 @@ im_copy_file( IMAGE *in, IMAGE *out )
if( !im_isfile( in ) ) {
IMAGE *disc;
if( !(disc = im__open_temp()) )
if( !(disc = im__open_temp( "%s.v" )) )
return( -1 );
if( im_add_close_callback( out,
(im_callback_fn) im_close, disc, NULL ) ) {

View File

@ -79,7 +79,7 @@ im_system( IMAGE *im, const char *cmd, char **out )
if( !im_isfile( im ) ) {
IMAGE *disc;
if( !(disc = im__open_temp()) )
if( !(disc = im__open_temp( "%s.v" )) )
return( -1 );
if( im_copy( im, disc ) ||
im_system( disc, cmd, out ) ) {

View File

@ -60,31 +60,20 @@
static int
system_image( IMAGE *im,
const char *in_name, const char *out_name, const char *cmd_format,
IMAGE *in_image, IMAGE *out_image, const char *cmd_format,
char **log )
{
IMAGE *disc;
const char *in_name = in_image->filename;
const char *out_name = out_image->filename;
FILE *fp;
char line[IM_MAX_STRSIZE];
char txt[IM_MAX_STRSIZE];
VipsBuf buf = VIPS_BUF_STATIC( txt );
int result;
if( !(disc = im_open( in_name, "w" )) )
if( im_copy( im, in_image ) ||
!(fp = im_popenf( cmd_format, "r", in_name, out_name )) )
return( -1 );
if( im_copy( im, disc ) ) {
im_close( im );
g_unlink( in_name );
return( -1 );
}
im_close( im );
if( !(fp = im_popenf( cmd_format, "r", in_name, out_name )) ) {
g_unlink( in_name );
return( -1 );
}
while( fgets( line, IM_MAX_STRSIZE, fp ) )
if( !vips_buf_appends( &buf, line ) )
@ -92,15 +81,14 @@ system_image( IMAGE *im,
result = pclose( fp );
g_unlink( in_name );
if( log )
*log = im_strdup( NULL, vips_buf_all( &buf ) );
return( result );
}
/*
/**
* im_system_image:
Run a command on an image, returning a new image.
@ -127,29 +115,29 @@ system_image( IMAGE *im,
*/
char *
IMAGE *
im_system_image( IMAGE *im,
const char *in_format, const char *out_format, const char *cmd_format,
char **log )
{
char *in_name;
char *out_name;
IMAGE *in_image;
IMAGE *out_image;
if( log )
*log = NULL;
in_name = im__temp_name( in_format );
out_name = im__temp_name( in_format );
in_image = im__open_temp( in_format );
out_image = im__open_temp( out_format );
if( !in_name ||
!out_name ||
system_image( im, in_name, out_name, cmd_format, log ) ) {
g_free( in_name );
g_free( out_name );
if( !in_image ||
!out_image ||
system_image( im, in_image, out_image, cmd_format, log ) ) {
im_close( in_image );
im_close( out_image );
return( NULL );
}
g_free( in_name );
im_close( in_image );
return( out_name );
return( out_image );
}

View File

@ -40,6 +40,7 @@ typedef int (*im_callback_fn)( void *a, void *b );
int im_add_close_callback( IMAGE *im, im_callback_fn fn, void *a, void *b );
int im_add_preclose_callback( IMAGE *im, im_callback_fn fn, void *a, void *b );
int im_add_postclose_callback( IMAGE *im, im_callback_fn fn, void *a, void *b );
int im_add_evalstart_callback( IMAGE *im, im_callback_fn fn, void *a, void *b );
int im_add_eval_callback( IMAGE *im, im_callback_fn fn, void *a, void *b );

View File

@ -111,7 +111,7 @@ int im_subsample( IMAGE *in, IMAGE *out, int x, int y );
int im_zoom( IMAGE *in, IMAGE *out, int x, int y );
int im_system( IMAGE *im, const char *cmd, char **out );
char *im_system_image( IMAGE *im,
IMAGE *im_system_image( IMAGE *im,
const char *in_format, const char *out_format, const char *cmd_format,
char **log );

View File

@ -240,6 +240,11 @@ typedef struct _VipsImage {
* relationships, so it's a mandatory thing.
*/
gboolean hint_set;
/* Post-close callbacks happen on finalize. Eg. deleting the file
* associated with this temp image.
*/
GSList *postclosefns;
} VipsImage;
extern const size_t im__sizeof_bandfmt[];

View File

@ -255,7 +255,7 @@ int im_isvips( const char *filename );
int im_amiMSBfirst( void );
char *im__temp_name( const char *format );
IMAGE *im__open_temp( void );
IMAGE *im__open_temp( const char *format );
int im_bits_of_fmt( VipsBandFmt fmt );

View File

@ -108,11 +108,11 @@ add_callback( IMAGE *im, GSList **cblist, im_callback_fn fn, void *a, void *b )
*
* Attaches a close callback @fn to @im.
*
* Close callbacks are triggered exactly once when the image has been closed
* Close callbacks are triggered exactly once, when the image has been closed
* and most resources freed, but just before the memory for @im is released.
*
* Close callbacks are a good place to free memory that was need to generate
* @im, delete temporary files and so on. You can close other images and there
* @im. You can close other images and there
* may even be circularity in your close lists.
*
* See also: im_malloc() (implemented with im_add_close_callback()),
@ -127,6 +127,29 @@ im_add_close_callback( IMAGE *im, im_callback_fn fn, void *a, void *b )
return( add_callback( im, &im->closefns, fn, a, b ) );
}
/**
* im_add_postclose_callback:
* @im: image to attach callback to
* @fn: callback function
* @a: user data 1
* @b: user data 2
*
* Attaches a close callback @fn to @im.
*
* Post-close callbacks are triggered exactly once, just before the memory
* associated with @im is released.
*
* Close callbacks are a good place to delete temporary files. You can close
* other images and there may even be circularity in your close lists.
*
* Returns: 0 on success, or -1 on error.
*/
int
im_add_postclose_callback( IMAGE *im, im_callback_fn fn, void *a, void *b )
{
return( add_callback( im, &im->postclosefns, fn, a, b ) );
}
/**
* im_add_preclose_callback:
* @im: image to attach callback to

View File

@ -393,16 +393,18 @@ im_printdesc( IMAGE *image )
*/
if( image->generate )
printf( "generate function attached\n" );
if( image->preclosefns )
printf( "preclose callbacks attached\n" );
if( image->closefns )
printf( "close callbacks attached\n" );
if( image->postclosefns )
printf( "postclose callbacks attached\n" );
if( image->evalfns )
printf( "eval callbacks attached\n" );
if( image->evalendfns )
printf( "evalend callbacks attached\n" );
if( image->evalstartfns )
printf( "evalstart callbacks attached\n" );
if( image->preclosefns )
printf( "preclose callbacks attached\n" );
if( image->invalidatefns )
printf( "invalidate callbacks attached\n" );
if( image->regions ) {

View File

@ -50,6 +50,8 @@
* released
* 6/10/09
* - gtkdoc comment
* 10/1/09
* - added postclose
*/
/*
@ -294,6 +296,8 @@ im_close( IMAGE *im )
/* Final cleanup.
*/
result |= im__trigger_callbacks( im->postclosefns );
IM_FREEF( im_slist_free_all, im->postclosefns );
IM_FREEF( g_mutex_free, im->sslock );
IM_FREE( im->filename );
IM_FREE( im->Hist );

View File

@ -32,6 +32,8 @@
* - add file_length
* 8/10/09
* - add set_hint
* 10/1/09
* - added postclose
*/
/*
@ -173,6 +175,8 @@ im_init( const char *filename )
im->hint_set = FALSE;
im->postclosefns = NULL;
if( !(im->filename = im_strdup( NULL, filename )) ) {
im_close( im );
return( NULL );

View File

@ -1546,14 +1546,15 @@ im__temp_name( const char *format )
}
/* Make a disc IMAGE which will be automatically unlinked on im_close().
* Format is something like "%s.v" for a vips file.
*/
IMAGE *
im__open_temp( void )
im__open_temp( const char *format )
{
char *name;
IMAGE *disc;
if( !(name = im__temp_name( "%s.v" )) )
if( !(name = im__temp_name( format )) )
return( NULL );
if( !(disc = im_open( name, "w" )) ) {
@ -1562,7 +1563,10 @@ im__open_temp( void )
}
g_free( name );
if( im_add_close_callback( disc,
/* Needs to be postclose so we can rewindd disc after write without
* deleting the file.
*/
if( im_add_postclose_callback( disc,
(im_callback_fn) unlink, disc->filename, NULL ) ) {
im_close( disc );
g_unlink( name );

View File

@ -184,7 +184,7 @@ im_create_imask( const char *filename, int xs, int ys )
INTMASK *
im_create_imaskv( const char *filename, int xs, int ys, ... )
{
{
va_list ap;
INTMASK *m;