Hi Matthew,

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,

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

http://www.biojava.org/pipermail/biojava-l/2000-December/000578.html).

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

Reply via email to