Allow adding/removing listeners by weak reference so as not to prevent
garbage collection. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6076 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
package com.threerings.presents.dobj;
|
package com.threerings.presents.dobj;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -200,6 +201,31 @@ public class DObject
|
|||||||
_deathWish = deathWish;
|
_deathWish = deathWish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a listener using a weak reference that will not prevent the listener from being
|
||||||
|
* garbage-collected.
|
||||||
|
*/
|
||||||
|
public void addWeakListener (ChangeListener listener)
|
||||||
|
{
|
||||||
|
if (getWeakListenerIndex(listener) == -1) {
|
||||||
|
_listeners = ListUtil.add(_listeners, new WeakListenerWrapper(listener));
|
||||||
|
} else {
|
||||||
|
log.warning("Refusing repeat weak listener registration",
|
||||||
|
"dobj", which(), "list", listener, new Exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a weak event listener.
|
||||||
|
*/
|
||||||
|
public void removeWeakListener (ChangeListener listener)
|
||||||
|
{
|
||||||
|
int idx = getWeakListenerIndex(listener);
|
||||||
|
if (idx != -1) {
|
||||||
|
_listeners[idx] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener to this object. The listener will be notified when any events are
|
* Adds an event listener to this object. The listener will be notified when any events are
|
||||||
* dispatched on this object that match their particular listener interface.
|
* dispatched on this object that match their particular listener interface.
|
||||||
@@ -975,6 +1001,58 @@ public class DObject
|
|||||||
return null; // key not found.
|
return null; // key not found.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the identified wrapped weak listener, or -1 if not found.
|
||||||
|
*/
|
||||||
|
protected int getWeakListenerIndex (ChangeListener listener)
|
||||||
|
{
|
||||||
|
if (_listeners == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (int ii = 0, ll = _listeners.length; ii < ll; ii++) {
|
||||||
|
Object olistener = _listeners[ii];
|
||||||
|
if (!(olistener instanceof WeakListenerWrapper)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (((WeakListenerWrapper)olistener).ref.get() == listener) {
|
||||||
|
return ii;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener that wraps a weak reference to another listener.
|
||||||
|
*/
|
||||||
|
protected class WeakListenerWrapper
|
||||||
|
implements EventListener
|
||||||
|
{
|
||||||
|
/** The weak reference to our underlying listener. */
|
||||||
|
public final WeakReference<ChangeListener> ref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new weak listener wrapper.
|
||||||
|
*/
|
||||||
|
public WeakListenerWrapper (ChangeListener listener)
|
||||||
|
{
|
||||||
|
ref = new WeakReference<ChangeListener>(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface EventListener
|
||||||
|
public void eventReceived (DEvent event)
|
||||||
|
{
|
||||||
|
ChangeListener listener = ref.get();
|
||||||
|
if (listener == null) {
|
||||||
|
removeListener(this);
|
||||||
|
} else {
|
||||||
|
event.notifyListener(listener);
|
||||||
|
if (listener instanceof EventListener) {
|
||||||
|
((EventListener)listener).eventReceived(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Our object id. */
|
/** Our object id. */
|
||||||
protected int _oid;
|
protected int _oid;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user