BonoboXObject refcounting



Hi,

while trying to port Bonobo to glib HEAD this weekend I
found the following in BonoboXObject:

====
static void
bonobo_x_object_finalize_real (GtkObject *object)
{
	BonoboXObject *x_object;
	CORBA_Object   obj;
	
	x_object = BONOBO_X_OBJECT (object);
	obj = BONOBO_X_OBJECT_GET_CORBA (x_object);

	/* Setup the BonoboObject so nothing nasty happens when we chain later */
	x_object->base.servant      = NULL;
	x_object->base.corba_objref = CORBA_OBJECT_NIL;

	bonobo_running_context_remove_object (obj);

	ORBIT_ROOT_OBJECT_UNREF (obj);

	try_finalize (x_object);
}
====

IMHO this is already extremely ugly and hackish with GTK+ 1.x and just
wrong with GObject. With GObject, you cannot "block" the finalizing of an
object; this means, once the "finalize" method of a GObject is called,
this object _will_ go away after the finalizing handler returns.

So, no matter whether try_finalize() calls the parent classes finalize
handler or not, the object will go away after this function returns and there's
nothing you can do about this.

Second problem:

====
static void
corba_release (gpointer obj, CORBA_Environment *ev)
{
	BonoboXObject *object = BONOBO_X_CORBA_GET_OBJECT (obj);

	ORBIT_ROOT_OBJECT_UNREF (obj);

	if (ORBIT_ROOT_OBJECT (obj)->refs <= 0)
		try_finalize (object);
}
====

Again, it looks very ugly and hackish to me to jump into a "finalize" handler
from the outside, even in GTK+ 1.x. In GObject, this is simply wrong and does
not what you expect; it may even crash.

I tried to work around this and ended up with this code:

====
static void
try_finalize (BonoboXObject *object)
{
	CORBA_Object obj = BONOBO_X_OBJECT_GET_CORBA (object);

#ifdef BONOBO_X_OBJECT_DEBUG
	g_warning ("Try finalize '%p' : %d %d on", object,
		   ORBIT_ROOT_OBJECT (obj)->refs,
		   bonobo_object_get_refs ((BonoboObject *) object));
#endif

	if (ORBIT_ROOT_OBJECT (obj)->refs <= 0) {
		if (bonobo_object_get_refs ((BonoboObject *) object) <= 0) {

			corba_cleanup (object);
			g_object_unref (object);
#ifdef BONOBO_X_OBJECT_DEBUG
			g_warning ("Finalized '%p'", object);
#endif
		} else
			g_warning ("Reference counting error: "
				   "Attempts to release CORBA_Object associated with "
				   "'%s' which still has a reference count of %d",
				   G_OBJECT_TYPE_NAME (object),
				   bonobo_object_get_refs (BONOBO_OBJECT (object)));
	} else {
#ifdef BONOBO_X_OBJECT_DEBUG
		g_warning ("Not finalizing '%p'", object);
#endif
	}
}

static void
bonobo_x_object_shutdown_real (GObject *object)
{
	BonoboXObject *x_object;
	CORBA_Object   obj;
	
	x_object = BONOBO_X_OBJECT (object);
	obj = BONOBO_X_OBJECT_GET_CORBA (x_object);

#ifdef BONOBO_X_OBJECT_DEBUG
	g_message (G_STRLOC ": %p - %s - %d ; %p - %d", object,
		   G_OBJECT_TYPE_NAME (object), G_OBJECT (object)->ref_count,
		   obj, ORBIT_ROOT_OBJECT (obj)->refs);
#endif

	/* Setup the BonoboObject so nothing nasty happens when we chain later */
	x_object->base.servant      = NULL;
	x_object->base.corba_objref = CORBA_OBJECT_NIL;

	if (object->ref_count > 1) {
		/* We're called from bonobo_object_destroy(). */
		bonobo_running_context_remove_object (obj);

		ORBIT_ROOT_OBJECT_UNREF (obj);
	} else {
		g_object_ref (object);
		try_finalize (x_object);
	}

#ifdef BONOBO_X_OBJECT_DEBUG
	g_message (G_STRLOC ": %p - %d", object, object->ref_count);
#endif
}

/* cf. orbit_object.c (CORBA_Object_release_fn) */
static void
corba_release (gpointer obj, CORBA_Environment *ev)
{
	BonoboXObject *object = BONOBO_X_CORBA_GET_OBJECT (obj);

	ORBIT_ROOT_OBJECT_UNREF (obj);

#ifdef BONOBO_X_OBJECT_DEBUG
	g_message (G_STRLOC ": %p - %s - %d ; %p - %d", object,
		   G_OBJECT_TYPE_NAME (object), G_OBJECT (object)->ref_count,
		   obj, ORBIT_ROOT_OBJECT (obj)->refs);
#endif

	if (ORBIT_ROOT_OBJECT (obj)->refs <= 0)
		g_object_unref (object);
}
====

This is still not very nice, but it seems to work.

Better ideas are very welcome, I'm still a bit confused how this whole
refcounting stuff in Bonobo works.

-- 
Martin Baulig
martin gnome org (private)
baulig suse de (work)




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]