ca.odell.glazedlists.impl.WeakReferenceProxy Maven / Gradle / Ivy
Show all versions of glazedlists_java15 Show documentation
/* Glazed Lists (c) 2003-2006 */
/* http://publicobject.com/glazedlists/ publicobject.com,*/
/* O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.impl;
// the core Glazed Lists package
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
import java.lang.ref.WeakReference;
/**
* This class is a proxy to another ListEventListener that may go out of scope
* without explicitly removing itself from the source list's set of listeners.
*
* WeakReferenceProxy exists to solve a garbage collection problem. Suppose
* there exists an EventList L and with an iterator I. I
* must listen to L for change events in order to remain consistent.
* Therefore I will register itself as a listener to L. When
* I goes out of scope (as they typically do), it will remain registered
* as a listener of L. This prevents I from ever being garbage
* collected! But I can never used again. Because iterators are expected
* to be used very frequently, this will cause an unacceptable memory leak.
*
*
This problem is solved by WeakReferenceProxy. Instead of adding I
* as a direct listener of L, add a proxy instead. The proxy will retain
* a WeakReference
to I and forward events to I as
* long as it is reachable. When I is no longer reachable, the proxy
* will remove itself from the list of listeners for L and all garbage
* is available for collection.
*
*
Specifically, the proxy stops listening to L the
* next time any of the following occurs:
*
*
* - another ListEventListener is registered with the same EventList
*
- another ListEventListener is deregistered with the same EventList
*
- another ListEvent is broadcast for the same EventList
*
*
* @see java.lang.ref.WeakReference
* @see Bug 21
*
* @author Jesse Wilson
* @author James Lemieux
*/
public final class WeakReferenceProxy implements ListEventListener {
/** a weak reference the target ListEventListener */
private final WeakReference> proxyTargetReference;
/** the list to remove this listener from when done */
private EventList source;
/**
* Creates a new WeakReferenceProxy that listens for events from the
* specified list and forwards them to the specified listener.
*/
public WeakReferenceProxy(EventList source, ListEventListener proxyTarget) {
if (source == null)
throw new IllegalArgumentException("source may not be null");
if (proxyTarget == null)
throw new IllegalArgumentException("proxyTarget may not be null");
this.source = source;
this.proxyTargetReference = new WeakReference>(proxyTarget);
}
/**
* Accepts notification for the changes and forwards them to the proxy
* target if it has not yet been garbage collected.
*/
public void listChanged(ListEvent listChanges) {
// if this listener has already been cleaned up, ignore ListEvents
if (source == null) return;
// fetch the underlying ListEventListener
final ListEventListener proxyTarget = getReferent();
// test to see if the underlying ListEventListener still exists
if (proxyTarget == null) {
// it doesn't so clean it up
source.removeListEventListener(this);
dispose();
} else {
// it does, so notify it of the ListEvent
proxyTarget.listChanged(listChanges);
}
}
/**
* Returns the underlying ListEventListener or null
if it has
* been garbage collected.
*/
public ListEventListener getReferent() {
return proxyTargetReference.get();
}
/**
* A callback to notify this WeakReferenceProxy that it has been
* unregistered from the EventList to which it was listening. The
* WeakReferenceProxy responds by cleaning up internal references to the
* EventList and ensuring that any future ListEvents it receives are
* ignored.
*/
public void dispose() {
source = null;
}
}