delay rather than stall ahead threads
avoid deadlocks by only slowing down threads which run ahead of the read point
This commit is contained in:
parent
0c87863222
commit
7a0441d455
@ -1,5 +1,6 @@
|
|||||||
4/9/12 started 7.30.2
|
4/9/12 started 7.30.2
|
||||||
- sequential stops all threads on error
|
- sequential stops all threads on error
|
||||||
|
- sequential delays ahead threads rather than blocking them completely
|
||||||
|
|
||||||
6/8/12 started 7.30.1
|
6/8/12 started 7.30.1
|
||||||
- fixes to dzsave: shrink down to a 1x1 pixel tile, round image size up on
|
- fixes to dzsave: shrink down to a 1x1 pixel tile, round image size up on
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
* - use linecache
|
* - use linecache
|
||||||
* 4/9/12
|
* 4/9/12
|
||||||
* - stop all threads on error
|
* - stop all threads on error
|
||||||
|
* - don't stall forever, just delay ahead threads
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -62,6 +63,10 @@
|
|||||||
|
|
||||||
#include "conversion.h"
|
#include "conversion.h"
|
||||||
|
|
||||||
|
/* Stall threads that run ahead for this long, in seconds.
|
||||||
|
*/
|
||||||
|
#define STALL_TIME (0.1)
|
||||||
|
|
||||||
typedef struct _VipsSequential {
|
typedef struct _VipsSequential {
|
||||||
VipsConversion parent_instance;
|
VipsConversion parent_instance;
|
||||||
|
|
||||||
@ -116,13 +121,12 @@ vips_sequential_generate( VipsRegion *or,
|
|||||||
vips_diag( "VipsSequential",
|
vips_diag( "VipsSequential",
|
||||||
"request for %d lines, starting at line %d",
|
"request for %d lines, starting at line %d",
|
||||||
r->height, r->top );
|
r->height, r->top );
|
||||||
retry:
|
|
||||||
|
|
||||||
g_mutex_lock( sequential->lock );
|
g_mutex_lock( sequential->lock );
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "thread %p has lock ...\n", g_thread_self() );
|
VIPS_DEBUG_MSG( "thread %p has lock ...\n", g_thread_self() );
|
||||||
|
|
||||||
/* If we've seen an error, everything must stop or we'll deadlock.
|
/* If we've seen an error, everything must stop.
|
||||||
*/
|
*/
|
||||||
if( sequential->error ) {
|
if( sequential->error ) {
|
||||||
g_mutex_unlock( sequential->lock );
|
g_mutex_unlock( sequential->lock );
|
||||||
@ -131,19 +135,27 @@ retry:
|
|||||||
|
|
||||||
if( r->top > sequential->y_pos &&
|
if( r->top > sequential->y_pos &&
|
||||||
sequential->y_pos > 0 ) {
|
sequential->y_pos > 0 ) {
|
||||||
|
GTimeVal time;
|
||||||
|
|
||||||
/* We have started reading (y_pos > 0) and this request is for
|
/* We have started reading (y_pos > 0) and this request is for
|
||||||
* stuff beyond that, stall.
|
* stuff beyond that, stall for a short while to give other
|
||||||
|
* threads time to catch up.
|
||||||
*/
|
*/
|
||||||
VIPS_DEBUG_MSG( "thread %p stalling ...\n", g_thread_self() );
|
VIPS_DEBUG_MSG( "thread %p stalling for up to %gs ...\n",
|
||||||
g_cond_wait( sequential->ready, sequential->lock );
|
STALL_TIME, g_thread_self() );
|
||||||
VIPS_DEBUG_MSG( "thread %p awake again, retrying ...\n",
|
g_get_current_time( &time );
|
||||||
|
g_time_val_add( &time, STALL_TIME * 1000000 );
|
||||||
|
g_cond_timed_wait( sequential->ready,
|
||||||
|
sequential->lock, &time );
|
||||||
|
VIPS_DEBUG_MSG( "thread %p awake again ...\n",
|
||||||
g_thread_self() );
|
g_thread_self() );
|
||||||
g_mutex_unlock( sequential->lock );
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a request for something some way down the image, and we've
|
/* This is a request for something some way down the image, and we've
|
||||||
* not read anything yet. Probably the operation is something like
|
* either not read anything yet or fallen through from the stall
|
||||||
|
* above.
|
||||||
|
*
|
||||||
|
* Probably the operation is something like
|
||||||
* extract_area and we should skip the initial part of the image. In
|
* extract_area and we should skip the initial part of the image. In
|
||||||
* fact we read to cache.
|
* fact we read to cache.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user