investigation into replacing ref. counts with leases
- From: Darin Adler <darin bentspoon com>
- To: gnome-components-list gnome org
- Cc: Michael Meeks <michael ximian com>
- Subject: investigation into replacing ref. counts with leases
- Date: Wed, 18 Jul 2001 11:17:48 -0700
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]