On Friday, March 21, 2003, at 05:05 AM, Matthew Pocock wrote:
It's a problem, isn't it. The documentation should certainly be added. I'm a little uneasy about StrongRefChangeSupport because it's usualy the one registering the listener that needs to know if the reference is strong or weak, and there would be no way for them to discover this from a Changeable (without
I agree about that. I proposed StrongRefChangeSupport to give end-developers the option of using a strong-reference-based solution after evaluating the uses and potential costs/benefits for their projects. Since event handling is not BioJava's raison d'etre, it's fine with me if StrongRefChangeSupport just stays in the mailing list archive for reference (so to speak).
[I also don't think that adding something like canUseAnonEventListeners() to Changeable would be of any practical use -- the reason that anonymous event handlers are appealing is that they are code-light and easy to understand. If you had to wrap each use in a big conditional (and provide an alternative) that appeal goes out the window. The result would be that people just wouldn't use anonymous handlers with Changeables. This result can much more easily be accomplished through documentation.]
adding extra Changeable API which I'm loathed to sudgest). Perhaps this needs documenting in big flashing lights within Changeable as well.
That's probably a good idea. In Changeable there could be a message describing the potential pitfalls & benefits of using ChangeSupport to implement it. Then in classes that do use it could have some sort of boilerplate message that refers to this description. Ex: "This class' implementation of Changeable does not support anonymous event listeners. See Changeable for details."
Rhett
-- Rhett Sutphin Research Assistant (Software) Coordinated Laboratory for Computational Genomics and the Center for Macular Degeneration University of Iowa - Iowa City, IA 52242 - USA 4111 MEBRF - email: [EMAIL PROTECTED]
--- Rhett Sutphin <[EMAIL PROTECTED]> wrote: > Hi,http://www.biojava.org/pipermail/biojava-l/2000-December/000578.html).
I am using org.biojava.utils.ChangeSupport in a application I'm writing. I noticed some odd behavior yesterday: some of my ChangeListeners would stop being notified after the program had been executing for a short while. After some false starts, I looked at the ChangeSupport source and discovered that it only maintains weak references to the ChangeListeners registered in it.
After looking through the mailing list archives, I understand why this is desirable in some instances (see
Unfortunately, it conflicts with a common java-event-handling idiom: the inner class event handler (anonymous or not). When you do something like this:
chgable.addChangeListener(new ChangeAdapter() { public void postChange(ChangeEvent ce) { doSomething(); } });
or this:
chgable.addChangeListener(new InnerChangeHandler());
where chgable uses ChangeSupport, it silently stops working shortly after the application starts up because the only reference to the event handler is the weak reference in the ChangeSupport object.
Since the WeakReference use is, on one hand, a reasonable solution to a memory-efficiency problem but, on the other hand, silently causes odd behavior in some instances, I propose that this should be documented. Something like this might be sufficient:
--- Warning: ChangeSupport only maintains weak references to registered ChangeListeners. This means that any ChangeListener registered to it will stop receiving change events (because it is garbage-collected) as soon as all other references to the ChangeListener go out of scope. Classes that use ChangeSupport are advised to document this, as it will make anonymous event handlers fail to behave as expected. ---
In addition to this, it might be reasonable to add a version of ChangeSupport that uses strong references for those who are aware of the risks and don't care. A quick-and-dirty version of such a class appears below.
Rhett
------ StrongRefChangeSupport.java ------
import org.biojava.utils.ChangeSupport; import org.biojava.utils.ChangeListener; import org.biojava.utils.ChangeType;
import java.util.Set; import java.util.HashSet;
/** * An implementation of ChangeSupport that maintains strong references * to registered ChangeListeners. This makes it suitable for use with * anonymous ChangeListeners, but introduces the potential for memory * leaks when a large object listens to a long-lived object. */ public class StrongRefChangeSupport extends ChangeSupport { private Set strongRefs;
public StrongRefChangeSupport() { super(); initStrongRefs(); }
public StrongRefChangeSupport(int initialSize) { super(initialSize); initStrongRefs(); }
public StrongRefChangeSupport(int initialSize, int delta) { super(initialSize, delta); initStrongRefs(); }
public StrongRefChangeSupport(Set unchanging) { super(unchanging); initStrongRefs(); }
public StrongRefChangeSupport(Set unchanging, int initialSize, int delta) { super(unchanging, initialSize, delta); initStrongRefs(); }
private void initStrongRefs() { strongRefs = new HashSet(); }
public void addChangeListener(ChangeListener cl, ChangeType ct) { super.addChangeListener(cl, ct); strongRefs.add(new Key(cl, ct)); }
public void removeChangeListener(ChangeListener cl, ChangeType ct) { super.removeChangeListener(cl, ct); strongRefs.remove(new Key(cl, ct)); }
private static class Key { private final ChangeListener cl; private final ChangeType ct; public Key(ChangeListener cl, ChangeType ct) { this.cl = cl; this.ct = ct; }
public boolean equals(Object other) { if (!(other instanceof Key)) return false; Key oKey = (Key) other; return (oKey.cl == this.cl && oKey.ct == this.ct); }
public int hashCode() { return cl.hashCode() + ct.hashCode(); } } }
------ StrongRefChangeSupport.java ------
_______________________________________________ Biojava-l mailing list - [EMAIL PROTECTED] http://biojava.org/mailman/listinfo/biojava-l