? autom4te.cache
? stamp-h1
Index: bonobo/bonobo-object.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-object.c,v
retrieving revision 1.146
diff -u -p -r1.146 bonobo-object.c
--- bonobo/bonobo-object.c	28 Oct 2002 14:37:53 -0000	1.146
+++ bonobo/bonobo-object.c	4 Apr 2003 13:48:08 -0000
@@ -9,6 +9,7 @@
  * Copyright 1999,2001 Ximian, Inc.
  */
 
+#define BONOBO_PRIVATE
 #include <config.h>
 #include <stdio.h>
 #include <string.h>
@@ -40,13 +41,23 @@ typedef struct {
 	int         line;
 } BonoboDebugRefData;
 
+/* invariant: objref == CORBA_OBJECT_NIL OR (exclusive) object != NULL  */
+typedef struct {
+	CORBA_Object           objref;	/* "foreign" object */
+	GDestroyNotify         destroy_notify;
+	gpointer               user_data;
+	BonoboObject          *object;
+} BonoboAggregateItem;
+
+#define _aggregate_item_objref(ai) ((ai)->object? (ai)->object->corba_objref : (ai)->objref)
+
 typedef struct {
 	int      ref_count;
 	gboolean immortal;
 	GList   *objs;
 #ifdef G_ENABLE_DEBUG
 	/* the following is required for reference debugging */
-	GList   *refs;
+	GList   *refs;		/* list of BonoboAggregateItem */
 	int      destroyed;
 #endif /* G_ENABLE_DEBUG */
 } BonoboAggregateObject;
@@ -77,14 +88,19 @@ bonobo_object_destroy (BonoboAggregateOb
 	g_return_if_fail (ao->ref_count > 0);
 
 	for (l = ao->objs; l; l = l->next) {
-		GObject *o = l->data;
-
-		if (o->ref_count >= 1) {
-			g_object_ref (o);
-			g_signal_emit (o, bonobo_object_signals [DESTROY], 0);
-			g_object_unref (o);
+		BonoboAggregateItem *ai = l->data;
+		if (ai->object)
+		{
+			GObject *o = (GObject *) ai->object;
+		
+			if (o->ref_count >= 1) {
+				g_object_ref (o);
+				g_signal_emit (o, bonobo_object_signals [DESTROY], 0);
+				g_object_unref (o);
+			} else
+				g_warning ("Serious ref-counting error [%p]", o);
 		} else
-			g_warning ("Serious ref-counting error [%p]", o);
+			ai->destroy_notify (ai->user_data);
 	}
 #ifdef G_ENABLE_DEBUG
 	if(_bonobo_debug_flags & BONOBO_DEBUG_REFS) 
@@ -140,48 +156,53 @@ bonobo_object_finalize_internal (BonoboA
 	g_return_if_fail (ao->ref_count == 0);
 
 	for (l = ao->objs; l; l = l->next) {
-		GObject *o = G_OBJECT (l->data);
+		BonoboAggregateItem *ai = l->data;
+		if (ai->object)
+		{
+			GObject *o = (GObject *) ai->object;
 
-		if (!o)
-			g_error ("Serious bonobo object corruption");
-		else {
-			g_assert (BONOBO_OBJECT (o)->priv->ao != NULL);
-#ifdef G_ENABLE_DEBUG
-			if(_bonobo_debug_flags & BONOBO_DEBUG_REFS) {
-				g_assert (BONOBO_OBJECT (o)->priv->ao->destroyed);
-
-				bonobo_debug_print ("finalize", 
-						    "[%p] %-20s corba_objref=[%p]"
-						    " g_ref_count=%d", o,
-						    G_OBJECT_TYPE_NAME (o),
-						    BONOBO_OBJECT (o)->corba_objref,
-						    G_OBJECT (o)->ref_count);
-			}
+			if (!o)
+				g_error ("Serious bonobo object corruption");
+			else {
+				g_assert (BONOBO_OBJECT (o)->priv->ao != NULL);
+#ifdef G_ENABLE_DEBUG
+				if(_bonobo_debug_flags & BONOBO_DEBUG_REFS) {
+					g_assert (BONOBO_OBJECT (o)->priv->ao->destroyed);
+
+					bonobo_debug_print ("finalize", 
+							    "[%p] %-20s corba_objref=[%p]"
+							    " g_ref_count=%d", o,
+							    G_OBJECT_TYPE_NAME (o),
+							    BONOBO_OBJECT (o)->corba_objref,
+							    G_OBJECT (o)->ref_count);
+				}
 #endif /* G_ENABLE_DEBUG */
 
-			/*
-			 * Disconnect the GObject from the aggregate object
-			 * and unref it so that it is possibly finalized ---
-			 * other parts of glib may still have references to it.
-			 *
-			 * The GObject was already destroy()ed in
-			 * bonobo_object_destroy().
-			 */
-
-			BONOBO_OBJECT (o)->priv->ao = NULL;
-
-			bonobo_object_corba_deactivate (BONOBO_OBJECT (o));
-
-			g_object_unref (o);
-#ifdef G_ENABLE_DEBUG
-			if(_bonobo_debug_flags & BONOBO_DEBUG_LIFECYCLE)
-				bonobo_debug_print ("finalize",
-						    "Done finalize internal on %p",
-						    o);
+				/*
+				 * Disconnect the GObject from the aggregate object
+				 * and unref it so that it is possibly finalized ---
+				 * other parts of glib may still have references to it.
+				 *
+				 * The GObject was already destroy()ed in
+				 * bonobo_object_destroy().
+				 */
+
+				BONOBO_OBJECT (o)->priv->ao = NULL;
+
+				bonobo_object_corba_deactivate (BONOBO_OBJECT (o));
+
+				g_object_unref (o);
+#ifdef G_ENABLE_DEBUG
+				if(_bonobo_debug_flags & BONOBO_DEBUG_LIFECYCLE)
+					bonobo_debug_print ("finalize",
+							    "Done finalize internal on %p",
+							    o);
 #endif /* G_ENABLE_DEBUG */
-		}
+			}
+		} else
+			ai->destroy_notify (ai->user_data);
 	}
-
+	g_list_foreach (ao->objs, (GFunc) g_free, NULL);
 	g_list_free (ao->objs);
 	ao->objs = NULL;
 
@@ -553,33 +574,32 @@ impl_Bonobo_Unknown_unref (PortableServe
 		bonobo_object_unref (object);
 }
 
-/**
- * bonobo_object_query_local_interface:
- * @object: A #BonoboObject which is the aggregate of multiple objects.
- * @repo_id: The id of the interface being queried.
- *
- * Returns: A #BonoboObject for the requested interface.
- */
-BonoboObject *
-bonobo_object_query_local_interface (BonoboObject *object,
-				     const char   *repo_id)
+
+static void
+query_local_interface (BonoboObject  *object,
+		       const char    *repo_id,
+		       CORBA_Object  *out_foreign_object,
+		       BonoboObject **out_bonobo_object)
 {
 	GList             *l;
-	CORBA_Object       corba_retval = CORBA_OBJECT_NIL;
+/* 	CORBA_Object       corba_retval = CORBA_OBJECT_NIL; */
 	CORBA_Environment  ev;
 
-	g_return_val_if_fail (BONOBO_IS_OBJECT (object), NULL);
+	*out_foreign_object = CORBA_OBJECT_NIL;
+	*out_bonobo_object = NULL;
 
-	corba_retval = CORBA_OBJECT_NIL;
+	g_return_if_fail (BONOBO_IS_OBJECT (object));
+
+/* 	corba_retval = CORBA_OBJECT_NIL; */
 
 	CORBA_exception_init (&ev);
 
 	for (l = object->priv->ao->objs; l; l = l->next){
-		BonoboObject *tryme = l->data;
-
-		if (CORBA_Object_is_a (
-			tryme->corba_objref, (char *) repo_id, &ev)) {
+		BonoboAggregateItem *ai = l->data;
+		CORBA_Object tryme = _aggregate_item_objref(ai);
 
+		if (CORBA_Object_is_a (tryme, (char *) repo_id, &ev)) {
+			
 			if (BONOBO_EX (&ev)) {
 				CORBA_exception_free (&ev);
 				continue;
@@ -587,25 +607,44 @@ bonobo_object_query_local_interface (Bon
 			
 			bonobo_object_ref (object);
 
-			return tryme;
+			*out_foreign_object = ai->objref;
+			*out_bonobo_object = ai->object;
+			return;
 		}
 	}
 
 	CORBA_exception_free (&ev);
+}
 
-	return NULL;
+/**
+ * bonobo_object_query_local_interface:
+ * @object: A #BonoboObject which is the aggregate of multiple objects.
+ * @repo_id: The id of the interface being queried.
+ *
+ * Returns: A #BonoboObject for the requested interface.
+ */
+BonoboObject *
+bonobo_object_query_local_interface (BonoboObject *object,
+				     const char   *repo_id)
+{
+	CORBA_Object  foreign_object = CORBA_OBJECT_NIL;
+	BonoboObject *bonobo_object = NULL;
+
+	query_local_interface (object, repo_id, &foreign_object, &bonobo_object);
+	return bonobo_object;
 }
 
+
 static CORBA_Object
 impl_Bonobo_Unknown_queryInterface (PortableServer_Servant  servant,
 				    const CORBA_char       *repoid,
 				    CORBA_Environment      *ev)
 {
 	BonoboObject *object = bonobo_object_from_servant (servant);
-	BonoboObject *local_interface;
+	CORBA_Object  foreign_interface = CORBA_OBJECT_NIL;
+	BonoboObject *local_interface = NULL;
 
-	local_interface = bonobo_object_query_local_interface (
-		object, repoid);
+	query_local_interface (object, repoid, &foreign_interface, &local_interface);
 
 #ifdef G_ENABLE_DEBUG
 	if(_bonobo_debug_flags & BONOBO_DEBUG_REFS) {
@@ -617,10 +656,13 @@ impl_Bonobo_Unknown_queryInterface (Port
 	}
 #endif /* G_ENABLE_DEBUG */
 
-	if (local_interface == NULL)
+	if (local_interface == NULL && foreign_interface == CORBA_OBJECT_NIL)
 		return CORBA_OBJECT_NIL;
 
-	return CORBA_Object_duplicate (local_interface->corba_objref, ev);
+	return CORBA_Object_duplicate (local_interface?
+				       local_interface->corba_objref :
+				       foreign_interface,
+				       ev);
 }
 
 static void
@@ -788,6 +830,7 @@ bonobo_object_instance_init (GObject    
 {
 	BonoboObject *object = BONOBO_OBJECT (g_object);
 	BonoboAggregateObject *ao;
+	BonoboAggregateItem   *ai;
 
 #ifdef G_ENABLE_DEBUG
 	if(_bonobo_debug_flags & BONOBO_DEBUG_OBJECT) {
@@ -806,7 +849,9 @@ bonobo_object_instance_init (GObject    
 
 	/* Setup aggregate */
 	ao            = g_new0 (BonoboAggregateObject, 1);
-	ao->objs      = g_list_append (ao->objs, object);
+	ai            = g_new0 (BonoboAggregateItem, 1);
+	ai->object    = object;
+	ao->objs      = g_list_append (ao->objs, ai);
 	ao->ref_count = 1;
 
 	/* Setup Private fields */
@@ -887,13 +932,18 @@ bonobo_ao_debug_foreach (gpointer key, g
 			    ao->ref_count, g_list_length (ao->objs));
 		
 	for (l = ao->objs; l; l = l->next) {
-		BonoboObject *object = BONOBO_OBJECT (l->data);
+		BonoboAggregateItem *ai = l->data;
+		if (ai->object)
+		{
+			BonoboObject *object = ai->object;
 		
-		bonobo_debug_print ("", "[%p] %-20s corba_objref=[%p]"
-				    " g_ref_count=%d", object,
-				    G_OBJECT_TYPE_NAME (object),
-				    object->corba_objref,
-				    G_OBJECT (object)->ref_count);
+			bonobo_debug_print ("", "[%p] %-20s corba_objref=[%p]"
+					    " g_ref_count=%d", object,
+					    G_OBJECT_TYPE_NAME (object),
+					    object->corba_objref,
+					    G_OBJECT (object)->ref_count);
+		} else
+			bonobo_debug_print ("", "(foreign object)");
 	}
 
 	l = g_list_last (ao->refs);
@@ -963,7 +1013,7 @@ void
 bonobo_object_add_interface (BonoboObject *object, BonoboObject *newobj)
 {
        BonoboAggregateObject *oldao, *ao;
-       GList *l;
+       GList *l; /* warning: this whole function block is mis-indented! */
 
        g_return_if_fail (object->priv->ao->ref_count > 0);
        g_return_if_fail (newobj->priv->ao->ref_count > 0);
@@ -1000,7 +1050,7 @@ bonobo_object_add_interface (BonoboObjec
 
        /* Merge the two AggregateObject lists */
        for (l = oldao->objs; l; l = l->next) {
-	       BonoboObject *new_if = l->data;
+	       BonoboAggregateItem *new_if = l->data;
 
 #ifdef G_ENABLE_DEBUG
 	       if(_bonobo_debug_flags & BONOBO_DEBUG_AGGREGATE) {
@@ -1009,11 +1059,11 @@ bonobo_object_add_interface (BonoboObjec
 		       CORBA_char *new_id;
 		       
 		       CORBA_exception_init (&ev);
-
-		       new_id = ORBit_small_get_type_id (new_if->corba_objref, &ev);
+		       
+		       new_id = ORBit_small_get_type_id (_aggregate_item_objref(new_if), &ev);
 
 		       for (i = ao->objs; i; i = i->next) {
-			       BonoboObject *old_if = i->data;
+			       BonoboAggregateItem *old_if = i->data;
 
 			       if (old_if == new_if)
 				       g_error ("attempting to merge identical "
@@ -1021,7 +1071,8 @@ bonobo_object_add_interface (BonoboObjec
 			       else {
 				       CORBA_char *old_id;
 				       
-				       old_id = ORBit_small_get_type_id (old_if->corba_objref, &ev);
+				       old_id = ORBit_small_get_type_id
+					       (_aggregate_item_objref(old_if), &ev);
 				       
 				       if (!strcmp (new_id, old_id))
 					       g_error ("Aggregating two BonoboObject that implement "
@@ -1036,7 +1087,8 @@ bonobo_object_add_interface (BonoboObjec
 #endif /* G_ENABLE_DEBUG */
 
 	       ao->objs = g_list_prepend (ao->objs, new_if);
-	       new_if->priv->ao = ao;
+	       if (new_if->object)
+		       new_if->object->priv->ao = ao;
        }
 
        g_assert (newobj->priv->ao == ao);
@@ -1058,6 +1110,33 @@ bonobo_object_add_interface (BonoboObjec
        LINC_MUTEX_UNLOCK (bonobo_total_aggregates_lock);
 }
 
+
+void
+bonobo_object_add_foreign_interface (BonoboObject          *object,
+				     CORBA_Object           objref,
+				     GDestroyNotify         destroy_notify,
+				     gpointer               user_data)
+{
+	BonoboAggregateObject *ao;
+	BonoboAggregateItem   *ai;
+
+	g_return_if_fail (object->priv->ao->ref_count > 0);
+
+	ao = object->priv->ao;
+	ai = g_new0 (BonoboAggregateItem, 1);
+	ao->objs = g_list_prepend (ao->objs, ai);
+
+	ai->objref           = objref;
+	ai->destroy_notify   = destroy_notify;
+	ai->user_data        = user_data;
+
+	/* Some simple debugging - count aggregate free */
+	LINC_MUTEX_LOCK   (bonobo_total_aggregates_lock);
+	bonobo_total_aggregates--;
+	LINC_MUTEX_UNLOCK (bonobo_total_aggregates_lock);
+}
+
+
 /**
  * bonobo_object_query_interface:
  * @object: A BonoboObject to be queried for a given interface.
@@ -1197,14 +1276,13 @@ bonobo_object_dump_interfaces (BonoboObj
 
 	fprintf (stderr, "references %d\n", ao->ref_count);
 	for (l = ao->objs; l; l = l->next) {
-		BonoboObject *o = l->data;
+		BonoboAggregateItem *ai = l->data;
 		
-		g_return_if_fail (BONOBO_IS_OBJECT (o));
-
-		if (o->corba_objref != CORBA_OBJECT_NIL) {
+		if (_aggregate_item_objref(ai) != CORBA_OBJECT_NIL) {
 			CORBA_char   *type_id;
 
-			type_id = ORBit_small_get_type_id (o->corba_objref, &ev);
+			type_id = ORBit_small_get_type_id
+				(_aggregate_item_objref(ai), &ev);
 			fprintf (stderr, "I/F: '%s'\n", type_id);
 			CORBA_free (type_id);
 		} else
Index: bonobo/bonobo-object.h
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-object.h,v
retrieving revision 1.86
diff -u -p -r1.86 bonobo-object.h
--- bonobo/bonobo-object.h	21 Jan 2003 10:54:29 -0000	1.86
+++ bonobo/bonobo-object.h	4 Apr 2003 13:48:08 -0000
@@ -86,6 +86,12 @@ typedef struct {
 GType                    bonobo_object_get_type               (void) G_GNUC_CONST;
 void                     bonobo_object_add_interface          (BonoboObject           *object,
 							       BonoboObject           *newobj);
+#ifdef BONOBO_PRIVATE
+void                     bonobo_object_add_foreign_interface  (BonoboObject           *object,
+							       CORBA_Object            objref,
+							       GDestroyNotify          destroy_notify,
+							       gpointer                user_data);
+#endif
 BonoboObject            *bonobo_object_query_local_interface  (BonoboObject           *object,
 							       const char             *repo_id);
 Bonobo_Unknown           bonobo_object_query_remote           (Bonobo_Unknown          unknown,
