improve thread-safety
the cache and link thing now lock, so you can create images and process them from several threads
This commit is contained in:
parent
57492bee16
commit
cff8f44373
@ -2,6 +2,8 @@
|
||||
*
|
||||
* 20/6/12
|
||||
* - try to make it compile on centos5
|
||||
* 7/7/12
|
||||
* - add a lock so we can run operations from many threads
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -103,6 +105,10 @@ static GHashTable *vips_cache_table = NULL;
|
||||
*/
|
||||
static int vips_cache_time = 0;
|
||||
|
||||
/* Protect cache access with this.
|
||||
*/
|
||||
static GMutex *vips_cache_lock = NULL;
|
||||
|
||||
/* Old versions of glib are missing these. When we abandon centos 5, switch to
|
||||
* g_int64_hash() and g_double_hash().
|
||||
*/
|
||||
@ -407,6 +413,8 @@ static void
|
||||
vips_cache_init( void )
|
||||
{
|
||||
if( !vips_cache_table ) {
|
||||
vips_cache_lock = g_mutex_new();
|
||||
|
||||
vips_cache_table = g_hash_table_new(
|
||||
(GHashFunc) vips_operation_hash,
|
||||
(GEqualFunc) vips_operation_equal );
|
||||
@ -438,7 +446,6 @@ vips_cache_print_fn( void *value, void *a, void *b )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vips_cache_print:
|
||||
*
|
||||
@ -447,11 +454,15 @@ vips_cache_print_fn( void *value, void *a, void *b )
|
||||
void
|
||||
vips_cache_print( void )
|
||||
{
|
||||
g_mutex_lock( vips_cache_lock );
|
||||
|
||||
if( vips_cache_table ) {
|
||||
printf( "Operation cache:\n" );
|
||||
vips_hash_table_map( vips_cache_table,
|
||||
vips_cache_print_fn, NULL, NULL );
|
||||
}
|
||||
|
||||
g_mutex_unlock( vips_cache_lock );
|
||||
}
|
||||
|
||||
static void *
|
||||
@ -578,6 +589,8 @@ vips_cache_trim( void )
|
||||
{
|
||||
VipsOperation *operation;
|
||||
|
||||
g_mutex_lock( vips_cache_lock );
|
||||
|
||||
while( vips_cache_table &&
|
||||
(g_hash_table_size( vips_cache_table ) > vips_cache_max ||
|
||||
vips_tracked_get_files() > vips_cache_max_files ||
|
||||
@ -589,6 +602,8 @@ vips_cache_trim( void )
|
||||
|
||||
vips_cache_drop( operation );
|
||||
}
|
||||
|
||||
g_mutex_unlock( vips_cache_lock );
|
||||
}
|
||||
|
||||
static void *
|
||||
@ -659,6 +674,8 @@ vips_cache_operation_buildp( VipsOperation **operation )
|
||||
|
||||
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: hit %p\n ", hit );
|
||||
@ -672,7 +689,10 @@ vips_cache_operation_buildp( VipsOperation **operation )
|
||||
|
||||
*operation = hit;
|
||||
}
|
||||
else {
|
||||
|
||||
g_mutex_unlock( vips_cache_lock );
|
||||
|
||||
if( !hit ) {
|
||||
if( vips__cache_trace ) {
|
||||
if( (*operation)->nocache )
|
||||
printf( "vips cache: uncacheable %p\n ",
|
||||
@ -685,13 +705,18 @@ vips_cache_operation_buildp( VipsOperation **operation )
|
||||
if( vips_object_build( VIPS_OBJECT( *operation ) ) )
|
||||
return( -1 );
|
||||
|
||||
g_mutex_lock( vips_cache_lock );
|
||||
|
||||
if( !(*operation)->nocache ) {
|
||||
vips_cache_ref( *operation );
|
||||
g_hash_table_insert( vips_cache_table,
|
||||
*operation, *operation );
|
||||
}
|
||||
|
||||
g_mutex_unlock( vips_cache_lock );
|
||||
}
|
||||
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,9 @@
|
||||
* 24/3/11
|
||||
* - move demand_hint stuff in here
|
||||
* - move to vips_ namespace
|
||||
* 7/7/12
|
||||
* - lock around link make/break so we can process an image from many
|
||||
* threads
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -172,10 +175,12 @@ vips__link_break_rev( VipsImage *image_down, VipsImage *image_up )
|
||||
void
|
||||
vips__link_break_all( VipsImage *image )
|
||||
{
|
||||
g_mutex_lock( vips__global_lock );
|
||||
vips_slist_map2( image->upstream,
|
||||
(VipsSListMap2Fn) vips__link_break, image, NULL );
|
||||
vips_slist_map2( image->downstream,
|
||||
(VipsSListMap2Fn) vips__link_break_rev, image, NULL );
|
||||
g_mutex_unlock( vips__global_lock );
|
||||
|
||||
g_assert( !image->upstream );
|
||||
g_assert( !image->downstream );
|
||||
@ -326,8 +331,10 @@ vips_demand_hint_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in )
|
||||
|
||||
/* im depends on all these ims.
|
||||
*/
|
||||
g_mutex_lock( vips__global_lock );
|
||||
for( i = 0; i < len; i++ )
|
||||
vips__link_make( in[i], image );
|
||||
g_mutex_unlock( vips__global_lock );
|
||||
|
||||
/* Set a flag on the image to say we remembered to call this thing.
|
||||
* vips_image_generate() and friends check this.
|
||||
|
@ -835,9 +835,8 @@ vips_threadpool_create_threads( VipsThreadpool *pool )
|
||||
* processed, @progress is called, so that the operation can give
|
||||
* progress feedback. @progress may be %NULL.
|
||||
*
|
||||
* Each thread has private state that the @allocate and @work functions can
|
||||
* use to communicate. This state is created by each worker as it starts using
|
||||
* @start. Use the state destructor to clean up.
|
||||
* The object returned by @start must be an instance of a subclass of
|
||||
* #VipsThreadState. Use this to communicate between @allocate and @work.
|
||||
*
|
||||
* @allocate and @start are always single-threaded (so they can write to the
|
||||
* per-pool state), whereas @work can be executed concurrently. @progress is
|
||||
|
Loading…
Reference in New Issue
Block a user