investigation into replacing ref. counts with leases



Attached is a rough cut of some ideas for replacing ref. counts with leases. It's not completely implemented yet, but I wanted to talk with some others about this possibility for GNOME 2. If we don't do this, we're going to be stuck with the old "stale processes" problem. The fix I did for this in Nautilus 1.0 is quite unsatisfactory, and I'd hate to have to ship it with GNOME 2.

The overall approach is that we rarely transfer ownership of objects. Most calls that return objects do not return owning references. The new C convenience calls bonobo_retain and bonobo_release are used in places where we formerly did things like bonobo_object_dup_ref and bonobo_object_release_unref -- they arrange for the lease to be extended at regular intervals.

The problem I ran into is that extending the leases from client processes seems to require some kind of regular timer. The glib timeout is not satisfactory because it's tied to the event loop, and I'm not sure what I should use for the timer.

Overall, the model seems to be working out fairly nicely, but there are all sorts of issues. For one thing, making lease extension convenient bindings for languages other than C.

I've enclosed the *huge* patch to libbonobo that implements this. It may be hard to get the big picture from this patch, and I'm sure there are some mistakes in it, but I figured that sending the patch was better than just doing nothing.

Easiest for me would be just dropping the whole thing, but I think that without this we have big architectural trouble in Bonobo that makes it impractical for serious use.

Maybe there's some better solution to this problem. If I don't get any responses to this mail, I'll just drop the whole thing and hope that someone else fixes the problem.

Index: bonobo/bonobo-context.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-context.c,v
retrieving revision 1.7
diff -p -u -r1.7 bonobo-context.c
--- bonobo/bonobo-context.c	2001/02/20 19:42:01	1.7
+++ bonobo/bonobo-context.c	2001/07/18 17:42:49
@@ -37,7 +37,7 @@ bonobo_context_add (const CORBA_char *co

 	g_hash_table_insert (bonobo_contexts,
 			     g_strdup (context_name),
-			     bonobo_object_dup_ref (context, NULL));
+			     bonobo_retain (bonobo_contexts, context));
 }

 /**
@@ -59,7 +59,7 @@ bonobo_context_get (const CORBA_char  *c
 	g_return_val_if_fail (context_name != NULL, CORBA_OBJECT_NIL);

 	if ((ret = g_hash_table_lookup (bonobo_contexts, context_name)))
-		return bonobo_object_dup_ref (ret, opt_ev);
+		return ret;
 	else
 		return CORBA_OBJECT_NIL;
 }
@@ -75,8 +75,6 @@ context_add (BonoboObject *object, const

 	/* Don't count it as a running object; we always have it */
 	bonobo_running_context_ignore_object (ref);
-
-	bonobo_object_unref (object);
 }

 /**
@@ -97,7 +95,7 @@ static gboolean
 context_destroy (char *key, Bonobo_Unknown handle, gpointer dummy)
 {
 	g_free (key);
-	bonobo_object_release_unref (handle, NULL);
+	bonobo_release (bonobo_contexts, handle);
 	return TRUE;
 }

Index: bonobo/bonobo-event-source.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-event-source.c,v
retrieving revision 1.32
diff -p -u -r1.32 bonobo-event-source.c
--- bonobo/bonobo-event-source.c	2001/06/26 16:43:32	1.32
+++ bonobo/bonobo-event-source.c	2001/07/18 17:42:50
@@ -59,11 +59,11 @@ bonobo_event_source_from_servant (Portab
 }

 static void
-desc_free (ListenerDesc *desc, CORBA_Environment *ev)
+desc_free (BonoboEventSource *source, ListenerDesc *desc)
 {
 	if (desc) {
 		g_strfreev (desc->event_masks);
-		bonobo_object_release_unref (desc->listener, ev);
+		bonobo_release (source, desc->listener);
 		g_free (desc);
 	}
 }
@@ -85,7 +85,7 @@ impl_Bonobo_EventSource_addListenerWithM
 		bonobo_running_context_ignore_object (l);

 	desc = g_new0 (ListenerDesc, 1);
-	desc->listener = bonobo_object_dup_ref (l, ev);
+ desc->listener = bonobo_retain_while_alive (G_OBJECT (event_source), l);
 	desc->id = create_listener_id (event_source);

 	if (event_mask)
@@ -121,7 +121,7 @@ impl_Bonobo_EventSource_removeListener (
 			event_source->priv->listeners =
 				g_slist_remove (event_source->priv->listeners,
 						desc);
-			desc_free (desc, ev);
+			desc_free (event_source, desc);
 			return;
 		}
 	}
@@ -199,13 +199,9 @@ bonobo_event_source_notify_listeners (Bo
 			notify = g_slist_prepend (notify, desc->listener);
 	}

-	bonobo_object_ref (BONOBO_OBJECT (event_source));
-
 	for (l = notify; l; l = l->next)
 		Bonobo_Listener_event (l->data, event_name, value, my_ev);

-	bonobo_object_unref (BONOBO_OBJECT (event_source));
-
 	g_slist_free (notify);

 	if (!opt_ev)
@@ -233,24 +229,19 @@ bonobo_event_source_notify_listeners_ful
 static void
 bonobo_event_source_finalize (GObject *object)
 {
-	CORBA_Environment         ev;
 	BonoboEventSourcePrivate *priv;
 	
 	priv = BONOBO_EVENT_SOURCE (object)->priv;

-	CORBA_exception_init (&ev);
-	
 	while (priv->listeners) {
 		ListenerDesc *d = priv->listeners->data;

 		priv->listeners = g_slist_remove (
 			priv->listeners, d);

-		desc_free (d, &ev);
+		desc_free (BONOBO_EVENT_SOURCE (object), d);
 	}

-	CORBA_exception_free (&ev);
-
 	g_free (priv);

 	bonobo_event_source_parent_class->finalize (object);
@@ -341,10 +332,7 @@ bonobo_event_source_client_remove_listen
 	        "IDL:Bonobo/EventSource:1.0", my_ev);

 	if (!BONOBO_EX (my_ev) && es) {
-
 		Bonobo_EventSource_removeListener (es, id, my_ev);
-
-		Bonobo_Unknown_unref (es, my_ev);
 	}

 	if (!opt_ev) {
@@ -394,9 +382,6 @@ bonobo_event_source_client_add_listener
 	else
 		id = Bonobo_EventSource_addListener (es, corba_listener,
 						     my_ev);
-
-	bonobo_object_unref (BONOBO_OBJECT (listener));
-	Bonobo_Unknown_unref (es, my_ev);

  add_listener_end:

Index: bonobo/bonobo-item-container.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-item-container.c,v
retrieving revision 1.56
diff -p -u -r1.56 bonobo-item-container.c
--- bonobo/bonobo-item-container.c	2001/07/02 12:50:29	1.56
+++ bonobo/bonobo-item-container.c	2001/07/18 17:42:50
@@ -45,7 +45,7 @@ remove_object (gpointer key,
 	       gpointer user_data)
 {
 	g_free (key);
-	bonobo_object_unref (value);
+	bonobo_release (user_data, value);

 	return TRUE;
 }
@@ -57,7 +57,7 @@ bonobo_item_container_finalize (GObject

 	/* Destroy all the ClientSites. */
 	g_hash_table_foreach_remove (container->priv->objects,
-				     remove_object, NULL);
+				     remove_object, container);

 	g_hash_table_destroy (container->priv->objects);
 	g_free (container->priv);
@@ -217,10 +217,9 @@ bonobo_item_container_add (BonoboItemCon
 	if (g_hash_table_lookup (container->priv->objects, name)) {
 		g_warning ("Object of name '%s' already exists", name);
 	} else {
-		bonobo_object_ref (object);
 		g_hash_table_insert (container->priv->objects,
 				     g_strdup (name),
-				     object);
+				     bonobo_retain_while_alive (G_OBJECT (container), object));
 	}
 }

@@ -245,7 +244,7 @@ bonobo_item_container_remove_by_name (Bo
 		g_warning ("Removing '%s' but not in container", name);
 	else {
 		g_free (key);
-		bonobo_object_unref (value);
+		bonobo_release (container, value);
 		g_hash_table_remove (container->priv->objects, name);
 	}
 }
Index: bonobo/bonobo-listener.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-listener.c,v
retrieving revision 1.22
diff -p -u -r1.22 bonobo-listener.c
--- bonobo/bonobo-listener.c	2001/07/07 14:10:48	1.22
+++ bonobo/bonobo-listener.c	2001/07/18 17:42:50
@@ -40,7 +40,6 @@ impl_Bonobo_Listener_event (PortableServ

 	listener = BONOBO_LISTENER (bonobo_object_from_servant (servant));

-	bonobo_object_ref (BONOBO_OBJECT (listener));
 	if (listener->priv->event_callback)
 		listener->priv->event_callback (
 			listener, (CORBA_char *) event_name,
@@ -50,7 +49,6 @@ impl_Bonobo_Listener_event (PortableServ
 	g_signal_emit (G_OBJECT (listener),
 		       signals [EVENT_NOTIFY], 0,
 		       event_name, args, ev);
-	bonobo_object_unref (BONOBO_OBJECT (listener));
 }

 static void
Index: bonobo/bonobo-main.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-main.c,v
retrieving revision 1.47
diff -p -u -r1.47 bonobo-main.c
--- bonobo/bonobo-main.c	2001/06/30 19:53:30	1.47
+++ bonobo/bonobo-main.c	2001/07/18 17:42:51
@@ -256,8 +256,6 @@ bonobo_init_full (int *argc, char **argv

 	CORBA_exception_free (&ev);

-	bonobo_object_init ();
-
 	bonobo_context_init ();

 	bindtextdomain (PACKAGE, BONOBO_LOCALEDIR);
Index: bonobo/bonobo-moniker-extender.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-moniker-extender.c,v
retrieving revision 1.9
diff -p -u -r1.9 bonobo-moniker-extender.c
--- bonobo/bonobo-moniker-extender.c	2001/04/18 22:09:06	1.9
+++ bonobo/bonobo-moniker-extender.c	2001/07/18 17:42:52
@@ -187,7 +187,5 @@ bonobo_moniker_use_extender (const gchar
 		bonobo_moniker_get_name_full (moniker),
 		requested_interface, ev);

-	bonobo_object_release_unref (extender, ev);
-
 	return retval;
 }
Index: bonobo/bonobo-moniker-util.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-moniker-util.c,v
retrieving revision 1.38
diff -p -u -r1.38 bonobo-moniker-util.c
--- bonobo/bonobo-moniker-util.c	2001/06/26 16:43:32	1.38
+++ bonobo/bonobo-moniker-util.c	2001/07/18 17:42:53
@@ -143,7 +143,7 @@ bonobo_moniker_util_new_from_name_full (
 	g_return_val_if_fail (name != NULL, NULL);

 	if (!name [0])
-		return bonobo_object_dup_ref (parent, ev);
+		return parent;

 	if (name [0] == '#')
 		name++;
@@ -177,15 +177,18 @@ bonobo_moniker_util_new_from_name_full (
 		}
 	}

+	bonobo_retain (&object, object);
+
 	toplevel = Bonobo_Unknown_queryInterface (
 		object, "IDL:Bonobo/Moniker:1.0", ev);

 	if (BONOBO_EX (ev)) {
-		bonobo_object_release_unref (object, ev);
+		bonobo_release (NULL, object);
 		return CORBA_OBJECT_NIL;
 	}

-	bonobo_object_release_unref (object, ev);
+	bonobo_retain (&toplevel, toplevel);
+	bonobo_release (&object, object);

 	if (toplevel == CORBA_OBJECT_NIL) {
 		g_warning ("Moniker object '%s' doesn't implement "
@@ -198,7 +201,7 @@ bonobo_moniker_util_new_from_name_full (
 	if (BONOBO_EX (ev))
 		return CORBA_OBJECT_NIL;

-	bonobo_object_release_unref (toplevel, ev);
+	bonobo_release (&toplevel, toplevel);

 	if (BONOBO_EX (ev))
 		return CORBA_OBJECT_NIL;
@@ -237,8 +240,6 @@ bonobo_moniker_util_get_parent_name (Bon
 	if (BONOBO_EX (ev))
 		name = NULL;

-	bonobo_object_release_unref (parent, ev);
-
 	return name;
 }

@@ -275,21 +276,14 @@ bonobo_moniker_util_qi_return (Bonobo_Un
 		object, requested_interface, ev);

 	if (BONOBO_EX (ev))
-		goto release_unref_object;
-	
+		return CORBA_OBJECT_NIL;
+
 	if (retval == CORBA_OBJECT_NIL) {
 		CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
 				     ex_Bonobo_Moniker_InterfaceNotFound, NULL);
-		goto release_unref_object;
 	}

- release_unref_object:	
-	bonobo_object_release_unref (object, ev);
-
-	if (retval != CORBA_OBJECT_NIL)
-		return CORBA_Object_duplicate (retval, ev);
-	else
-		return CORBA_OBJECT_NIL;
+	return retval;
 }

 /**
@@ -541,11 +535,11 @@ bonobo_get_object (const CORBA_char *nam
 	if (BONOBO_EX (ev))
 		return CORBA_OBJECT_NIL;

+	bonobo_retain (&moniker, moniker);
 	retval = bonobo_moniker_client_resolve_default (
 		moniker, interface_name, ev);
+	bonobo_release (&moniker, moniker);

-	bonobo_object_release_unref (moniker, ev);
-
 	if (BONOBO_EX (ev))
 		return CORBA_OBJECT_NIL;
 	
@@ -589,7 +583,7 @@ async_parse_cb (BonoboAsyncReply  *reply
 		ctx->cb (retval, ev, ctx->user_data);
 	}

-	bonobo_object_release_unref (ctx->moniker, ev);
+	bonobo_release (ctx, ctx->moniker);
 	parse_async_ctx_free (ctx);
 }

@@ -651,8 +645,6 @@ async_activation_cb (CORBA_Object activa
 				ctx->cb (CORBA_OBJECT_NIL, &ev, ctx->user_data);
 				parse_async_ctx_free (ctx);
 			}
-
-			bonobo_object_release_unref (activated_object, &ev);
 		}
 	}

@@ -733,7 +725,7 @@ resolve_async_cb (BonoboAsyncReply  *han
 		ctx->cb (object, ev, ctx->user_data);
 	}

-	bonobo_object_release_unref (ctx->moniker, ev);
+	bonobo_release (ctx, moniker);
 	g_free (ctx);
 }

@@ -786,7 +778,7 @@ bonobo_moniker_resolve_async (Bonobo_Mon
 	ctx = g_new0 (resolve_async_ctx_t, 1);
 	ctx->cb = cb;
 	ctx->user_data = user_data;
-	ctx->moniker = bonobo_object_dup_ref (moniker, ev);
+	ctx->moniker = bonobo_retain (ctx, moniker);

 	bonobo_async_invoke (&method, resolve_async_cb, ctx,
 			     timeout_msec, ctx->moniker, arg_values, ev);
Index: bonobo/bonobo-moniker.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-moniker.c,v
retrieving revision 1.51
diff -p -u -r1.51 bonobo-moniker.c
--- bonobo/bonobo-moniker.c	2001/07/11 14:32:34	1.51
+++ bonobo/bonobo-moniker.c	2001/07/18 17:42:53
@@ -73,8 +73,9 @@ bonobo_moniker_set_parent (BonoboMoniker
 {
 	g_return_if_fail (BONOBO_IS_MONIKER (moniker));
 	
-	bonobo_object_release_unref (moniker->priv->parent, ev);
-	moniker->priv->parent = bonobo_object_dup_ref (parent, ev);
+	parent = bonobo_retain_while_alive (G_OBJECT (moniker), parent);
+	bonobo_release (moniker, moniker->priv->parent);
+	moniker->priv->parent = parent;
 }

 /**
@@ -96,7 +97,7 @@ bonobo_moniker_get_parent (BonoboMoniker
 	if (moniker->priv->parent == CORBA_OBJECT_NIL)
 		return CORBA_OBJECT_NIL;
 	
-	return bonobo_object_dup_ref (moniker->priv->parent, ev);
+	return moniker->priv->parent;
 }

 /**
@@ -357,12 +358,14 @@ impl_resolve (PortableServer_Servant
 			return CORBA_OBJECT_NIL;

 		else if (extender != CORBA_OBJECT_NIL) {
+			bonobo_retain (moniker, extender);
+
 			retval = Bonobo_MonikerExtender_resolve (
 				extender, BONOBO_OBJREF (moniker),
 				options, moniker->priv->name,
 				requested_interface, ev);

-			bonobo_object_release_unref (extender, ev);
+			bonobo_release (moniker, extender);
 		}
 	}

@@ -388,10 +391,8 @@ static void
 bonobo_moniker_finalize (GObject *object)
 {
 	BonoboMoniker *moniker = BONOBO_MONIKER (object);
-
-	if (moniker->priv->parent != CORBA_OBJECT_NIL)
-		bonobo_object_release_unref (moniker->priv->parent, NULL);

+	bonobo_release (object, moniker->priv->parent);
 	g_free (moniker->priv->prefix);
 	g_free (moniker->priv->name);
 	g_free (moniker->priv);
Index: bonobo/bonobo-object.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-object.c,v
retrieving revision 1.113
diff -p -u -r1.113 bonobo-object.c
--- bonobo/bonobo-object.c	2001/07/16 23:42:23	1.113
+++ bonobo/bonobo-object.c	2001/07/18 17:42:55
@@ -27,37 +27,74 @@
 #include "bonobo-object-directory.h"
 #include "bonobo-marshal.h"

-#ifdef BONOBO_OBJECT_DEBUG
-#	define BONOBO_REF_HOOKS
-#endif
+/* How often should we extend all the leases that we hold? */
+#define BONOBO_LEASE_HEARTBEAT_INTERVAL 100

-/* NB. for a quicker debugging experience define this */
-/* # define BONOBO_REF_HOOKS */
+/*
+ * How much slower should we be to decide that a lease is dead? This
+ * must be set to at least 2 to give lease holders enough time to
+ * extend their leases.
+ */
+#define BONOBO_LEASE_TIME_TO_LIVE 10

-/* You almost certainly don't want this */
-#undef BONOBO_LIFECYCLE_DEBUG
+/*
+ * This makes sure we always pass out unique lease IDs. Since objects
+ * can be combined, we prefer to have lease IDs that are globally
+ * unique.
+ */
+static Bonobo_Unknown_LeaseID last_used_lease_id;

-#ifdef BONOBO_REF_HOOKS
-typedef struct {
-	const char *fn;
-	gboolean    ref;
-	int         line;
-} BonoboDebugRefData;
-#endif
+/*
+ * This is a list of all the aggregate objects that currently exist.
+ * It's used to age the leases on the server side at regular
+ * intervals.
+ */
+static GList *aggregate_objects;

-typedef struct {
-	int   ref_count;
-	GList *objs;
-#ifdef BONOBO_REF_HOOKS
-	GList *refs;
-	int    destroyed;
-#endif
-} BonoboAggregateObject;
+/*
+ * This hash table maps from CORBA object references to
+ * ownership lists. It's used on the client side to keep track
+ * of leases we hold and extend the leases at regular intervals.
+ */
+static GHashTable *owned_objects;

+/*
+ * Since the only thing we need in private storage is the
+ * aggregate object, we use the "priv" pointer as a pointer
+ * to the aggregate object to save storage. If we ever need
+ * something else private per-object, we can change priv to
+ * be a separate structure with a pointer to the ao.
+ */
 struct _BonoboObjectPrivate {
-	BonoboAggregateObject *ao;
+	GList *objs;
+	GList *leases;
 };
+typedef BonoboObjectPrivate BonoboAggregateObject;
+
+/* Entries in the aggregate object leases list (server side). */
+typedef struct {
+	Bonobo_Unknown_LeaseID id;
+	int age;
+} BonoboLease;

+/* Entries in the owned_objects hash table. */
+typedef struct {
+	Bonobo_Unknown_LeaseID id;
+	GList *owners;
+} BonoboHeldLease;
+
+/* Entries in the owners list within the hash table. */
+typedef struct {
+	gpointer owner;
+	gboolean while_alive;
+	Bonobo_Unknown owned_object;
+} BonoboOwnerListEntry;
+
+typedef struct {
+	gpointer owner;
+	Bonobo_Unknown owned_object;
+} BonoboReleaseArgs;
+
 enum {
 	DESTROY,
 	QUERY_INTERFACE,
@@ -68,32 +105,92 @@ enum {
 static guint bonobo_object_signals [LAST_SIGNAL];
 static GObjectClass *bonobo_object_parent_class;

-#ifdef BONOBO_REF_HOOKS
+static void owner_gone_callback (gpointer data);
+
+static CORBA_Object
+bonobo_objref_duplicate (CORBA_Object object)
+{
+	CORBA_Environment ev;
+	CORBA_Object duplicate;

-static GHashTable *living_ao_ht = NULL;
+	CORBA_exception_init (&ev);
+	duplicate = CORBA_Object_duplicate (object, &ev);
+	g_assert (!BONOBO_EX (&ev));
+	CORBA_exception_free (&ev);
+
+	return duplicate;
+}

 static void
-bonobo_debug_print (char *name, char *fmt, ...)
+bonobo_objref_release (CORBA_Object object)
 {
-	va_list args;
-
-	va_start (args, fmt);
-	
-	printf ("[%06d]:%-15s ", getpid (), name);
-	vprintf (fmt, args);
-	printf ("\n");
+	CORBA_Environment ev;
+
+	CORBA_exception_init (&ev);
+	CORBA_Object_release (object, &ev);
+	g_assert (!BONOBO_EX (&ev));
+	CORBA_exception_free (&ev);
+}
+
+static gboolean
+bonobo_objref_equal (CORBA_Object a, CORBA_Object b)
+{
+	CORBA_Environment ev;
+	gboolean equal;
+
+	CORBA_exception_init (&ev);
+	equal = CORBA_Object_is_equivalent (a, b, &ev);
+	if (BONOBO_EX (&ev)) {
+ g_warning ("unable to compare CORBA object references %p and %p", a, b);
+		equal = FALSE;
+	}
+	CORBA_exception_free (&ev);

-	va_end (args);
+	return FALSE;
 }
-#endif /* BONOBO_REF_HOOKS */
+
+static guint
+bonobo_objref_hash (CORBA_Object object)
+{
+	CORBA_Environment ev;
+	guint hash;

-/* Do not use this function, it is not what you want; see unref */
+	CORBA_exception_init (&ev);
+	hash = CORBA_Object_hash (object, 0, &ev);
+	if (BONOBO_EX (&ev)) {
+		g_warning ("unable to hash CORBA object reference %p", object);
+		hash = 0;
+	}
+	CORBA_exception_free (&ev);
+
+	return hash;
+}
+
 static void
+bonobo_objref_release_cover (gpointer data)
+{
+	bonobo_objref_release (data);
+}
+
+static gboolean
+bonobo_objref_equal_cover (gconstpointer a, gconstpointer b)
+{
+	return bonobo_objref_equal ((CORBA_Object) a, (CORBA_Object) b);
+}
+
+static guint
+bonobo_objref_hash_cover (gconstpointer data)
+{
+	return bonobo_objref_hash ((CORBA_Object) data);
+}
+
+/* Do not use this function, it is not what you want; see destroy_lease *
/
+static void
 bonobo_object_destroy (BonoboAggregateObject *ao)
 {
 	GList *l;

-	g_return_if_fail (ao->ref_count > 0);
+	g_return_if_fail (ao->leases != NULL);

 	for (l = ao->objs; l; l = l->next) {
 		GObject *o = l->data;
@@ -120,13 +217,13 @@ bonobo_object_corba_deactivate (BonoboOb
 	g_warning ("BonoboObject corba deactivate %p", object);
 #endif

-	g_assert (object->priv->ao == NULL);
+	g_assert (object->priv == NULL);

 	CORBA_exception_init (&ev);

 	if (object->corba_objref != CORBA_OBJECT_NIL) {
 		bonobo_running_context_remove_object (object->corba_objref);
-		CORBA_Object_release (object->corba_objref, &ev);
+		bonobo_objref_release (object->corba_objref);
 		object->corba_objref = CORBA_OBJECT_NIL;
 	}

@@ -150,6 +247,14 @@ bonobo_object_corba_deactivate (BonoboOb
 	CORBA_exception_free (&ev);
 }

+static void
+bonobo_aggregate_object_free (BonoboAggregateObject *ao)
+{
+	g_list_free (ao->objs);
+	aggregate_objects = g_list_remove (aggregate_objects, ao);
+	g_free (ao);
+}
+
 /*
  * bonobo_object_finalize_internal:
  *
@@ -165,7 +270,7 @@ bonobo_object_finalize_internal (BonoboA
 {
 	GList *l;

-	g_return_if_fail (ao->ref_count == 0);
+	g_return_if_fail (ao->leases == NULL);

 	for (l = ao->objs; l; l = l->next) {
 		GObject *o = G_OBJECT (l->data);
@@ -173,18 +278,8 @@ bonobo_object_finalize_internal (BonoboA
 		if (!o)
 			g_error ("Serious bonobo object corruption");
 		else {
-			g_assert (BONOBO_OBJECT (o)->priv->ao != NULL);
-#ifdef BONOBO_REF_HOOKS
-			g_assert (BONOBO_OBJECT (o)->priv->ao->destroyed);
+			g_assert (BONOBO_OBJECT (o)->priv != NULL);

-			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
-
 			/*
 			 * Disconnect the GTK+ object from the aggregate object
 			 * and unref it so that it is possibly finalized ---
@@ -194,7 +289,7 @@ bonobo_object_finalize_internal (BonoboA
 			 * bonobo_object_destroy().
 			 */

-			BONOBO_OBJECT (o)->priv->ao = NULL;
+			BONOBO_OBJECT (o)->priv = NULL;

 			bonobo_object_corba_deactivate (BONOBO_OBJECT (o));

@@ -205,16 +300,7 @@ bonobo_object_finalize_internal (BonoboA
 		}
 	}

-	g_list_free (ao->objs);
-	ao->objs = NULL;
-
-#ifdef BONOBO_REF_HOOKS
-	for (l = ao->refs; l; l = l->next)
-		g_free (l->data);
-	g_list_free (ao->refs);
-#endif
-
-	g_free (ao);
+	bonobo_aggregate_object_free (ao);
 }


@@ -243,229 +329,88 @@ bonobo_object_finalize_servant (Portable
 	g_object_unref (G_OBJECT (object));
 }

-#ifndef bonobo_object_ref
-/**
- * bonobo_object_ref:
- * @object: A BonoboObject you want to ref-count
- *
- * Increments the reference count for the aggregate BonoboObject.
- */
-void
-bonobo_object_ref (BonoboObject *object)
+static Bonobo_Unknown_LeaseID
+impl_Bonobo_Unknown_createLease (PortableServer_Servant servant,
+				 CORBA_Environment *ev)
 {
-	g_return_if_fail (BONOBO_IS_OBJECT (object));
-	g_return_if_fail (object->priv->ao->ref_count > 0);
+	BonoboObject *object;
+	BonoboAggregateObject *ao;
+	BonoboLease *lease;

-#ifdef BONOBO_REF_HOOKS
-	bonobo_object_trace_refs (object, "local", 0, TRUE);
-#else
-	object->priv->ao->ref_count++;
-#endif
+	object = bonobo_object_from_servant (servant);
+	ao = object->priv;
+	lease = g_new0 (BonoboLease, 1);
+	lease->id = ++last_used_lease_id;
+	ao->leases = g_list_prepend (ao->leases, lease);
+	return lease->id;
+}
+
+static GList *
+bonobo_object_find_lease (BonoboAggregateObject *ao, Bonobo_Unknown_LeaseID id)
+{
+	GList *node;
+	BonoboLease *lease;
+
+	for (node = ao->leases; node != NULL; node = node->next) {
+		lease = node->data;
+		if (lease->id == id)
+			break;
+	}
+	return node;
 }
-#endif /* bonobo_object_ref */
-

-#ifndef bonobo_object_unref
-/**
- * bonobo_object_unref:
- * @object: A BonoboObject you want to unref.
- *
- * Decrements the reference count for the aggregate BonoboObject.
- */
-void
-bonobo_object_unref (BonoboObject *object)
+static void
+bonobo_object_remove_lease (BonoboAggregateObject *ao, GList *node)
 {
-#ifdef BONOBO_REF_HOOKS
-	bonobo_object_trace_refs (object, "local", 0, FALSE);
-#else
-	BonoboAggregateObject *ao;
+	ao->leases = g_list_remove_link (ao->leases, node);
+	g_free (node->data);
+	g_list_free_1 (node);

-	g_return_if_fail (BONOBO_IS_OBJECT (object));
-
-	ao = object->priv->ao;
-	g_return_if_fail (ao != NULL);
-	g_return_if_fail (ao->ref_count > 0);
-
-	if (ao->ref_count == 1)
+	if (ao->leases == NULL)
 		bonobo_object_destroy (ao);
-
-	ao->ref_count--;

-	if (ao->ref_count == 0)
+	if (ao->leases == NULL)
 		bonobo_object_finalize_internal (ao);
-#endif /* BONOBO_REF_HOOKS */
 }
-#endif /* bonobo_object_unref */
-
-void
-bonobo_object_trace_refs (BonoboObject *object,
-			  const char   *fn,
-			  int           line,
-			  gboolean      ref)
-{
-#ifdef BONOBO_REF_HOOKS
-	BonoboAggregateObject *ao;
-	BonoboDebugRefData *descr;
-	
-	g_return_if_fail (BONOBO_IS_OBJECT (object));
-	ao = object->priv->ao;
-	g_return_if_fail (ao != NULL);
-
-	descr  = g_new (BonoboDebugRefData, 1);
-	ao->refs = g_list_prepend (ao->refs, descr);
-	descr->fn = fn;
-	descr->ref = ref;
-	descr->line = line;

-	if (ref) {
-		g_return_if_fail (ao->ref_count > 0);
-		
-		object->priv->ao->ref_count++;
-		
-		bonobo_debug_print ("ref", "[%p]:[%p]:%s to %d at %s:%d",
-			object, ao,
-		        G_OBJECT_TYPE_NAME (object),
-			ao->ref_count, fn, line);
-
-	} else { /* unref */
-		bonobo_debug_print ("unref", "[%p]:[%p]:%s from %d at %s:%d",
-			object, ao,
-			G_OBJECT_TYPE_NAME (object),
-			ao->ref_count, fn, line);
-
-		g_return_if_fail (ao->ref_count > 0);
-
-		if (ao->ref_count == 1) {
-			bonobo_object_destroy (ao);
-
-			g_return_if_fail (ao->ref_count > 0);
-		}
-
-		/*
-		 * If this blows it is likely some loony used
-		 * g_object_unref somewhere instead of
-		 * bonobo_object_unref, send them my regards.
-		 */
-		g_assert (object->priv->ao == ao);
-		
-		ao->ref_count--;
-	
-		if (ao->ref_count == 0) {
-
-			g_assert (g_hash_table_lookup (living_ao_ht, ao) == ao);
-			g_hash_table_remove (living_ao_ht, ao);
-			
-			bonobo_object_finalize_internal (ao);
-		} else if (ao->ref_count < 0) {
-			bonobo_debug_print ("unusual",
-					    "[%p] already finalized", ao);
-		}
-	}
-#else
-	if (ref)
-		bonobo_object_ref (object);
-	else
-		bonobo_object_unref (object);
-#endif
-}
-
 static void
-impl_Bonobo_Unknown_ref (PortableServer_Servant servant, CORBA_Environment *ev)
+impl_Bonobo_Unknown_destroyLease (PortableServer_Servant servant,
+				  Bonobo_Unknown_LeaseID id,
+				  CORBA_Environment *ev)
 {
 	BonoboObject *object;
+	BonoboAggregateObject *ao;
+	GList *node;

 	object = bonobo_object_from_servant (servant);
-
-#if defined(BONOBO_REF_HOOKS) && !defined(bonobo_object_ref)
-	bonobo_object_trace_refs (object, "remote", 0, TRUE);
-#else
-	bonobo_object_ref (object);
-#endif
-}
-
-/**
- * bonobo_object_dup_ref:
- * @object: a Bonobo_Unknown corba object
- * @ev: Corba_Environment
- *
- *   This function returns a duplicated CORBA Object reference;
- * it also bumps the ref count on the object. This is ideal to
- * use in any method returning a Bonobo_Object in a CORBA impl.
- * If object is CORBA_OBJECT_NIL it is returned unaffected.
- *
- * Return value: duplicated & ref'd corba object reference.
- **/
-Bonobo_Unknown
-bonobo_object_dup_ref (Bonobo_Unknown     object,
-		       CORBA_Environment *ev)
-{
-	CORBA_Environment tmpev, *rev;
-	Bonobo_Unknown    ans;
-
-	if (object == CORBA_OBJECT_NIL)
-		return CORBA_OBJECT_NIL;
-
-	if (ev)
-		rev = ev;
-	else {
-		rev = &tmpev;
-		CORBA_exception_init (rev);
-	}
-
-	Bonobo_Unknown_ref (object, rev);
-	ans = CORBA_Object_duplicate (object, rev);
-
-	if (!ev)
-		CORBA_exception_free (&tmpev);
-
-	return ans;
-}
-
-/**
- * bonobo_object_release_unref:
- * @object: a Bonobo_Unknown corba object
- * @ev: Corba_Environment, optional
- *
- *   This function releases a CORBA Object reference;
- * it also decrements the ref count on the bonobo object.
- * This is the converse of bonobo_object_dup_ref. We
- * tolerate object == CORBA_OBJECT_NIL silently.
- **/
-void
-bonobo_object_release_unref (Bonobo_Unknown     object,
-			     CORBA_Environment *ev)
-{
-	CORBA_Environment tmpev, *rev;
-
-	if (object == CORBA_OBJECT_NIL)
+	ao = object->priv;
+	node = bonobo_object_find_lease (ao, id);
+	if (node == NULL) {
+		g_warning ("destroyLease called on non-existent lease");
 		return;
-
-	if (ev)
-		rev = ev;
-	else {
-		rev = &tmpev;
-		CORBA_exception_init (rev);
 	}
-
-	Bonobo_Unknown_unref (object, rev);
-	CORBA_Object_release (object, rev);
-
-	if (!ev)
-		CORBA_exception_free (&tmpev);
+	bonobo_object_remove_lease (ao, node);
 }

 static void
-impl_Bonobo_Unknown_unref (PortableServer_Servant servant, CORBA_Environment *ev)
+impl_Bonobo_Unknown_extendLease (PortableServer_Servant servant,
+				 Bonobo_Unknown_LeaseID id,
+				 CORBA_Environment *ev)
 {
 	BonoboObject *object;
+	BonoboAggregateObject *ao;
+	GList *node;
+	BonoboLease *lease;

 	object = bonobo_object_from_servant (servant);
-
-#if defined(BONOBO_REF_HOOKS) && !defined(bonobo_object_unref)
-	bonobo_object_trace_refs (object, "remote", 0, FALSE);
-#else
-	bonobo_object_unref (object);
-#endif
+	ao = object->priv;
+	node = bonobo_object_find_lease (ao, id);
+	if (node == NULL) {
+		g_warning ("extendLease called on non-existent lease");
+		return;
+	}
+	lease = node->data;
+	lease->age = 0;
 }

 static BonoboObject *
@@ -480,7 +425,7 @@ bonobo_object_get_local_interface_from_o

 	CORBA_exception_init (&ev);

-	for (l = object->priv->ao->objs; l; l = l->next) {
+	for (l = object->priv->objs; l; l = l->next) {
 		BonoboObject *tryme = l->data;

if (CORBA_Object_is_equivalent (interface, tryme->corba_objref, &ev)) {
@@ -492,7 +437,6 @@ bonobo_object_get_local_interface_from_o
 			CORBA_exception_free (&ev);
 			return NULL;
 		}
-
 	}

 	CORBA_exception_free (&ev);
@@ -511,7 +455,9 @@ BonoboObject *
 bonobo_object_query_local_interface (BonoboObject *object,
 				     const char   *repo_id)
 {
+#ifdef ORBIT_IMPLEMENTS_IS_A
 	CORBA_Environment  ev;
+#endif
 	BonoboObject      *retval;
 	CORBA_Object       corba_retval;
 	GType              type;
@@ -526,24 +472,18 @@ bonobo_object_query_local_interface (Bon
 		G_OBJECT (object), bonobo_object_signals [QUERY_INTERFACE],
 		0, repo_id, &corba_retval);

+#ifdef ORBIT_IMPLEMENTS_IS_A
 	CORBA_exception_init (&ev);
-
-	if (! CORBA_Object_is_nil (corba_retval, &ev)) {
-		BonoboObject *local_interface;
+#endif

-		local_interface = bonobo_object_get_local_interface_from_objref (
+	if (corba_retval != CORBA_OBJECT_NIL)
+		return bonobo_object_get_local_interface_from_objref (
 			object, corba_retval);

-		if (local_interface != NULL)
-			bonobo_object_ref (object);
-
-		return local_interface;
-	}
-
 	type = g_type_from_name (repo_id);

 	/* Try looking at the gtk types */
-	for (l = object->priv->ao->objs; l; l = l->next){
+	for (l = object->priv->objs; l; l = l->next){
 		BonoboObject *tryme = l->data;

 		if ((type && g_type_is_a (G_OBJECT_TYPE (tryme), type)) ||
@@ -557,11 +497,10 @@ bonobo_object_query_local_interface (Bon
 			break;
 		}
 	}
-
-	if (retval != NULL)
-		bonobo_object_ref (object);

+#ifdef ORBIT_IMPLEMENTS_IS_A
 	CORBA_exception_free (&ev);
+#endif

 	return retval;
 }
@@ -577,25 +516,18 @@ impl_Bonobo_Unknown_queryInterface (Port
 	local_interface = bonobo_object_query_local_interface (
 		object, repoid);

-#ifdef BONOBO_REF_HOOKS
-	bonobo_debug_print ("query-interface",
-			    "[%p]:[%p]:%s repoid=%s",
-			    object, object->priv->ao,
-			    G_OBJECT_TYPE_NAME (object),
-			    repoid);
-#endif
-
 	if (local_interface == NULL)
 		return CORBA_OBJECT_NIL;

-	return CORBA_Object_duplicate (local_interface->corba_objref, ev);
+	return local_interface->corba_objref;
 }

 static void
 bonobo_object_epv_init (POA_Bonobo_Unknown__epv *epv)
 {
-	epv->ref            = impl_Bonobo_Unknown_ref;
-	epv->unref          = impl_Bonobo_Unknown_unref;
+	epv->createLease    = impl_Bonobo_Unknown_createLease;
+	epv->destroyLease   = impl_Bonobo_Unknown_destroyLease;
+	epv->extendLease    = impl_Bonobo_Unknown_extendLease;
 	epv->queryInterface = impl_Bonobo_Unknown_queryInterface;
 }

@@ -610,14 +542,10 @@ bonobo_object_dispose (GObject *gobject)
 static void
 bonobo_object_finalize_gobject (GObject *gobject)
 {
-	BonoboObject *object = (BonoboObject *) gobject;
-
 #ifdef BONOBO_LIFECYCLE_DEBUG
 	g_warning ("Bonobo Object finalize GObject %p", gobject);
 #endif

-	g_free (object->priv);
-
 	bonobo_object_parent_class->finalize (gobject);
 }

@@ -734,14 +662,13 @@ bonobo_object_instance_init (GObject
 #endif

 	/* Setup aggregate */
-	ao            = g_new0 (BonoboAggregateObject, 1);
-	ao->objs      = g_list_append (ao->objs, object);
-	ao->ref_count = 1;
-
-	/* Setup Private fields */
-	object->priv = g_new (BonoboObjectPrivate, 1);
-	object->priv->ao = ao;
+	ao           = g_new (BonoboAggregateObject, 1);
+	ao->objs     = g_list_prepend (NULL, object);
+	ao->leases   = g_list_prepend (NULL, g_new0 (BonoboLease, 1));
+	object->priv = ao;

+	aggregate_objects = g_list_prepend (aggregate_objects, ao);
+
 	/* Setup signatures */
 	object->object_signature  = BONOBO_OBJECT_SIGNATURE;
 	object->servant_signature = BONOBO_SERVANT_SIGNATURE;
@@ -749,21 +676,10 @@ bonobo_object_instance_init (GObject
 	/* Though this make look strange, destruction of this object
 	   can only occur when the servant is deactivated by the poa.
 	   The poa maintains its own ref count over method invocations
-	   and delays finalization which happens only after:
-	   bonobo_object_finalize_servant: is invoked */
+	   and delays finalization which happens only after
+	   bonobo_object_finalize_servant is invoked */
 	g_object_ref (g_object);

-#ifdef BONOBO_REF_HOOKS
-	{
-		bonobo_debug_print ("create", "[%p]:[%p]:%s to %d", object, ao,
-				    g_type_name (G_TYPE_FROM_CLASS (klass)),
-				    ao->ref_count);
-
-		g_assert (g_hash_table_lookup (living_ao_ht, ao) == NULL);
-		g_hash_table_insert (living_ao_ht, ao, ao);
-	}
-#endif
-
 	do_corba_setup (object, BONOBO_OBJECT_CLASS (klass));
 }

@@ -792,80 +708,11 @@ bonobo_object_get_type (void)
 		
 		type = g_type_register_static (G_TYPE_OBJECT, "BonoboObject",
 					       &info, 0);
-
-#ifdef BONOBO_REF_HOOKS
-		living_ao_ht = g_hash_table_new (NULL, NULL);
-#endif
 	}

 	return type;
 }

-#ifdef BONOBO_REF_HOOKS
-static void
-bonobo_ao_debug_foreach (gpointer key, gpointer value, gpointer user_data)
-{
-	BonoboAggregateObject *ao = value;
-	GList *l;
-
-	g_return_if_fail (ao != NULL);
-
-	bonobo_debug_print ("object-status",
-			    "[%p] %-20s ref_count=%d, interfaces=%d", ao, "",
-			    ao->ref_count, g_list_length (ao->objs));
-		
-	for (l = ao->objs; l; l = l->next) {
-		BonoboObject *object = BONOBO_OBJECT (l->data);
-		
-		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);
-	}
-
-	l = g_list_last (ao->refs);
-
-	if (l)
-		bonobo_debug_print ("referencing" ,"");
-
-	for (; l; l = l->prev) {
-		BonoboDebugRefData *descr = l->data;
-
-		bonobo_debug_print ("", "%-7s - %s:%d",
-				    descr->ref ? "ref" : "unref",
-				    descr->fn, descr->line);
-	}
-}
-#endif
-
-static void
-bonobo_object_tracking_shutdown (void)
-{
-#ifdef BONOBO_REF_HOOKS
-	
-	bonobo_debug_print ("shutdown-start",
-		"-------------------------------------------------");
-
-	if (living_ao_ht)
-		g_hash_table_foreach (living_ao_ht,
-				      bonobo_ao_debug_foreach, NULL);
-
-	bonobo_debug_print ("living-objects",
-			    "living bonobo objects count = %d",
-			    g_hash_table_size (living_ao_ht));
-
-	bonobo_debug_print ("shutdown-end",
-		"-------------------------------------------------");
-#endif
-}
-
-void
-bonobo_object_init (void)
-{
-	g_atexit (bonobo_object_tracking_shutdown);
-}
-
 #ifdef HAVE_DLADDR
 #ifdef __USE_GNU
 static void G_GNUC_UNUSED
@@ -928,38 +775,23 @@ bonobo_object_add_interface (BonoboObjec
        BonoboAggregateObject *oldao, *ao;
        GList *l;

-       g_return_if_fail (object->priv->ao->ref_count > 0);
-       g_return_if_fail (newobj->priv->ao->ref_count > 0);
+       if (object->corba_objref == CORBA_OBJECT_NIL
+	   || newobj->corba_objref == CORBA_OBJECT_NIL)
+	       g_warning ("Adding an interface with a NULL Corba objref");

-       if (object->priv->ao == newobj->priv->ao)
-               return;
+       ao = object->priv;
+       oldao = newobj->priv;

-       if (newobj->corba_objref == CORBA_OBJECT_NIL)
-	       g_warning ("Adding an interface with a NULL Corba objref");
+       if (ao == oldao)
+               return;

        /*
 	* Explanation:
 	*   Bonobo Objects should not be assembled after they have been
 	*   exposed, or we would be breaking the contract we have with
 	*   the other side.
-	*
-	*   This check is not perfect, but might help some people.
 	*/

-       ao = object->priv->ao;
-       oldao = newobj->priv->ao;
-       ao->ref_count = ao->ref_count + oldao->ref_count - 1;
-
-#ifdef BONOBO_REF_HOOKS		
-       bonobo_debug_print ("add_interface",
-			   "[%p]:[%p]:%s to [%p]:[%p]:%s ref_count=%d",
-			   object, object->priv->ao,
-			   G_OBJECT_TYPE_NAME (object),
-			   newobj, newobj->priv->ao,
-			   G_OBJECT_TYPE_NAME (newobj),
-			   ao->ref_count);
-#endif
-
        /* Merge the two AggregateObject lists */
        for (l = oldao->objs; l; l = l->next) {
 	       BonoboObject *new_if = l->data;
@@ -968,21 +800,16 @@ bonobo_object_add_interface (BonoboObjec
                if (!g_list_find (ao->objs, new_if)) {
                        ao->objs = g_list_prepend (ao->objs, new_if);

-		       new_if->priv->ao = ao;
+		       new_if->priv = ao;
                } else
g_warning ("attempting to merge identical interfaces [%p]", new_if);
        }
+       g_assert (newobj->priv == ao);

-       g_assert (newobj->priv->ao == ao);
+       /* Merge the two lease lists. */
+       ao->leases = g_list_concat (ao->leases, oldao->leases);

-#ifdef BONOBO_REF_HOOKS
-       g_assert (g_hash_table_lookup (living_ao_ht, oldao) == oldao);
-       g_hash_table_remove (living_ao_ht, oldao);
-       ao->refs = g_list_concat (ao->refs, oldao->refs);
-#endif
-
-       g_list_free (oldao->objs);
-       g_free (oldao);
+       bonobo_aggregate_object_free (oldao);
 }

 /**
@@ -1053,7 +880,7 @@ bonobo_object_check_env (BonoboObject *o
  * bonobo_unknown_ping:
  * @object: a CORBA object reference of type Bonobo::Unknown
  *
- * Pings the object @object using the ref/unref methods from Bonobo::Unknown.
+ * Pings the object @object with CORBA_Object_non_existent.
  * You can use this one to see if a remote object has gone away.
  *
  * Returns: %TRUE if the Bonobo::Unknown @object is alive.
@@ -1064,16 +891,12 @@ bonobo_unknown_ping (Bonobo_Unknown obje
 	CORBA_Environment ev;
 	gboolean alive;

-	g_return_val_if_fail (object != NULL, FALSE);
+	g_return_val_if_fail (object != CORBA_OBJECT_NIL, FALSE);

-	alive = FALSE;
 	CORBA_exception_init (&ev);
-	Bonobo_Unknown_ref (object, &ev);
-	if (!BONOBO_EX (&ev)) {
-		Bonobo_Unknown_unref (object, &ev);
-		if (!BONOBO_EX (&ev))
-			alive = TRUE;
-	}
+	alive = !CORBA_Object_non_existent (object, &ev);
+	if (BONOBO_EX (&ev))
+		alive = FALSE;
 	CORBA_exception_free (&ev);

 	return alive;
@@ -1087,9 +910,8 @@ bonobo_object_dump_interfaces (BonoboObj

 	g_return_if_fail (BONOBO_IS_OBJECT (object));

-	ao = object->priv->ao;
+	ao = object->priv;
 	
-	fprintf (stderr, "references %d\n", ao->ref_count);
 	for (l = ao->objs; l; l = l->next) {
 		BonoboObject *o = l->data;
 		
@@ -1103,86 +925,26 @@ bonobo_object_dump_interfaces (BonoboObj
 }

 static gboolean
-idle_unref_fn (BonoboObject *object)
-{
-	bonobo_object_unref (object);
-
-	return FALSE;
-}
-
-void
-bonobo_object_idle_unref (BonoboObject *object)
-{
-	g_idle_add ((GSourceFunc) idle_unref_fn, object);
-}
-
-static void
-unref_list (GSList *l)
-{
-	for (; l; l = l->next)
-		bonobo_object_unref (l->data);
-}
-
-/**
- * bonobo_object_list_unref_all:
- * @list: A list of BonoboObjects *s
- *
- *  This routine unrefs all valid objects in
- * the list and then removes them from @list if
- * they have not already been so removed.
- **/
-void
-bonobo_object_list_unref_all (GList **list)
+idle_release_fn (gpointer callback_data)
 {
-	GList *l;
-	GSList *unrefs = NULL, *u;
+	BonoboReleaseArgs *args;

-	g_return_if_fail (list != NULL);
+	args = callback_data;
+	bonobo_release (args->owner, args->owned_object);
+	g_free (args);

-	for (l = *list; l; l = l->next) {
-		if (l->data && !BONOBO_IS_OBJECT (l->data))
-			g_warning ("Non object in unref list");
-		else if (l->data)
-			unrefs = g_slist_prepend (unrefs, l->data);
-	}
-
-	unref_list (unrefs);
-
-	for (u = unrefs; u; u = u->next)
-		*list = g_list_remove (*list, u->data);
-
-	g_slist_free (unrefs);
+	return FALSE;
 }

-/**
- * bonobo_object_list_unref_all:
- * @list: A list of BonoboObjects *s
- *
- *  This routine unrefs all valid objects in
- * the list and then removes them from @list if
- * they have not already been so removed.
- **/
 void
-bonobo_object_slist_unref_all (GSList **list)
+bonobo_idle_release (gpointer owner, Bonobo_Unknown owned_object)
 {
-	GSList *l;
-	GSList *unrefs = NULL, *u;
-
-	g_return_if_fail (list != NULL);
-
-	for (l = *list; l; l = l->next) {
-		if (l->data && !BONOBO_IS_OBJECT (l->data))
-			g_warning ("Non object in unref list");
-		else if (l->data)
-			unrefs = g_slist_prepend (unrefs, l->data);
-	}
+	BonoboReleaseArgs *args;

-	unref_list (unrefs);
-
-	for (u = unrefs; u; u = u->next)
-		*list = g_slist_remove (*list, u->data);
-
-	g_slist_free (unrefs);
+	args = g_new (BonoboReleaseArgs, 1);
+	args->owner = owner;
+	args->owned_object = owned_object;
+	g_idle_add (idle_release_fn, args);
 }

 /**
@@ -1347,4 +1109,203 @@ bonobo_type_unique (GType             pa
 		return type;
 	else
 		return 0;
+}
+
+static BonoboOwnerListEntry *
+bonobo_owner_list_entry_new (gpointer owner,
+			     gboolean while_alive,
+			     Bonobo_Unknown owned_object)
+{
+	BonoboOwnerListEntry *entry = g_new (BonoboOwnerListEntry, 1);
+
+	entry->owner = owner;
+	entry->while_alive = while_alive;
+	entry->owned_object = corba_objref_duplicate (owned_object);
+	if (while_alive) {
+		g_object_weak_ref (G_OBJECT (owner),
+				   owner_gone_callback,
+				   entry);
+	}
+
+	return entry;
+}
+
+static void
+bonobo_owner_list_entry_free (BonoboOwnerListEntry *entry)
+{
+	if (entry->while_alive) {
+		g_object_weak_unref (G_OBJECT (entry->owner),
+				     owner_gone_callback,
+				     entry);
+	}
+	corba_objref_release (entry->owned_object);
+	g_free (entry);
+}
+
+static void
+remove_owner_list_entry (BonoboOwnerListEntry *entry)
+{
+	BonoboHeldLease *held_lease;
+
+	held_lease = g_hash_table_lookup (owned_objects, entry->owned_object);
+	g_assert (held_lease != NULL);
+
+	held_lease->owners = g_list_remove (held_lease->owners, entry);
+	if (held_lease->owners == NULL) {
+		g_hash_table_remove (owned_objects, entry->owned_object);
+	}
+
+	bonobo_owner_list_entry_free (entry);
+}
+
+static void
+owner_gone_callback (gpointer data)
+{
+	BonoboOwnerListEntry *entry = data;
+
+	entry->while_alive = FALSE; /* prevent doing another weak_unref */
+	remove_owner_list_entry (entry);
+}
+
+static void
+bonobo_held_lease_free (BonoboHeldLease *held_lease)
+{
+	GList *node;
+
+	for (node = held_lease->owners; node != NULL; node = node->next)
+		bonobo_owner_list_entry_free (node->data);
+	g_list_free (held_lease->owners);
+	g_free (held_lease);
+}
+
+static void
+bonobo_held_lease_free_cover (gpointer data)
+{
+	bonobo_held_lease_free (data);
+}
+
+static Bonobo_Unknown
+bonobo_retain_internal (gpointer owner,
+			gboolean while_alive,
+			Bonobo_Unknown owned_object)
+{
+	BonoboHeldLease *held_lease;
+	CORBA_Environment ev;
+	Bonobo_Unknown_LeaseID id;
+
+	CORBA_exception_init (&ev);
+
+	if (owned_objects == NULL)
+		owned_objects = g_hash_table_new_full
+			(corba_objref_hash_cover,
+			 corba_objref_equal_cover,
+			 corba_objref_release_cover,
+			 bonobo_held_lease_free_cover);
+
+	held_lease = g_hash_table_lookup (owned_objects, owned_object);
+	if (held_lease == NULL) {
+		id = Bonobo_Unknown_createLease (owned_object, &ev);
+		if (BONOBO_EX (&ev)) {
+			g_warning ("unable to create lease for object %p", owned_object);
+			goto exit;
+		}
+
+		held_lease = g_new0 (BonoboHeldLease, 1);
+		held_lease->id = id;
+		g_hash_table_insert (owned_objects, owned_object, held_lease);
+	}
+
+	held_lease->owners = g_list_prepend
+		(held_lease->owners,
+		 bonobo_owner_list_entry_new (owner, while_alive, owned_object));
+
+ exit:
+	CORBA_exception_free (&ev);
+
+	return corba_objref_duplicate (owned_object);
+}
+
+/**
+ * bonobo_retain
+ *
+ * @owner: A pointer representing the entity while will retain a reference.
+ * @owned_object: The CORBA object to retain a reference to.
+ *
+ * Makes a duplicate reference for @owned_object and records the
+ * fact that it is retained by @owner. This will create a lease
+ * to @owned_object if necessary and will arrange to have the lease
+ * extended at regular intervals until the reference is released
+ * by a call to bonobo_release.
+ *
+ * Returns: A duplicate reference to @owned_object.
+ */
+Bonobo_Unknown
+bonobo_retain (gpointer owner,
+	       Bonobo_Unknown owned_object)
+{
+	return bonobo_retain_internal (owner, FALSE, owned_object);
+}
+
+/**
+ * bonobo_retain_while_alive
+ *
+ * @owner: An object which will retain a reference.
+ * @owned_object: The CORBA object to retain a reference to.
+ *
+ * Makes a duplicate reference for @owned_object and records the
+ * fact that it is retained by @owner. This will create a lease
+ * to @owned_object if necessary and will arrange to have the lease
+ * extended at regular intervals until the reference is released
+ * by a call to bonobo_release.
+ *
+ * If @owner is destroyed, the reference to @owned_object is
+ * automatically released.
+ *
+ * Returns: A duplicate reference to @owned_object.
+ */
+Bonobo_Unknown
+bonobo_retain_while_alive (GObject *owner,
+			   Bonobo_Unknown owned_object)
+{
+	g_return_val_if_fail (G_IS_OBJECT (owner),
+			      corba_objref_duplicate (owned_object));
+	return bonobo_retain_internal (owner, TRUE, owned_object);
+}
+
+static gboolean
+owner_list_entry_matches_owner (gconstpointer a,
+				gconstpointer b)
+{
+	return ((BonoboOwnerListEntry *) a)->owner == b;
+}
+
+/**
+ * bonobo_release
+ *
+ * @owner: An entity that was retaining a reference.
+ * @owned_object: The CORBA object it was retaining a reference to.
+ *
+ * Releases a reference for @owned_object and records the fact that
+ * it is no longer retained by @owner. This will destroy a lease to
+ * @owned_object if necessary.
+ */
+void
+bonobo_release (gpointer owner,
+		Bonobo_Unknown owned_object)
+{
+	BonoboHeldLease *held_lease;
+	GList *node;
+
+	if (owned_objects != NULL) {
+		held_lease = g_hash_table_lookup (owned_objects, owned_object);
+		if (held_lease != NULL) {
+			node = g_list_find_custom (held_lease->owners,
+						   owner,
+						   owner_list_entry_matches_owner);
+			if (node != NULL)
+				remove_owner_list_entry (node->data);
+		}
+	}
+
+	corba_objref_release (owned_object);
 }
Index: bonobo/bonobo-object.h
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-object.h,v
retrieving revision 1.63
diff -p -u -r1.63 bonobo-object.h
--- bonobo/bonobo-object.h	2001/06/27 23:40:03	1.63
+++ bonobo/bonobo-object.h	2001/07/18 17:42:55
@@ -88,24 +88,16 @@ Bonobo_Unknown           bonobo_object_c
#define bonobo_object_get_servant(o) ((PortableServer_Servant)((guchar *)(o) + BONOBO_OBJECT_HEADER_SIZE))

 /*
- * Gnome Object Life Cycle
+ * Object Life Cycle
  */
-Bonobo_Unknown bonobo_object_dup_ref (Bonobo_Unknown object,
-							       CORBA_Environment      *ev);
-void bonobo_object_release_unref (Bonobo_Unknown object,
-							       CORBA_Environment      *ev);
-void bonobo_object_ref (BonoboObject *object); -void bonobo_object_idle_unref (BonoboObject *object); -void bonobo_object_unref (BonoboObject *object);
-void                     bonobo_object_init                   (void);
-void bonobo_object_trace_refs (BonoboObject *object,
-							       const char   *fn,
-							       int           line,
-							       gboolean      ref);
-#ifdef BONOBO_OBJECT_DEBUG
-# define bonobo_object_ref(o) G_STMT_START{bonobo_object_trace_refs((o),G_GNUC_PRETTY_FUNCTION,__LINE__,TRUE)
;}G_STMT_END
-# define bonobo_object_unref(o) G_STMT_START{bonobo_object_trace_refs((o),G_GNUC_PRETTY_FUNCTION,__LINE__,FALSE)
;}G_STMT_END
-#endif	/* BONOBO_OBJECT_DEBUG */
+Bonobo_Unknown bonobo_retain (gpointer owner, Bonobo_Unknown owned_object); +Bonobo_Unknown bonobo_retain_while_alive (GObject *owner, Bonobo_Unknown owned_object); +void bonobo_release (gpointer owner, Bonobo_Unknown owned_object); +void bonobo_idle_release (gpointer owner, Bonobo_Unknown owned_object);
+
+/*
+ * Debugging
+ */
void bonobo_object_dump_interfaces (BonoboObject *object);

 /*
@@ -125,8 +117,6 @@ void                     bonobo_object_c
  * Others
  */
 gboolean  bonobo_unknown_ping           (Bonobo_Unknown object);
-void      bonobo_object_list_unref_all  (GList        **list);
-void      bonobo_object_slist_unref_all (GSList       **list);


 /* Detects the pointer type and returns the object reference - magic. */
Index: bonobo/bonobo-property-bag-client.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-property-bag-client.c,v
retrieving revision 1.39
diff -p -u -r1.39 bonobo-property-bag-client.c
--- bonobo/bonobo-property-bag-client.c	2001/07/07 14:10:48	1.39
+++ bonobo/bonobo-property-bag-client.c	2001/07/18 17:42:55
@@ -26,8 +26,8 @@ unref_default_bag (void)
 {
 	G_LOCK(default_bag_lock);

-	if (default_bag !=  CORBA_OBJECT_NIL)
-		bonobo_object_release_unref (default_bag, NULL);
+	if (default_bag != CORBA_OBJECT_NIL)
+		bonobo_release (&default_bag, default_bag);

 	G_UNLOCK(default_bag_lock);
 }
@@ -39,10 +39,12 @@ get_default_bag (CORBA_Environment  *ev)

 	if (default_bag ==  CORBA_OBJECT_NIL) {
 		default_bag = bonobo_get_object (BONOBO_PBCLIENT_DEFAULT_BAG,
-		        "IDL:Bonobo/PropertyBag:1.0", ev);
+						 "IDL:Bonobo/PropertyBag:1.0", ev);

-		if (default_bag !=  CORBA_OBJECT_NIL)
+		if (default_bag !=  CORBA_OBJECT_NIL) {
+			default_bag = bonobo_retain (&default_bag, default_bag);
 			g_atexit (unref_default_bag);
+		}
 	}

 	if (default_bag ==  CORBA_OBJECT_NIL)
Index: bonobo/bonobo-running-context.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-running-context.c,v
retrieving revision 1.20
diff -p -u -r1.20 bonobo-running-context.c
--- bonobo/bonobo-running-context.c	2001/07/02 12:50:30	1.20
+++ bonobo/bonobo-running-context.c	2001/07/18 17:42:56
@@ -115,8 +115,6 @@ running_info_destroy (void)
 	}
 	bonobo_running_info = NULL;

-	if (bonobo_running_context)
-		bonobo_object_unref (BONOBO_OBJECT (bonobo_running_context));
 	bonobo_running_context = NULL;
 	bonobo_running_event_source = NULL;
 }
@@ -307,14 +305,6 @@ impl_Bonobo_RunningContext_removeKey (Po
 }

 static void
-impl_Bonobo_RunningContext_atExitUnref (PortableServer_Servant servant,
-					const CORBA_Object     object,
-					CORBA_Environment     *ev)
-{
-	bonobo_running_context_at_exit_unref (object);
-}
-
-static void
 bonobo_running_context_class_init (BonoboRunningContextClass *klass)
 {
 	GObjectClass *object_class = (GObjectClass *) klass;
@@ -335,7 +325,6 @@ bonobo_running_context_class_init (Bonob
 	epv->removeObject  = impl_Bonobo_RunningContext_removeObject;
 	epv->addKey        = impl_Bonobo_RunningContext_addKey;
 	epv->removeKey     = impl_Bonobo_RunningContext_removeKey;
-	epv->atExitUnref   = impl_Bonobo_RunningContext_atExitUnref;

 }

@@ -346,15 +335,14 @@ bonobo_running_context_init (GObject *ob
 }

 BONOBO_TYPE_FUNC_FULL (BonoboRunningContext,
-			 Bonobo_RunningContext,
-			 PARENT_TYPE,
-			 bonobo_running_context);
+		       Bonobo_RunningContext,
+		       PARENT_TYPE,
+		       bonobo_running_context);

 BonoboObject *
 bonobo_running_context_new (void)
 {
 	if (bonobo_running_context) {
-		bonobo_object_ref (bonobo_running_context);
 		return bonobo_running_context;
 	}

@@ -381,13 +369,6 @@ bonobo_context_running_get (void)
 	return bonobo_running_context_new ();
 }

-static void
-last_unref_cb (gpointer      context,
-	       CORBA_Object  object)
-{
-	bonobo_object_release_unref (object, NULL);
-}
-
 void
 bonobo_running_context_at_exit_unref (CORBA_Object object)
 {
@@ -396,39 +377,12 @@ bonobo_running_context_at_exit_unref (CO

 	CORBA_exception_init (&ev);

-	obj_dup = CORBA_Object_duplicate (object, &ev);
-
 	bonobo_running_context_ignore_object (obj_dup);

 	if (bonobo_running_context)
 		g_signal_connect (G_OBJECT (bonobo_running_context),
-				  "last_unref", G_CALLBACK (last_unref_cb),
+				  "last_unref", G_CALLBACK (bonobo_release),
 				  obj_dup);
 	
 	CORBA_exception_free (&ev);
 }
-
-static void
-last_unref_exit_cb (gpointer      context,
-		    BonoboObject *object)
-{
-        bonobo_object_unref (object);
-	bonobo_main_quit ();
-}
-
-void
-bonobo_running_context_auto_exit_unref (BonoboObject *object)
-{
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (BONOBO_IS_OBJECT (object));
-
-	bonobo_running_context_ignore_object (BONOBO_OBJREF (object));
-
-	if (bonobo_running_context)
-		g_signal_connect (G_OBJECT (bonobo_running_context),
-				  "last_unref",
-				  G_CALLBACK (last_unref_exit_cb),
-				  object);
-
-}
-
Index: bonobo/bonobo-running-context.h
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-running-context.h,v
retrieving revision 1.11
diff -p -u -r1.11 bonobo-running-context.h
--- bonobo/bonobo-running-context.h	2001/04/18 22:09:07	1.11
+++ bonobo/bonobo-running-context.h	2001/07/18 17:42:56
@@ -45,7 +45,6 @@ void        bonobo_running_context_trace
 						    const char  *fn,
 						    int          line,
 						    int          mode);
-void        bonobo_running_context_at_exit_unref   (CORBA_Object object);

 #ifdef BONOBO_OBJECT_DEBUG
# define bonobo_running_context_add_object(o) G_STMT_START{bonobo_running_context_trace_objects((o),G_GNUC_PRETTY_FUNCTION,
__LINE__,0);}G_STMT_END
Index: bonobo/bonobo-simple-source.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/Attic/bonobo-simple-source.c,v
retrieving revision 1.17
diff -p -u -r1.17 bonobo-simple-source.c
--- bonobo/bonobo-simple-source.c	2000/12/13 16:29:00	1.17
+++ bonobo/bonobo-simple-source.c	2001/07/18 17:42:56
@@ -199,7 +199,6 @@ gnome_simple_data_source_new (GnomeSimpl
 	ssource = gtk_type_new (gnome_simple_data_source_get_type ());
corba_ssource = create_gnome_simple_data_source (BONOBO_OBJECT (ssource));
 	if (corba_ssource == CORBA_OBJECT_NIL) {
-		bonobo_object_unref (BONOBO_OBJECT (ssource));
 		return NULL;
 	}

Index: bonobo/bonobo-storage.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-storage.c,v
retrieving revision 1.56
diff -p -u -r1.56 bonobo-storage.c
--- bonobo/bonobo-storage.c	2001/07/10 12:30:37	1.56
+++ bonobo/bonobo-storage.c	2001/07/18 17:42:56
@@ -90,7 +90,7 @@ bonobo_storage_copy_to (Bonobo_Storage s
 						ev);

 			if (BONOBO_EX (ev)) {
-				bonobo_object_release_unref (new_dest, NULL);
+				bonobo_release (NULL, new_dest);
 				break;
 			}

@@ -99,14 +99,14 @@ bonobo_storage_copy_to (Bonobo_Storage s
 				 Bonobo_Storage_READ, ev);
 			
 			if (BONOBO_EX (ev)) {
-				bonobo_object_release_unref (new_dest, NULL);
+				bonobo_release (NULL, new_dest);
 				break;
 			}

 			bonobo_storage_copy_to (new_src, new_dest, ev);
 			
-			bonobo_object_release_unref (new_src, NULL);
-			bonobo_object_release_unref (new_dest, NULL);
+			bonobo_release (NULL, new_src);
+			bonobo_release (NULL, new_dest);

 			if (BONOBO_EX (ev))
 				break;
@@ -129,8 +129,7 @@ bonobo_storage_copy_to (Bonobo_Storage s
 				CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
 						     ex_Bonobo_Storage_IOError,
 						     NULL);
-				bonobo_object_release_unref (dest_stream,
-							     NULL);
+				bonobo_release (NULL, dest_stream);
 				break;
 			}

@@ -139,15 +138,14 @@ bonobo_storage_copy_to (Bonobo_Storage s
 				 Bonobo_Storage_READ, ev);

 			if (BONOBO_EX (ev)) {
-				bonobo_object_release_unref (dest_stream,
-							     NULL);
+				bonobo_release (NULL, dest_stream);
 				break;
 			}

 			copy_stream (src_stream, dest_stream, ev);

-			bonobo_object_release_unref (src_stream, NULL);
-			bonobo_object_release_unref (dest_stream, NULL);
+			bonobo_release (NULL, src_stream);
+			bonobo_release (NULL, dest_stream);

 			if (BONOBO_EX (ev))
 				break;
Index: idl/Bonobo_Context.idl
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Bonobo_Context.idl,v
retrieving revision 1.10
diff -p -u -r1.10 Bonobo_Context.idl
--- idl/Bonobo_Context.idl	2001/05/11 22:46:08	1.10
+++ idl/Bonobo_Context.idl	2001/07/18 17:42:57
@@ -95,8 +95,6 @@ module Bonobo {
 		 * Removes a stringified reference from tracking
 		 */
 		void removeKey   (in string key);
-
-		void atExitUnref (in Object obj);
 	};

 #if 0
Index: idl/Bonobo_Unknown.idl
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Bonobo_Unknown.idl,v
retrieving revision 1.5
diff -p -u -r1.5 Bonobo_Unknown.idl
--- idl/Bonobo_Unknown.idl	2000/11/27 19:53:50	1.5
+++ idl/Bonobo_Unknown.idl	2001/07/18 17:42:57
@@ -16,19 +16,31 @@

 module Bonobo {
 	interface Unknown {
+		typedef long LeaseID;
+
 		/**
-		 * ref:
+		 * createLease:
 		 *
-		 * increments the reference count
+		 * Creates a new lease.
+		 * Return: ID of the new lease.
+		 */
+		LeaseID createLease ();
+
+		/**
+		 * destroyLease:
+		 *
+		 * Destroys an existing lease.
+		 * @id: ID of the lease to destroy.
 		 */
-		void ref ();
+		void destroyLease (in LeaseID id);

 		/**
-		 * unref:
+		 * extendLease:
 		 *
-		 * decrements the reference count
+		 * Extends an existing lease.
+		 * @id: ID of the lease to extend.
 		 */
-		void unref ();
+		void extendLease (in LeaseID id);

 		/**
 		 * queryInterface:
Index: tests/test-moniker.c
===================================================================
RCS file: /cvs/gnome/libbonobo/tests/test-moniker.c,v
retrieving revision 1.15
diff -p -u -r1.15 test-moniker.c
--- tests/test-moniker.c	2001/06/26 16:43:34	1.15
+++ tests/test-moniker.c	2001/07/18 17:42:57
@@ -33,8 +33,6 @@ check_string (const char *prefix, const
 	g_assert (bonobo_moniker_client_equal (
 		BONOBO_OBJREF (moniker), name, NULL));

-	bonobo_object_unref (BONOBO_OBJECT (moniker));
-
 	g_free (name);
 }

Index: tests/test-object.c
===================================================================
RCS file: /cvs/gnome/libbonobo/tests/test-object.c,v
retrieving revision 1.4
diff -p -u -r1.4 test-object.c
--- tests/test-object.c	2001/07/16 23:42:23	1.4
+++ tests/test-object.c	2001/07/18 17:42:57
@@ -27,34 +27,6 @@ main (int argc, char *argv [])
 	
 		g_assert (bonobo_object (object) == object);
 		g_assert (bonobo_object (&object->servant) == object);
-
-		bonobo_object_unref (BONOBO_OBJECT (object));
-	}
-
-	fprintf (stderr, "In-proc lifecycle\n");
-	{
-		object = BONOBO_OBJECT (g_object_new (
-			bonobo_moniker_get_type (), NULL));
-
-		ref = CORBA_Object_duplicate (BONOBO_OBJREF (object), NULL);
-
-		bonobo_object_release_unref (ref, NULL);
-	}
-
-	fprintf (stderr, "Out of proc lifecycle\n");
-	{
-		object = BONOBO_OBJECT (g_object_new (
-			bonobo_moniker_get_type (), NULL));
-
-		ref = CORBA_Object_duplicate (BONOBO_OBJREF (object), NULL);
-
-		ORBit_small_handle_request (
-			ORBIT_STUB_GetPoaObj (BONOBO_OBJREF (object)),
-			"unref", NULL, NULL, NULL, NULL, ev);
-		g_assert (!BONOBO_EX (ev));
-
-		CORBA_Object_release (ref, ev);
-		g_assert (!BONOBO_EX (ev));
 	}

 	fprintf (stderr, "All tests passed\n");
Index: tests/test-properties-client.c
===================================================================
RCS file: /cvs/gnome/libbonobo/tests/test-properties-client.c,v
retrieving revision 1.14
diff -p -u -r1.14 test-properties-client.c
--- tests/test-properties-client.c	2001/07/07 14:10:49	1.14
+++ tests/test-properties-client.c	2001/07/18 17:42:57
@@ -175,7 +175,7 @@ create_bag_client (void)
 		"string-test", TC_CORBA_string, "you are a precious flower",
 		NULL);

-	bonobo_object_release_unref (pb, NULL);
+	bonobo_release (&pb, pb);

 	bonobo_main_quit ();

@@ -202,6 +202,8 @@ main (int argc, char **argv)
 		g_error ("Could not bind to PropertyBag object");
 		return 1;
 	}
+
+	bonobo_retain (&pb, pb);

 	g_idle_add ((GSourceFunc) create_bag_client, NULL);

===================================================================

    -- Darin




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