Merge remote-tracking branch 'origin/master' into colour
Conflicts: libvips/colour/im_icc_transform.c
This commit is contained in:
commit
40604e776a
@ -10,10 +10,13 @@
|
||||
- openslide2vips gets underlying tile size from openslide
|
||||
- embed has 'background' option
|
||||
- dzsave --layout google has a @background option
|
||||
- update for new glib threading API
|
||||
- remove no threads option
|
||||
|
||||
2/10/12 started 7.30.4
|
||||
- remove options from format string in .dzi (thanks Martin)
|
||||
- vipsCC.pc required the wrong version of vips (thanks Alessandro)
|
||||
- larger max tile size for dzsave
|
||||
|
||||
13/9/12 started 7.30.3
|
||||
- linecache sized itself too large
|
||||
|
19
configure.in
19
configure.in
@ -318,16 +318,14 @@ AC_CHECK_LIB(m,hypot,[AC_DEFINE(HAVE_HYPOT,1,[have hypot() in libm.])])
|
||||
PKG_CHECK_MODULES(REQUIRED, glib-2.0 >= 2.6 gmodule-2.0 >= 2.4 libxml-2.0 gobject-2.0)
|
||||
PACKAGES_USED="$PACKAGES_USED glib-2.0 gmodule-2.0 libxml-2.0 gobject-2.0"
|
||||
|
||||
# option to eval without threads
|
||||
AC_ARG_ENABLE(threads,
|
||||
AS_HELP_STRING([--enable-threads], [evaluate with threads (default: yes)]))
|
||||
|
||||
if test x"$enable_threads" != "xno"; then
|
||||
AC_DEFINE(HAVE_THREADS,1,[threaded evaluation])
|
||||
PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
|
||||
PACKAGES_USED="$PACKAGES_USED gthread-2.0"
|
||||
enable_threads=yes
|
||||
fi
|
||||
# after 2.32 there are a new set of thread functions, annoyingly
|
||||
PKG_CHECK_MODULES(THREADS, glib-2.0 >= 2.32,[
|
||||
AC_DEFINE(HAVE_MUTEX_INIT,1,[define if your glib has g_mutex_init().])
|
||||
AC_DEFINE(HAVE_COND_INIT,1,[define if your glib has g_cond_init().])
|
||||
AC_DEFINE(HAVE_THREAD_NEW,1,[define if your glib has g_thread_new().])
|
||||
AC_DEFINE(HAVE_PRIVATE_INIT,1,[define if your glib has G_PRIVATE_INIT().])
|
||||
AC_DEFINE(HAVE_VALUE_GET_SCHAR,1,[define if your glib has g_value_get_schar().])
|
||||
])
|
||||
|
||||
# check for gtk-doc
|
||||
GTK_DOC_CHECK(1.9)
|
||||
@ -734,7 +732,6 @@ native win32: $vips_os_win32
|
||||
native OS X: $vips_os_darwin
|
||||
open files in binary mode: $vips_binary_open
|
||||
enable debug: $enable_debug
|
||||
evaluate with threads: $enable_threads
|
||||
build C++ components: $enable_cxx
|
||||
build docs with gtkdoc: $enable_gtk_doc
|
||||
gobject introspection: $found_introspection
|
||||
|
@ -39,7 +39,7 @@ $(PDF): $(SRC)
|
||||
pdflatex vipsmanual.tex
|
||||
pdflatex vipsmanual.tex
|
||||
|
||||
.PHONEY: html
|
||||
.PHONY: html
|
||||
html:
|
||||
-rm -rf vipsmanual
|
||||
mkdir vipsmanual
|
||||
@ -48,7 +48,7 @@ html:
|
||||
-rm vipsmanual/figs/*.svg
|
||||
-rm vipsmanual/*.png
|
||||
|
||||
.PHONEY: clean
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -f *.4ct
|
||||
-rm -f *.4tc
|
||||
|
@ -169,7 +169,7 @@ vips_icc_dispose( GObject *gobject )
|
||||
VIPS_FREEF( cmsDeleteTransform, icc->trans );
|
||||
VIPS_FREEF( cmsCloseProfile, icc->in_profile );
|
||||
VIPS_FREEF( cmsCloseProfile, icc->out_profile );
|
||||
VIPS_FREEF( g_mutex_free, icc->lock );
|
||||
VIPS_FREEF( vips_g_mutex_free, icc->lock );
|
||||
|
||||
G_OBJECT_CLASS( vips_icc_parent_class )->dispose( gobject );
|
||||
}
|
||||
@ -324,7 +324,7 @@ vips_icc_class_init( VipsIccClass *class )
|
||||
static void
|
||||
vips_icc_init( VipsIcc *icc )
|
||||
{
|
||||
icc->lock = g_mutex_new();
|
||||
icc->lock = vips_g_mutex_new();
|
||||
icc->intent = VIPS_INTENT_RELATIVE;
|
||||
icc->depth = 8;
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ vips_sequential_dispose( GObject *gobject )
|
||||
{
|
||||
VipsSequential *sequential = (VipsSequential *) gobject;
|
||||
|
||||
VIPS_FREEF( g_mutex_free, sequential->lock );
|
||||
VIPS_FREEF( g_cond_free, sequential->ready );
|
||||
VIPS_FREEF( vips_g_mutex_free, sequential->lock );
|
||||
VIPS_FREEF( vips_g_cond_free, sequential->ready );
|
||||
|
||||
G_OBJECT_CLASS( vips_sequential_parent_class )->dispose( gobject );
|
||||
}
|
||||
@ -135,18 +135,16 @@ vips_sequential_generate( VipsRegion *or,
|
||||
|
||||
if( r->top > sequential->y_pos &&
|
||||
sequential->y_pos > 0 ) {
|
||||
GTimeVal time;
|
||||
|
||||
/* We have started reading (y_pos > 0) and this request is for
|
||||
* stuff beyond that, stall for a short while to give other
|
||||
* threads time to catch up.
|
||||
*
|
||||
* The stall can be cancelled by a signal on @ready.
|
||||
*/
|
||||
VIPS_DEBUG_MSG( "thread %p stalling for up to %gs ...\n",
|
||||
STALL_TIME, g_thread_self() );
|
||||
g_get_current_time( &time );
|
||||
g_time_val_add( &time, STALL_TIME * 1000000 );
|
||||
g_cond_timed_wait( sequential->ready,
|
||||
sequential->lock, &time );
|
||||
vips_g_cond_timed_wait( sequential->ready,
|
||||
sequential->lock, STALL_TIME * 1000000 );
|
||||
VIPS_DEBUG_MSG( "thread %p awake again ...\n",
|
||||
g_thread_self() );
|
||||
}
|
||||
@ -156,7 +154,8 @@ vips_sequential_generate( VipsRegion *or,
|
||||
* above.
|
||||
*
|
||||
* Probably the operation is something like extract_area and we should
|
||||
* skip the initial part of the image. In fact, we read to cache.
|
||||
* skip the initial part of the image. In fact, we read to cache,
|
||||
* since it may be useful.
|
||||
*/
|
||||
if( r->top > sequential->y_pos ) {
|
||||
VipsRect area;
|
||||
@ -293,8 +292,8 @@ static void
|
||||
vips_sequential_init( VipsSequential *sequential )
|
||||
{
|
||||
sequential->trace = FALSE;
|
||||
sequential->lock = g_mutex_new();
|
||||
sequential->ready = g_cond_new();
|
||||
sequential->lock = vips_g_mutex_new();
|
||||
sequential->ready = vips_g_cond_new();
|
||||
sequential->tile_height = 1;
|
||||
sequential->error = 0;
|
||||
}
|
||||
|
@ -144,8 +144,8 @@ vips_block_cache_dispose( GObject *gobject )
|
||||
VipsBlockCache *cache = (VipsBlockCache *) gobject;
|
||||
|
||||
vips_block_cache_drop_all( cache );
|
||||
VIPS_FREEF( g_mutex_free, cache->lock );
|
||||
VIPS_FREEF( g_cond_free, cache->new_tile );
|
||||
VIPS_FREEF( vips_g_mutex_free, cache->lock );
|
||||
VIPS_FREEF( vips_g_cond_free, cache->new_tile );
|
||||
|
||||
G_OBJECT_CLASS( vips_block_cache_parent_class )->dispose( gobject );
|
||||
}
|
||||
@ -489,8 +489,8 @@ vips_block_cache_init( VipsBlockCache *cache )
|
||||
|
||||
cache->time = 0;
|
||||
cache->ntiles = 0;
|
||||
cache->lock = g_mutex_new();
|
||||
cache->new_tile = g_cond_new();
|
||||
cache->lock = vips_g_mutex_new();
|
||||
cache->new_tile = vips_g_cond_new();
|
||||
cache->tiles = g_hash_table_new_full(
|
||||
(GHashFunc) vips_rect_hash,
|
||||
(GEqualFunc) vips_rect_equal,
|
||||
|
@ -105,7 +105,7 @@ tile_destroy( Tile *tile )
|
||||
static void
|
||||
read_destroy( Read *read )
|
||||
{
|
||||
IM_FREEF( g_mutex_free, read->lock );
|
||||
IM_FREEF( vips_g_mutex_free, read->lock );
|
||||
|
||||
while( read->cache ) {
|
||||
Tile *tile = (Tile *) read->cache->data;
|
||||
@ -131,7 +131,7 @@ read_new( IMAGE *in, IMAGE *out,
|
||||
read->max_tiles = max_tiles;
|
||||
read->time = 0;
|
||||
read->ntiles = 0;
|
||||
read->lock = g_mutex_new();
|
||||
read->lock = vips_g_mutex_new();
|
||||
read->cache = NULL;
|
||||
|
||||
if( im_add_close_callback( out,
|
||||
|
@ -1129,7 +1129,7 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
||||
_( "Tile overlap in pixels" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveDz, overlap ),
|
||||
0, 1024, 0 );
|
||||
0, 8192, 0 );
|
||||
|
||||
VIPS_ARG_INT( class, "tile_size", 11,
|
||||
_( "Tile size" ),
|
||||
|
@ -133,7 +133,7 @@ static void
|
||||
vips_fits_close( VipsFits *fits )
|
||||
{
|
||||
VIPS_FREE( fits->filename );
|
||||
VIPS_FREEF( g_mutex_free, fits->lock );
|
||||
VIPS_FREEF( vips_g_mutex_free, fits->lock );
|
||||
|
||||
if( fits->fptr ) {
|
||||
int status;
|
||||
@ -180,7 +180,7 @@ vips_fits_new_read( const char *filename, VipsImage *out, int band_select )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
fits->lock = g_mutex_new();
|
||||
fits->lock = vips_g_mutex_new();
|
||||
|
||||
return( fits );
|
||||
}
|
||||
@ -578,7 +578,7 @@ vips_fits_new_write( VipsImage *in, const char *filename )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
fits->lock = g_mutex_new();
|
||||
fits->lock = vips_g_mutex_new();
|
||||
|
||||
return( fits );
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ read_destroy( VipsImage *im, Read *read )
|
||||
VIPS_FREEF( DestroyImageInfo, read->image_info );
|
||||
VIPS_FREE( read->frames );
|
||||
DestroyExceptionInfo( &read->exception );
|
||||
VIPS_FREEF( g_mutex_free, read->lock );
|
||||
VIPS_FREEF( vips_g_mutex_free, read->lock );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -161,7 +161,7 @@ read_new( const char *filename, VipsImage *im )
|
||||
read->n_frames = 0;
|
||||
read->frames = NULL;
|
||||
read->frame_height = 0;
|
||||
read->lock = g_mutex_new();
|
||||
read->lock = vips_g_mutex_new();
|
||||
|
||||
g_signal_connect( im, "close", G_CALLBACK( read_destroy ), read );
|
||||
|
||||
|
@ -1075,7 +1075,7 @@ write_tif_tilewise( TiffWrite *tw )
|
||||
return( -1 );
|
||||
|
||||
g_assert( !tw->write_lock );
|
||||
tw->write_lock = g_mutex_new();
|
||||
tw->write_lock = vips_g_mutex_new();
|
||||
|
||||
/* Write pyramid too? Only bother if bigger than tile size.
|
||||
*/
|
||||
@ -1179,7 +1179,7 @@ free_tiff_write( TiffWrite *tw )
|
||||
|
||||
VIPS_FREEF( TIFFClose, tw->tif );
|
||||
VIPS_FREEF( vips_free, tw->tbuf );
|
||||
VIPS_FREEF( g_mutex_free, tw->write_lock );
|
||||
VIPS_FREEF( vips_g_mutex_free, tw->write_lock );
|
||||
VIPS_FREEF( free_pyramid, tw->layer );
|
||||
VIPS_FREEF( vips_free, tw->icc_profile );
|
||||
}
|
||||
|
@ -35,48 +35,21 @@
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
/* Stack size for each thread. We need to set this explicitly because some
|
||||
* systems have a very low default.
|
||||
|
||||
FIXME ... should have an environment variable for this?
|
||||
|
||||
/* We need wrappers over g_mutex_new(), it was replaced by g_mutex_init() in
|
||||
* glib 2.32+
|
||||
*/
|
||||
#define VIPS__DEFAULT_STACK_SIZE (2 * 1024 * 1024)
|
||||
GMutex *vips_g_mutex_new( void );
|
||||
void vips_g_mutex_free( GMutex * );
|
||||
|
||||
#ifndef HAVE_THREADS
|
||||
#undef g_thread_supported
|
||||
#define g_thread_supported() (0)
|
||||
|
||||
#define g_thread_init vips__g_thread_init
|
||||
#define g_thread_join vips__g_thread_join
|
||||
#define g_thread_self vips__g_thread_self
|
||||
#define g_thread_create_full vips__g_thread_create_full
|
||||
|
||||
/* We don't need a shadow imlementation of g_thread_create(), even though we
|
||||
* use it, because it's just a macro over g_thread_create_full().
|
||||
/* Same for GCond. And we need a wrapper for waiting too.
|
||||
*/
|
||||
GCond *vips_g_cond_new( void );
|
||||
void vips_g_cond_free( GCond * );
|
||||
void vips_g_cond_timed_wait( GCond *, GMutex *, gint64 );
|
||||
|
||||
void vips__g_thread_init( GThreadFunctions *vtable );
|
||||
gpointer vips__g_thread_join( GThread * );
|
||||
gpointer vips__g_thread_self( void );
|
||||
GThread *vips__g_thread_create_full( GThreadFunc,
|
||||
gpointer, gulong, gboolean, gboolean, GThreadPriority, GError ** );
|
||||
|
||||
#undef g_mutex_new
|
||||
#undef g_mutex_free
|
||||
#undef g_mutex_lock
|
||||
#undef g_mutex_unlock
|
||||
|
||||
#define g_mutex_new vips__g_mutex_new
|
||||
#define g_mutex_free vips__g_mutex_free
|
||||
#define g_mutex_lock vips__g_mutex_lock
|
||||
#define g_mutex_unlock vips__g_mutex_unlock
|
||||
|
||||
GMutex *vips__g_mutex_new( void );
|
||||
void vips__g_mutex_free( GMutex * );
|
||||
void vips__g_mutex_lock( GMutex * );
|
||||
void vips__g_mutex_unlock( GMutex * );
|
||||
#endif /*!HAVE_THREADS*/
|
||||
/* ... and for GThread.
|
||||
*/
|
||||
GThread *vips_g_thread_new( const char *, GThreadFunc, gpointer );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -72,15 +72,8 @@ static GSList *vips__buffers_all = NULL;
|
||||
static int buffer_cache_n = 0;
|
||||
#endif /*DEBUG_CREATE*/
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static GPrivate *thread_buffer_cache_key = NULL;
|
||||
#else /*!HAVE_THREADS*/
|
||||
static VipsBufferCache *thread_buffer_cache = NULL;
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
/* Only need this if we're threading and need to do a lot of start/stop.
|
||||
*/
|
||||
#ifdef HAVE_THREADS
|
||||
static void
|
||||
buffer_cache_free( VipsBufferCache *cache )
|
||||
{
|
||||
@ -95,7 +88,6 @@ buffer_cache_free( VipsBufferCache *cache )
|
||||
VIPS_FREEF( g_hash_table_destroy, cache->hash );
|
||||
VIPS_FREE( cache );
|
||||
}
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
static void
|
||||
buffer_cache_list_free( VipsBufferCacheList *cache_list )
|
||||
@ -163,16 +155,10 @@ buffer_cache_get( void )
|
||||
{
|
||||
VipsBufferCache *cache;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
if( !(cache = g_private_get( thread_buffer_cache_key )) ) {
|
||||
cache = buffer_cache_new();
|
||||
g_private_set( thread_buffer_cache_key, cache );
|
||||
}
|
||||
#else /*!HAVE_THREADS*/
|
||||
if( !thread_buffer_cache )
|
||||
thread_buffer_cache = buffer_cache_new();
|
||||
cache = thread_buffer_cache;
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
return( cache );
|
||||
}
|
||||
@ -474,9 +460,14 @@ vips_buffer_print( VipsBuffer *buffer )
|
||||
void
|
||||
vips__buffer_init( void )
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
#ifdef HAVE_PRIVATE_INIT
|
||||
static GPrivate private =
|
||||
G_PRIVATE_INIT( (GDestroyNotify) buffer_cache_free );
|
||||
|
||||
thread_buffer_cache_key = &private;
|
||||
#else
|
||||
if( !thread_buffer_cache_key )
|
||||
thread_buffer_cache_key = g_private_new(
|
||||
(GDestroyNotify) buffer_cache_free );
|
||||
#endif /*HAVE_THREADS*/
|
||||
#endif
|
||||
}
|
||||
|
@ -112,6 +112,14 @@ static GMutex *vips_cache_lock = NULL;
|
||||
#define INT64_HASH(X) (g_direct_hash(X))
|
||||
#define DOUBLE_HASH(X) (g_direct_hash(X))
|
||||
|
||||
/* Old glibs use g_value_get_char(), new ones g_value_get_schar().
|
||||
*/
|
||||
#ifdef HAVE_VALUE_GET_SCHAR
|
||||
#define VIPS_VALUE_GET_CHAR g_value_get_schar
|
||||
#else
|
||||
#define VIPS_VALUE_GET_CHAR g_value_get_char
|
||||
#endif
|
||||
|
||||
/* Pass in the pspec so we can get the generic type. For example, a
|
||||
* held in a GParamSpec allowing OBJECT, but the value could be of type
|
||||
* VipsImage. generics are much faster to compare.
|
||||
@ -128,7 +136,7 @@ vips_value_hash( GParamSpec *pspec, GValue *value )
|
||||
if( generic == G_TYPE_PARAM_BOOLEAN )
|
||||
return( (unsigned int) g_value_get_boolean( value ) );
|
||||
else if( generic == G_TYPE_PARAM_CHAR )
|
||||
return( (unsigned int) g_value_get_char( value ) );
|
||||
return( (unsigned int) VIPS_VALUE_GET_CHAR( value ) );
|
||||
else if( generic == G_TYPE_PARAM_UCHAR )
|
||||
return( (unsigned int) g_value_get_uchar( value ) );
|
||||
else if( generic == G_TYPE_PARAM_INT )
|
||||
@ -230,8 +238,8 @@ vips_value_equal( GParamSpec *pspec, GValue *v1, GValue *v2 )
|
||||
return( g_value_get_boolean( v1 ) ==
|
||||
g_value_get_boolean( v2 ) );
|
||||
else if( generic == G_TYPE_PARAM_CHAR )
|
||||
return( g_value_get_char( v1 ) ==
|
||||
g_value_get_char( v2 ) );
|
||||
return( VIPS_VALUE_GET_CHAR( v1 ) ==
|
||||
VIPS_VALUE_GET_CHAR( v2 ) );
|
||||
if( generic == G_TYPE_PARAM_UCHAR )
|
||||
return( g_value_get_uchar( v1 ) ==
|
||||
g_value_get_uchar( v2 ) );
|
||||
@ -416,7 +424,7 @@ void
|
||||
vips__cache_init( void )
|
||||
{
|
||||
if( !vips_cache_table ) {
|
||||
vips_cache_lock = g_mutex_new();
|
||||
vips_cache_lock = vips_g_mutex_new();
|
||||
|
||||
vips_cache_table = g_hash_table_new(
|
||||
(GHashFunc) vips_operation_hash,
|
||||
|
@ -241,7 +241,7 @@ vips_image_finalize( GObject *gobject )
|
||||
*/
|
||||
vips_image_delete( image );
|
||||
|
||||
VIPS_FREEF( g_mutex_free, image->sslock );
|
||||
VIPS_FREEF( vips_g_mutex_free, image->sslock );
|
||||
|
||||
VIPS_FREE( image->Hist );
|
||||
VIPS_FREEF( vips__gslist_gvalue_free, image->history_list );
|
||||
@ -1057,7 +1057,7 @@ vips_image_init( VipsImage *image )
|
||||
image->Yres = 1.0;
|
||||
|
||||
image->fd = -1; /* since 0 is stdout */
|
||||
image->sslock = g_mutex_new();
|
||||
image->sslock = vips_g_mutex_new();
|
||||
|
||||
image->sizeof_header = VIPS_SIZEOF_HEADER;
|
||||
|
||||
|
@ -195,13 +195,13 @@ vips_init( const char *argv0 )
|
||||
|
||||
/* Older glibs need this.
|
||||
*/
|
||||
#ifdef G_THREADS_ENABLED
|
||||
#ifndef HAVE_THREAD_NEW
|
||||
if( !g_thread_supported() )
|
||||
g_thread_init( NULL );
|
||||
#endif /*G_THREADS_ENABLED*/
|
||||
#endif
|
||||
|
||||
if( !vips__global_lock )
|
||||
vips__global_lock = g_mutex_new();
|
||||
vips__global_lock = vips_g_mutex_new();
|
||||
|
||||
VIPS_SETSTR( vips__argv0, argv0 );
|
||||
|
||||
|
@ -240,21 +240,13 @@ vips_tracked_free( void *s )
|
||||
g_free( s );
|
||||
}
|
||||
|
||||
/* g_mutex_new() is a macro.
|
||||
*/
|
||||
static void *
|
||||
vips_tracked_mutex_new( void *data )
|
||||
{
|
||||
return( g_mutex_new() );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_tracked_init( void )
|
||||
{
|
||||
static GOnce vips_tracked_once = G_ONCE_INIT;
|
||||
|
||||
vips_tracked_mutex = g_once( &vips_tracked_once,
|
||||
vips_tracked_mutex_new, NULL );
|
||||
(GThreadFunc) vips_g_mutex_new, NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1271,7 +1271,7 @@ vips_object_class_init( VipsObjectClass *class )
|
||||
if( !vips__object_all ) {
|
||||
vips__object_all = g_hash_table_new(
|
||||
g_direct_hash, g_direct_equal );
|
||||
vips__object_all_lock = g_mutex_new();
|
||||
vips__object_all_lock = vips_g_mutex_new();
|
||||
}
|
||||
|
||||
gobject_class->dispose = vips_object_dispose;
|
||||
|
@ -58,19 +58,15 @@ vips_semaphore_init( VipsSemaphore *s, int v, char *name )
|
||||
{
|
||||
s->v = v;
|
||||
s->name = name;
|
||||
#ifdef HAVE_THREADS
|
||||
s->mutex = g_mutex_new();
|
||||
s->cond = g_cond_new();
|
||||
#endif /*HAVE_THREADS*/
|
||||
s->mutex = vips_g_mutex_new();
|
||||
s->cond = vips_g_cond_new();
|
||||
}
|
||||
|
||||
void
|
||||
vips_semaphore_destroy( VipsSemaphore *s )
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
VIPS_FREEF( g_mutex_free, s->mutex );
|
||||
VIPS_FREEF( g_cond_free, s->cond );
|
||||
#endif /*HAVE_THREADS*/
|
||||
VIPS_FREEF( vips_g_mutex_free, s->mutex );
|
||||
VIPS_FREEF( vips_g_cond_free, s->cond );
|
||||
}
|
||||
|
||||
/* Add n to the semaphore and signal any threads that are blocked waiting
|
||||
@ -81,12 +77,10 @@ vips_semaphore_upn( VipsSemaphore *s, int n )
|
||||
{
|
||||
int value_after_op;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
g_mutex_lock( s->mutex );
|
||||
#endif /*HAVE_THREADS*/
|
||||
s->v += n;
|
||||
value_after_op = s->v;
|
||||
#ifdef HAVE_THREADS
|
||||
|
||||
/* If we are only incrementing by one, we only need to wake a single
|
||||
* thread. If we are incrementing by a lot, we must wake all threads.
|
||||
*/
|
||||
@ -95,7 +89,6 @@ vips_semaphore_upn( VipsSemaphore *s, int n )
|
||||
else
|
||||
g_cond_broadcast( s->cond );
|
||||
g_mutex_unlock( s->mutex );
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
#ifdef DEBUG_IO
|
||||
printf( "vips_semaphore_upn(\"%s\",%d) = %d\n",
|
||||
@ -122,16 +115,14 @@ vips_semaphore_downn( VipsSemaphore *s, int n )
|
||||
{
|
||||
int value_after_op;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
g_mutex_lock( s->mutex );
|
||||
|
||||
while( s->v < n )
|
||||
g_cond_wait( s->cond, s->mutex );
|
||||
#endif /*HAVE_THREADS*/
|
||||
s->v -= n;
|
||||
value_after_op = s->v;
|
||||
#ifdef HAVE_THREADS
|
||||
|
||||
g_mutex_unlock( s->mutex );
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
#ifdef DEBUG_IO
|
||||
printf( "vips_semaphore_downn(\"%s\",%d): %d\n",
|
||||
|
@ -171,7 +171,6 @@ wbuffer_write( WriteBuffer *wbuffer )
|
||||
&wbuffer->area, write->a );
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
/* Run this as a thread to do a BG write.
|
||||
*/
|
||||
static void *
|
||||
@ -200,7 +199,6 @@ wbuffer_write_thread( void *data )
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
static WriteBuffer *
|
||||
wbuffer_new( Write *write )
|
||||
@ -227,17 +225,13 @@ wbuffer_new( Write *write )
|
||||
*/
|
||||
vips__region_no_ownership( wbuffer->region );
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
/* Make this last (picks up parts of wbuffer on startup).
|
||||
*/
|
||||
if( !(wbuffer->thread = g_thread_create( wbuffer_write_thread, wbuffer,
|
||||
TRUE, NULL )) ) {
|
||||
vips_error( "wbuffer_new",
|
||||
"%s", _( "unable to create thread" ) );
|
||||
if( !(wbuffer->thread = vips_g_thread_new( "wbuffer",
|
||||
wbuffer_write_thread, wbuffer )) ) {
|
||||
wbuffer_free( wbuffer );
|
||||
return( NULL );
|
||||
}
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
return( wbuffer );
|
||||
}
|
||||
@ -266,13 +260,7 @@ wbuffer_flush( Write *write )
|
||||
|
||||
/* Set the background writer going for this buffer.
|
||||
*/
|
||||
#ifdef HAVE_THREADS
|
||||
vips_semaphore_up( &write->buf->go );
|
||||
#else
|
||||
/* No threads? Write ourselves synchronously.
|
||||
*/
|
||||
wbuffer_write( write->buf );
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -66,14 +66,6 @@
|
||||
#include <vips/thread.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
/* A have-threads we can test in if().
|
||||
*/
|
||||
#ifdef HAVE_THREADS
|
||||
static const int have_threads = 1;
|
||||
#else /*!HAVE_THREADS*/
|
||||
static const int have_threads = 0;
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
#ifdef VIPS_DEBUG_AMBER
|
||||
static int render_num_renders = 0;
|
||||
#endif /*VIPS_DEBUG_AMBER*/
|
||||
@ -228,8 +220,8 @@ render_free( Render *render )
|
||||
}
|
||||
g_mutex_unlock( render_dirty_lock );
|
||||
|
||||
g_mutex_free( render->ref_count_lock );
|
||||
g_mutex_free( render->lock );
|
||||
vips_g_mutex_free( render->ref_count_lock );
|
||||
vips_g_mutex_free( render->lock );
|
||||
|
||||
vips_slist_map2( render->all, (VipsSListMap2Fn) tile_free, NULL, NULL );
|
||||
VIPS_FREEF( g_slist_free, render->all );
|
||||
@ -520,23 +512,15 @@ render_thread_main( void *client )
|
||||
static int
|
||||
render_thread_create( void )
|
||||
{
|
||||
if( !have_threads )
|
||||
return( 0 );
|
||||
|
||||
if( !render_dirty_lock ) {
|
||||
render_dirty_lock = g_mutex_new();
|
||||
render_dirty_lock = vips_g_mutex_new();
|
||||
vips_semaphore_init( &render_dirty_sem, 0, "render_dirty_sem" );
|
||||
}
|
||||
|
||||
if( !render_thread && have_threads ) {
|
||||
if( !(render_thread = g_thread_create_full(
|
||||
render_thread_main, NULL,
|
||||
VIPS__DEFAULT_STACK_SIZE, TRUE, FALSE,
|
||||
G_THREAD_PRIORITY_NORMAL, NULL )) ) {
|
||||
vips_error( "sink_screen",
|
||||
"%s", _( "unable to create thread" ) );
|
||||
if( !render_thread ) {
|
||||
if( !(render_thread = vips_g_thread_new( "sink_screen",
|
||||
render_thread_main, NULL )) )
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
@ -595,7 +579,7 @@ render_new( VipsImage *in, VipsImage *out, VipsImage *mask,
|
||||
return( NULL );
|
||||
|
||||
render->ref_count = 1;
|
||||
render->ref_count_lock = g_mutex_new();
|
||||
render->ref_count_lock = vips_g_mutex_new();
|
||||
|
||||
render->in = in;
|
||||
render->out = out;
|
||||
@ -607,7 +591,7 @@ render_new( VipsImage *in, VipsImage *out, VipsImage *mask,
|
||||
render->notify = notify;
|
||||
render->a = a;
|
||||
|
||||
render->lock = g_mutex_new();
|
||||
render->lock = vips_g_mutex_new();
|
||||
|
||||
render->all = NULL;
|
||||
render->ntiles = 0;
|
||||
@ -746,7 +730,7 @@ tile_queue( Tile *tile, VipsRegion *reg )
|
||||
tile->painted = FALSE;
|
||||
tile_touch( tile );
|
||||
|
||||
if( render->notify && have_threads ) {
|
||||
if( render->notify ) {
|
||||
/* Add to the list of renders with dirty tiles. The bg
|
||||
* thread will pick it up and paint it. It can be already on
|
||||
* the dirty list.
|
||||
@ -755,7 +739,7 @@ tile_queue( Tile *tile, VipsRegion *reg )
|
||||
render_dirty_put( render );
|
||||
}
|
||||
else {
|
||||
/* No threads, or no notify ... paint the tile ourselves
|
||||
/* no notify ... paint the tile ourselves
|
||||
* sychronously. No need to notify the client since they'll
|
||||
* never see black tiles.
|
||||
*/
|
||||
@ -968,7 +952,6 @@ image_stop( void *seq, void *a, void *b )
|
||||
static int
|
||||
mask_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
Render *render = (Render *) a;
|
||||
VipsRect *r = &out->valid;
|
||||
int x, y;
|
||||
@ -1006,9 +989,6 @@ mask_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
||||
}
|
||||
|
||||
g_mutex_unlock( render->lock );
|
||||
#else /*!HAVE_THREADS*/
|
||||
vips_region_paint( out, &out->valid, 255 );
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -101,25 +101,104 @@ int vips__thinstrip_height = VIPS__THINSTRIP_HEIGHT;
|
||||
*/
|
||||
int vips__concurrency = 0;
|
||||
|
||||
#ifndef HAVE_THREADS
|
||||
/* If we're building without gthread, we need stubs for the g_thread_*() and
|
||||
* g_mutex_*() functions. <vips/thread.h> has #defines which point the g_
|
||||
* names here.
|
||||
/* Glib 2.32 revised the thread API. We need some compat functions.
|
||||
*/
|
||||
|
||||
void vips__g_thread_init( GThreadFunctions *vtable ) {}
|
||||
gpointer vips__g_thread_join( GThread *dummy ) { return( NULL ); }
|
||||
gpointer vips__g_thread_self( void ) { return( NULL ); }
|
||||
GThread *vips__g_thread_create_full( GThreadFunc d1,
|
||||
gpointer d2, gulong d3, gboolean d4, gboolean d5, GThreadPriority d6,
|
||||
GError **d7 )
|
||||
{ return( NULL ); }
|
||||
GMutex *
|
||||
vips_g_mutex_new( void )
|
||||
{
|
||||
GMutex *mutex;
|
||||
|
||||
GMutex *vips__g_mutex_new( void ) { return( NULL ); }
|
||||
void vips__g_mutex_free( GMutex *d ) {}
|
||||
void vips__g_mutex_lock( GMutex *d ) {}
|
||||
void vips__g_mutex_unlock( GMutex *d ) {}
|
||||
#endif /*!HAVE_THREADS*/
|
||||
#ifdef HAVE_MUTEX_INIT
|
||||
mutex = g_new( GMutex, 1 );
|
||||
g_mutex_init( mutex );
|
||||
#else
|
||||
mutex = g_mutex_new();
|
||||
#endif
|
||||
|
||||
return( mutex );
|
||||
}
|
||||
|
||||
void
|
||||
vips_g_mutex_free( GMutex *mutex )
|
||||
{
|
||||
#ifdef HAVE_MUTEX_INIT
|
||||
g_mutex_clear( mutex );
|
||||
g_free( mutex );
|
||||
#else
|
||||
g_mutex_free( mutex );
|
||||
#endif
|
||||
}
|
||||
|
||||
GCond *
|
||||
vips_g_cond_new( void )
|
||||
{
|
||||
GCond *cond;
|
||||
|
||||
#ifdef HAVE_COND_INIT
|
||||
cond = g_new( GCond, 1 );
|
||||
g_cond_init( cond );
|
||||
#else
|
||||
cond = g_cond_new();
|
||||
#endif
|
||||
|
||||
return( cond );
|
||||
}
|
||||
|
||||
void
|
||||
vips_g_cond_free( GCond *cond )
|
||||
{
|
||||
#ifdef HAVE_COND_INIT
|
||||
g_cond_clear( cond );
|
||||
g_free( cond );
|
||||
#else
|
||||
g_cond_free( cond );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wait until cond is signalled, or timeout us have passed.
|
||||
*
|
||||
* You can get spurious wakeups, use this in a loop.
|
||||
*/
|
||||
void
|
||||
vips_g_cond_timed_wait( GCond *cond, GMutex *mutex, gint64 timeout )
|
||||
{
|
||||
#ifdef HAVE_COND_INIT
|
||||
g_cond_wait_until( cond, mutex,
|
||||
g_get_monotonic_time() + timeout );
|
||||
#else
|
||||
GTimeVal time;
|
||||
|
||||
g_get_current_time( &time );
|
||||
g_time_val_add( &time, timeout );
|
||||
g_cond_timed_wait( cond, mutex, &time );
|
||||
#endif
|
||||
}
|
||||
|
||||
GThread *
|
||||
vips_g_thread_new( const char *domain, GThreadFunc func, gpointer data )
|
||||
{
|
||||
GThread *thread;
|
||||
GError *error = NULL;
|
||||
|
||||
#ifdef HAVE_THREAD_NEW
|
||||
thread = g_thread_try_new( domain, func, data, &error );
|
||||
#else
|
||||
thread = g_thread_create( func, data, TRUE, &error );
|
||||
#endif
|
||||
|
||||
if( !thread ) {
|
||||
if( error ) {
|
||||
vips_error( domain, "%s", error->message );
|
||||
g_error_free( error );
|
||||
}
|
||||
else
|
||||
vips_error( domain,
|
||||
"%s", _( "unable to create thread" ) );
|
||||
}
|
||||
|
||||
return( thread );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_concurrency_set:
|
||||
@ -564,7 +643,6 @@ vips_thread_work_unit( VipsThread *thr )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
/* What runs as a thread ... loop, waiting to be told to do stuff.
|
||||
*/
|
||||
static void *
|
||||
@ -592,7 +670,6 @@ vips_thread_main_loop( void *a )
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
/* Attach another thread to a threadpool.
|
||||
*/
|
||||
@ -628,22 +705,13 @@ vips_thread_new( VipsThreadpool *pool )
|
||||
}
|
||||
#endif /*TIME_THREAD*/
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
/* Make a worker thread. We have to use g_thread_create_full() because
|
||||
* we need to insist on a non-tiny stack. Some platforms default to
|
||||
* very small values (eg. various BSDs).
|
||||
*/
|
||||
if( !(thr->thread = g_thread_create_full( vips_thread_main_loop, thr,
|
||||
VIPS__DEFAULT_STACK_SIZE, TRUE, FALSE,
|
||||
G_THREAD_PRIORITY_NORMAL, NULL )) ) {
|
||||
vips_error( "vips_thread_new",
|
||||
"%s", _( "unable to create thread" ) );
|
||||
if( !(thr->thread = vips_g_thread_new( "worker",
|
||||
vips_thread_main_loop, thr )) ) {
|
||||
vips_thread_free( thr );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
VIPS_DEBUG_MSG_RED( "vips_thread_new: g_thread_create_full()\n" );
|
||||
#endif /*HAVE_THREADS*/
|
||||
VIPS_DEBUG_MSG_RED( "vips_thread_new: vips_g_thread_new()\n" );
|
||||
|
||||
return( thr );
|
||||
}
|
||||
@ -674,7 +742,7 @@ vips_threadpool_free( VipsThreadpool *pool )
|
||||
pool->im->filename, pool );
|
||||
|
||||
vips_threadpool_kill_threads( pool );
|
||||
VIPS_FREEF( g_mutex_free, pool->allocate_lock );
|
||||
VIPS_FREEF( vips_g_mutex_free, pool->allocate_lock );
|
||||
vips_semaphore_destroy( &pool->finish );
|
||||
vips_semaphore_destroy( &pool->tick );
|
||||
|
||||
@ -699,7 +767,7 @@ vips_threadpool_new( VipsImage *im )
|
||||
pool->im = im;
|
||||
pool->allocate = NULL;
|
||||
pool->work = NULL;
|
||||
pool->allocate_lock = g_mutex_new();
|
||||
pool->allocate_lock = vips_g_mutex_new();
|
||||
pool->nthr = vips_concurrency_get();
|
||||
pool->thr = NULL;
|
||||
vips_semaphore_init( &pool->finish, 0, "finish" );
|
||||
@ -879,15 +947,9 @@ vips_threadpool_run( VipsImage *im,
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
#ifdef HAVE_THREADS
|
||||
/* Wait for a tick from a worker.
|
||||
*/
|
||||
vips_semaphore_down( &pool->tick );
|
||||
#else
|
||||
/* No threads, do the work ourselves in the main thread.
|
||||
*/
|
||||
vips_thread_work_unit( pool->thr[0] );
|
||||
#endif /*HAVE_THREADS*/
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_threadpool_run: tick\n" );
|
||||
|
||||
|
@ -680,7 +680,7 @@ lr_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
|
||||
static void *
|
||||
lock_free( GMutex *lock )
|
||||
{
|
||||
g_mutex_free( lock );
|
||||
vips_g_mutex_free( lock );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
@ -767,10 +767,10 @@ im__build_mergestate( const char *domain,
|
||||
for( x = 0; x < ovlap->flsize; x++ )
|
||||
ovlap->first[x] = -1;
|
||||
|
||||
ovlap->fl_lock = g_mutex_new();
|
||||
ovlap->fl_lock = vips_g_mutex_new();
|
||||
if( im_add_close_callback( out,
|
||||
(im_callback_fn) lock_free, ovlap->fl_lock, NULL ) ) {
|
||||
g_mutex_free( ovlap->fl_lock );
|
||||
vips_g_mutex_free( ovlap->fl_lock );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ libvipsCC_la_LIBADD = \
|
||||
# swap the 'awk' line for this:
|
||||
# awk '{if($$1!="deprecated") print $$1}'` ; \
|
||||
# to not generate the wrappers for deprecated functions
|
||||
.PHONEY:
|
||||
vipsc++.cc:
|
||||
packages=`vips list packages | \
|
||||
awk '{print $$1}'` ; \
|
||||
|
@ -10,7 +10,6 @@ pkginclude_HEADERS = \
|
||||
# swap the 'awk' line for this:
|
||||
# awk '{if($$1!="deprecated") print $$1}'` ; \
|
||||
# to not generate the wrappers for deprecated functions
|
||||
.PHONEY:
|
||||
vipsc++.h:
|
||||
packages=`vips list packages | \
|
||||
awk '{print $$1}'` ; \
|
||||
|
Loading…
Reference in New Issue
Block a user