Merge commit '4c263a36e9e728b5ab5cc1f4f3cafe5738a6b6e7' into 8.11

This commit is contained in:
John Cupitt 2021-06-07 14:26:58 +01:00
commit 939437d56e
5 changed files with 95 additions and 50 deletions

View File

@ -5703,16 +5703,3 @@ vips_popenf( const char *fmt, const char *mode, ... )
return( NULL ); return( NULL );
} }
GThread *
vips_g_thread_new( const char *domain, GThreadFunc func, gpointer data )
{
vips_error( "vips_g_thread_new", "%s", _( "deprecated" ) );
return( NULL );
}
void *
vips_g_thread_join( GThread *thread )
{
vips_error( "vips_g_thread_join", "%s", _( "deprecated" ) );
return( NULL );
}

View File

@ -47,6 +47,11 @@ void vips_g_mutex_free( GMutex * );
GCond *vips_g_cond_new( void ); GCond *vips_g_cond_new( void );
void vips_g_cond_free( GCond * ); void vips_g_cond_free( GCond * );
/* ... and for GThread.
*/
GThread *vips_g_thread_new( const char *, GThreadFunc, gpointer );
void *vips_g_thread_join( GThread *thread );
gboolean vips_thread_isworker( void ); gboolean vips_thread_isworker( void );
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1224,11 +1224,6 @@ VipsWindow *vips_window_ref( VipsImage *im, int top, int height );
FILE *vips_popenf( const char *fmt, const char *mode, ... ) FILE *vips_popenf( const char *fmt, const char *mode, ... )
__attribute__((format(printf, 1, 3))); __attribute__((format(printf, 1, 3)));
/* old GThread API.
*/
GThread *vips_g_thread_new( const char *, GThreadFunc, gpointer );
void *vips_g_thread_join( GThread *thread );
/* This stuff is very, very old and should not be used by anyone now. /* This stuff is very, very old and should not be used by anyone now.
*/ */
#ifdef VIPS_ENABLE_ANCIENT #ifdef VIPS_ENABLE_ANCIENT

View File

@ -167,29 +167,22 @@ typedef struct _RenderThreadStateClass {
G_DEFINE_TYPE( RenderThreadState, render_thread_state, VIPS_TYPE_THREAD_STATE ); G_DEFINE_TYPE( RenderThreadState, render_thread_state, VIPS_TYPE_THREAD_STATE );
/* A boolean indicating if the bg render thread is running. /* The BG thread which sits waiting to do some calculations, and the semaphore
* it waits on holding the number of renders with dirty tiles.
*/ */
static gboolean render_running = FALSE; static GThread *render_thread = NULL;
/* Set this to ask the render thread to quit. /* Set this to ask the render thread to quit.
*/ */
static gboolean render_kill = FALSE; static gboolean render_kill = FALSE;
/* All the renders with dirty tiles. /* All the renders with dirty tiles, and a semaphore that the bg render thread
* waits on.
*/ */
static GMutex *render_dirty_lock = NULL; static GMutex *render_dirty_lock = NULL;
static GSList *render_dirty_all = NULL; static GSList *render_dirty_all = NULL;
/* A semaphore where the bg render thread waits on holding the number of
* renders with dirty tiles
*/
static VipsSemaphore n_render_dirty_sem; static VipsSemaphore n_render_dirty_sem;
/* A semaphore where the main thread waits for when the bg render thread
* is shutdown.
*/
static VipsSemaphore render_finish;
/* Set this to make the bg thread stop and reschedule. /* Set this to make the bg thread stop and reschedule.
*/ */
static gboolean render_reschedule = FALSE; static gboolean render_reschedule = FALSE;
@ -452,7 +445,10 @@ vips__render_shutdown( void )
if( render_dirty_lock ) { if( render_dirty_lock ) {
g_mutex_lock( render_dirty_lock ); g_mutex_lock( render_dirty_lock );
if( render_running ) { if( render_thread ) {
GThread *thread;
thread = render_thread;
render_reschedule = TRUE; render_reschedule = TRUE;
render_kill = TRUE; render_kill = TRUE;
@ -460,16 +456,13 @@ vips__render_shutdown( void )
vips_semaphore_up( &n_render_dirty_sem ); vips_semaphore_up( &n_render_dirty_sem );
vips_semaphore_down( &render_finish ); (void) vips_g_thread_join( thread );
render_running = FALSE;
} }
else else
g_mutex_unlock( render_dirty_lock ); g_mutex_unlock( render_dirty_lock );
VIPS_FREEF( vips_g_mutex_free, render_dirty_lock ); VIPS_FREEF( vips_g_mutex_free, render_dirty_lock );
vips_semaphore_destroy( &n_render_dirty_sem ); vips_semaphore_destroy( &n_render_dirty_sem );
vips_semaphore_destroy( &render_finish );
} }
} }
@ -1008,8 +1001,8 @@ render_dirty_get( void )
/* Loop for the background render manager thread. /* Loop for the background render manager thread.
*/ */
static void static void *
render_thread_main( void *data, void *user_data ) render_thread_main( void *client )
{ {
Render *render; Render *render;
@ -1044,29 +1037,23 @@ render_thread_main( void *data, void *user_data )
} }
} }
/* We are exiting: tell the main thread. /* We are exiting, so render_thread must now be NULL.
*/ */
vips_semaphore_up( &render_finish ); render_thread = NULL;
return( NULL );
} }
static void * static void *
vips__sink_screen_init( void *data ) vips__sink_screen_init( void *data )
{ {
g_assert( !render_running ); g_assert( !render_thread );
g_assert( !render_dirty_lock ); g_assert( !render_dirty_lock );
render_dirty_lock = vips_g_mutex_new(); render_dirty_lock = vips_g_mutex_new();
vips_semaphore_init( &n_render_dirty_sem, 0, "n_render_dirty" ); vips_semaphore_init( &n_render_dirty_sem, 0, "n_render_dirty" );
vips_semaphore_init( &render_finish, 0, "render_finish" ); render_thread = vips_g_thread_new( "sink_screen",
render_thread_main, NULL );
if( vips__thread_execute( "sink_screen", render_thread_main,
NULL ) ) {
vips_error( "vips_sink_screen_init",
"%s", _( "unable to init render thread" ) );
return( NULL );
}
render_running = TRUE;
return( NULL ); return( NULL );
} }

View File

@ -182,6 +182,77 @@ vips_thread_isworker( void )
return( g_private_get( is_worker_key ) != NULL ); return( g_private_get( is_worker_key ) != NULL );
} }
typedef struct {
const char *domain;
GThreadFunc func;
gpointer data;
} VipsThreadInfo;
static void *
vips_thread_run( gpointer data )
{
VipsThreadInfo *info = (VipsThreadInfo *) data;
void *result;
/* Set this to something (anything) to tag this thread as a vips
* worker.
*/
g_private_set( is_worker_key, data );
if( vips__thread_profile )
vips__thread_profile_attach( info->domain );
result = info->func( info->data );
g_free( info );
vips_thread_shutdown();
return( result );
}
GThread *
vips_g_thread_new( const char *domain, GThreadFunc func, gpointer data )
{
GThread *thread;
VipsThreadInfo *info;
GError *error = NULL;
info = g_new( VipsThreadInfo, 1 );
info->domain = domain;
info->func = func;
info->data = data;
thread = g_thread_try_new( domain, vips_thread_run, info, &error );
VIPS_DEBUG_MSG_RED( "vips_g_thread_new: g_thread_create( %s ) = %p\n",
domain, thread );
if( !thread ) {
if( error )
vips_g_error( &error );
else
vips_error( domain,
"%s", _( "unable to create thread" ) );
}
return( thread );
}
void *
vips_g_thread_join( GThread *thread )
{
void *result;
result = g_thread_join( thread );
VIPS_DEBUG_MSG_RED( "vips_g_thread_join: g_thread_join( %p )\n",
thread );
return( result );
}
typedef struct { typedef struct {
/* An name for this thread. /* An name for this thread.
*/ */