Found nefarious bug (when it bit me, of course).

If a listener was removed during event dispatch, the size of the list
was shrinking and putting the kibosh on listeners at the end of the list.
(The Java side avoids this due to the different way arrays work.)
- Changed the listener and subscriber lists to simple arrays, and make
  a copy prior to dispatch so that we don't miss anybody!


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4467 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2006-12-06 02:48:53 +00:00
parent 2fbd049185
commit e15d6d31d1
+19 -16
View File
@@ -2,8 +2,6 @@ package com.threerings.presents.dobj {
import flash.events.EventDispatcher;
import mx.collections.ArrayCollection;
import com.threerings.util.ClassUtil;
import com.threerings.util.StringBuilder;
@@ -29,10 +27,10 @@ public class DObject // extends EventDispatcher
public function addSubscriber (sub :Subscriber) :void
{
if (_subscribers == null) {
_subscribers = new ArrayCollection();
_subscribers = [ ];
}
if (!_subscribers.contains(sub)) {
_subscribers.addItem(sub);
if (_subscribers.indexOf(sub) == -1) {
_subscribers.push(sub);
}
}
@@ -41,9 +39,9 @@ public class DObject // extends EventDispatcher
if (_subscribers == null) {
return;
}
var dex :int = _subscribers.getItemIndex(sub);
var dex :int = _subscribers.indexOf(sub);
if (dex != -1) {
_subscribers.removeItemAt(dex);
_subscribers.splice(dex, 1);
if (_subscribers.length == 0) {
_omgr.removedLastSubscriber(this, _deathWish);
}
@@ -58,23 +56,23 @@ public class DObject // extends EventDispatcher
public function addListener (listener :ChangeListener) :void
{
if (_listeners == null) {
_listeners = new ArrayCollection();
_listeners = [ ];
} else if (_listeners.contains(listener)) {
} else if (_listeners.indexOf(listener) != -1) {
log.warning("Refusing repeat listener registration " +
"[dobj=" + which() + ", list=" + listener + "].");
log.logStackTrace(new Error());
return;
}
_listeners.addItem(listener);
_listeners.push(listener);
}
public function removeListener (listener :ChangeListener) :void
{
if (_listeners != null) {
var dex :int = _listeners.getItemIndex(listener);
var dex :int = _listeners.indexOf(listener);
if (dex != -1) {
_listeners.removeItemAt(dex);
_listeners.splice(dex, 1);
}
}
}
@@ -85,8 +83,13 @@ public class DObject // extends EventDispatcher
return;
}
for (var ii :int = 0; ii < _listeners.length; ii++) {
var listener :Object = _listeners.getItemAt(ii);
var listenersCopy :Array = _listeners.concat();
for each (var listener :Object in listenersCopy) {
// make sure the listener is still a listener
// and hasn't been removed while dispatching to another listener..
if (_listeners.indexOf(listener) == -1) {
continue;
}
try {
event.friendNotifyListener(listener);
@@ -282,9 +285,9 @@ public class DObject // extends EventDispatcher
protected var _omgr :DObjectManager;
/** Our event listeners. */
protected var _listeners :ArrayCollection;
protected var _listeners :Array;
protected var _subscribers :ArrayCollection;
protected var _subscribers :Array;
protected var _deathWish :Boolean = false;
}