Ok, I have a better idea. What if we use the toggle references in the other way.
The situation would generally look like this: +---------+ | Other | | GObject | +---------+ | | V +---------+ +---------+ +---------+ | Proxy A |<------| GObject |------>| Proxy B | | |------>| |<------| | +---------+ +---------+ +---------+ ^ ^ | | +---------+ +---------+ | Other A | | Other B | | object | | object | +---------+ +---------+ However, when the last reference to the Proxy exept the GObject reference is gone, we convert the Gobject reference to a weak one: +---------+ | Other | | GObject | +---------+ | | V +---------+ +---------+ +---------+ | Proxy A |<------| GObject |------>| Proxy B | | |------>| |<......| | +---------+ +---------+ +---------+ ^ | +---------+ | Other A | | object | +---------+ This means the Proxies will not die until the GObject dies, and the proxy won't keep the GObject alive unless something references them. Just what we want. The problem is of course implementing the toggle-reference for the Language runtime (its easy in the GObject runtime, because we can just hack the runtime). I think I have a solution that should work in general. What you do is split up the Proxy into two objects, one keeping all the data for the proxy, and the other one is just a facade that you give out to other objects to use as a reference. The Proxy Data object knows about the facade object, but only through a weak reference, so when the facade is not referenced anymore we'll get told, and we can change our reference on the GObject from a strong to a weak ref. In this situation Proxy A has a reference, but Proxy B not: +---------+ +---------+ +---------+ | Proxy A |<------| GObject |------>| Proxy B | | Data |------>| |<......| | +---------+ +---------+ +---------+ ^ . | . | V +---------+ | Proxy A | | Facade | +---------+ ^ | +---------+ | Other A | | object | +---------+ The implementation in Java would be something like: (Note: this example is not threadsafe) static Hashtable gobjectHash; /* Long -> GObjectProxy */ static GObjectFacade lookupGObject(Long gobject) { GObjectProxy proxy = gobjectHash.get(gobject); if (proxy == null) { proxy = new GObjectProxy(gobject); } return proxy.getFacade(); } void gobject_died(Long gobject, GObjectProxy proxy) { /* facade should be null here */ gobjectHash.remove(gobject); } class GObjectProxy { WeakReference facade; Long gobject ; HashTable data; /* whatever data you want to store in the proxy */ GObjectProxy(Long gobject) { this.gobject = gobject; data = new HashTable(); gobjectHash.put(gobject, proxy); g_object_weak_ref(gobject, gobject_died, this); } clearFacace() { facade = null; g_object_weak_ref(gobject, gobject_died, this); g_object_unref(gobject); } GObjectFacade getFacade() { if (facade == null) { GObjectFacade facade = new GObjectFacade(this); facade = WeakReference(facade); g_object_ref(gobject); g_object_weak_unref(gobject, gobject_died, this); } return facade.get(); } } class GObjectFacade { GObjectProxy proxy; Object getData(String attr) { return proxy.data.get(attr); } void finalize() { proxy.clearFacade(); } } There is a disadvantage of course, we use two objects per proxy instead of one, and we do one extra dereference to get to the proxy data. We also do one extra dereference to get to the gobject pointer, but at the cost of some memory that could be optimized by also storing the gobject pointer in the facade. Of course, as an optimization, data-less proxies can just be handled by a weak reference from the GObject. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Alexander Larsson Red Hat, Inc [EMAIL PROTECTED] [EMAIL PROTECTED] He's a jaded vegetarian boxer moving from town to town, helping folk in trouble. She's a supernatural green-skinned bounty hunter from a family of eight older brothers. They fight crime! _______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list