single-thread class init

See:

  https://github.com/jcupitt/libvips/issues/64

We were seeing races in class init on very-many-core machines. GObject
is supposed to single-thread class init, I think, so this shouldn't
happen. Perhaps class init via g_type_class_ref() is not
single-threaded.
This commit is contained in:
John Cupitt 2013-06-21 09:35:04 +01:00
parent 890d7b1205
commit b58f67aa90

View File

@ -2314,16 +2314,32 @@ test_name( VipsObjectClass *class, const char *nickname )
VipsObjectClass *
vips_class_find( const char *basename, const char *nickname )
{
static GOnce vips_class_find_once = G_ONCE_INIT;
static GMutex *vips_class_find_lock = NULL;
const char *classname = basename ? basename : "VipsObject";
VipsObjectClass *class;
GType base;
if( !(base = g_type_from_name( classname )) ||
!(class = vips_class_map_all( base,
(VipsClassMapFn) test_name, (void *) nickname )) )
if( !(base = g_type_from_name( classname )) )
return( NULL );
if( !vips_class_find_lock )
vips_class_find_lock = g_once( &vips_class_find_once,
(GThreadFunc) vips_g_mutex_new, NULL );
/* We have to single-thread class lookup. The first time this runs on
* a class, the g_type_class_ref() in vips_class_map_all() will
* trigger class build and construct the arg table. We musn't have
* this run more than once.
*/
g_mutex_lock( vips_class_find_lock );
class = vips_class_map_all( base,
(VipsClassMapFn) test_name, (void *) nickname );
g_mutex_unlock( vips_class_find_lock );
return( class );
}