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 );
}
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 );
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 );
#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, ... )
__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.
*/
#ifdef VIPS_ENABLE_ANCIENT

View File

@ -167,29 +167,22 @@ typedef struct _RenderThreadStateClass {
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.
*/
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 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;
/* 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.
*/
static gboolean render_reschedule = FALSE;
@ -452,7 +445,10 @@ vips__render_shutdown( void )
if( render_dirty_lock ) {
g_mutex_lock( render_dirty_lock );
if( render_running ) {
if( render_thread ) {
GThread *thread;
thread = render_thread;
render_reschedule = TRUE;
render_kill = TRUE;
@ -460,16 +456,13 @@ vips__render_shutdown( void )
vips_semaphore_up( &n_render_dirty_sem );
vips_semaphore_down( &render_finish );
render_running = FALSE;
(void) vips_g_thread_join( thread );
}
else
g_mutex_unlock( render_dirty_lock );
VIPS_FREEF( vips_g_mutex_free, render_dirty_lock );
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.
*/
static void
render_thread_main( void *data, void *user_data )
static void *
render_thread_main( void *client )
{
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 *
vips__sink_screen_init( void *data )
{
g_assert( !render_running );
g_assert( !render_thread );
g_assert( !render_dirty_lock );
render_dirty_lock = vips_g_mutex_new();
vips_semaphore_init( &n_render_dirty_sem, 0, "n_render_dirty" );
vips_semaphore_init( &render_finish, 0, "render_finish" );
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;
render_thread = vips_g_thread_new( "sink_screen",
render_thread_main, NULL );
return( NULL );
}

View File

@ -182,6 +182,77 @@ vips_thread_isworker( void )
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 {
/* An name for this thread.
*/