Merge commit '4c263a36e9e728b5ab5cc1f4f3cafe5738a6b6e7' into 8.11
This commit is contained in:
commit
939437d56e
@ -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 );
|
|
||||||
}
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user