Thread: [java-gnome-hackers] handle->GObject mapping needed
Brought to you by:
afcowie
From: Tom B. <Tom...@Su...> - 2003-01-04 06:37:49
|
In adding support for container events, I found we need to be able to map a GTK widget handle to its associated Java-GNOME Widget object, something like: /** * Return the associated Java-GNOME object for a given handle. */ public static GObject getGObject(int handle) { ... } Briefly scanning through the code, it looks like this mapping is needed elsewhere. For example, there were many cases where a new Widget was created in an event callback, so that there were then two Widget objects which shared the same GTK handle. This duplication was okay back when all widget state was stored within GTK, but now that we have Java-based event listener lists and the like, it's important that the 1-to-1 mapping between widgets and Widgets be preserved. There are two ways to implement a "back-pointer" from a native handle to its associated GObject: 1. Store an JNI object reference in the native gobject. GTK has the ability to add named properties using g_object_set, so this is workable. The AWT uses this method. 2. Maintain a hashtable to map handles to GObjects, and use a factory method instead of constructors to look up or create GObjects from handles. The advantage of (1) is that GTK manages the memory, so there's no worry of object leaks. I'd implement it by making GObject.handle private and add a protected setter which would call a native method to set the named property. The disadvantage is that this mapping isn't as obvious as (2). The advantage of (2) is that it easy to understand and therefore maintain. The main problem is that all GObject constructors get hidden/deprecated, and a factory method used instead (like Widget.makeWidget). This factory method would check the hashtable before creating new GObjects with a given handle. Josh Bloch recommends this technique in Effective Java, but not everyone is used to it. My vote is for (1), but I'm comfortable implementing either solution. Tom |
From: Mark H. <mh...@ti...> - 2003-01-09 10:03:43
|
On Sat, 2003-01-04 at 06:37, Tom Ball wrote: > 1. Store an JNI object reference in the native gobject. GTK has the > ability to add named properties using g_object_set, so this is > workable. The AWT uses this method. I guess this would take longer when creating all widgets as more jni calls are required. Would the reference be created using (*env)->NewGlobalRef so that the GC doesn't free it? If so, how will this reference be removed to allow the Java object to be freed? If not, then what will happen if the user does not keep a reference to the Java object > 2. Maintain a hashtable to map handles to GObjects, and use a factory > method instead of constructors to look up or create GObjects from > handles. Constructors would still be used when constructing a new widget. Factory methods would be used when accessing an existing object (or at least existing in the native sense). Why is this a problem? IMHO, it makes more sense than having everything done in constructors. -- .''`. Mark Howard : :' : `. `' http://www.tildemh.com `- mh...@de... | mh...@ti... | mh...@ca... |
From: Tom B. <Tom...@Su...> - 2003-01-09 17:44:55
|
On Thu, 2003-01-09 at 01:52, Mark Howard wrote: > On Sat, 2003-01-04 at 06:37, Tom Ball wrote: > > 1. Store an JNI object reference in the native gobject. GTK has the > > ability to add named properties using g_object_set, so this is > > workable. The AWT uses this method. > > I guess this would take longer when creating all widgets as more jni > calls are required. Not very long, as downcalls (Java->JNI) are very fast while upcalls are slow. I doubt we're creating thousands of widgets per second; one extra JNI call per widget *creation* shouldn't impact performance. Also, this only applies to widgets that are created from handles; widgets which call GTK to create their native counterparts can store the handle in that same call. > Would the reference be created using (*env)->NewGlobalRef so that the GC > doesn't free it? Right. > If so, how will this reference be removed to allow the Java object to be > freed? In the widget's destroy method. > If not, then what will happen if the user does not keep a reference to > the Java object One issue we haven't faced is that it is currently possible for a Java widget to be gc'd without its handle being destroyed, causing an object leak in the underlying toolkit. This probably hasn't been a problem because our test programs are not long-lived, but may indeed be a serious issue when real apps using our library are created and used (like the email client). Doing better cleanup will address this issue. > > 2. Maintain a hashtable to map handles to GObjects, and use a factory > > method instead of constructors to look up or create GObjects from > > handles. > Constructors would still be used when constructing a new widget. > Factory methods would be used when accessing an existing object (or at > least existing in the native sense). > Why is this a problem? IMHO, it makes more sense than having everything > done in constructors. One reason I like using public factory methods *instead* of public constructors is that when designed well they can simplify library use. Josh Bloch describes their benefits in great detail in Effective Java, which I highly recommend. Still, I am not pushing for a big API overhaul -- I'd rather see 0.8 get released. Tom |