Skip to content

Commit

Permalink
Optimized Signal to not clone the listeners array on dispatch().
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Penner committed Feb 10, 2010
1 parent 35c3b97 commit 27880b7
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 6 deletions.
16 changes: 11 additions & 5 deletions src/org/osflash/signals/Signal.as
Expand Up @@ -18,6 +18,7 @@ package org.osflash.signals
protected var _valueClasses:Array; // of Class
protected var listeners:Array; // of Function
protected var onceListeners:Dictionary; // of Function
protected var dispatching:Boolean = false;;

/**
* Creates a Signal instance to dispatch value objects.
Expand Down Expand Up @@ -73,14 +74,15 @@ package org.osflash.signals
{
var index:int = listeners.indexOf(listener);
if (index == -1) return;
if (dispatching) listeners = listeners.slice();
listeners.splice(index, 1);
delete onceListeners[listener];
}

/** @inheritDoc */
public function removeAll():void
{
listeners.length = 0;
listeners = [];
onceListeners = new Dictionary();
}

Expand All @@ -104,35 +106,37 @@ package org.osflash.signals

if (!listeners.length) return;

dispatching = true;

//TODO: investigate performance of various approaches
//// Call listeners.
var listener:Function;
switch (valueObjects.length)
{
case 0:
// Clone listeners array because add/remove may occur during the dispatch.
for each (listener in listeners.slice())
for each (listener in listeners)
{
if (onceListeners[listener]) remove(listener);
listener();
}
break;

case 1:
for each (listener in listeners.slice())
for each (listener in listeners)
{
if (onceListeners[listener]) remove(listener);
listener(valueObjects[0]);
}
break;

default:
for each (listener in listeners.slice())
for each (listener in listeners)
{
if (onceListeners[listener]) remove(listener);
listener.apply(null, valueObjects);
}
}
dispatching = false;
}

protected function setValueClasses(valueClasses:Array):void
Expand Down Expand Up @@ -165,6 +169,8 @@ package org.osflash.signals
return;
}

if (dispatching) listeners = listeners.slice();

// Don't add the same listener twice.
if (listeners.indexOf(listener) >= 0)
return;
Expand Down
15 changes: 14 additions & 1 deletion tests/org/osflash/signals/SignalTest.as
Expand Up @@ -166,9 +166,10 @@ package org.osflash.signals
}
//////
[Test]
public function add_2_listeners_first_listener_removes_itself_should_call_2nd_listener():void
public function dispatch_2_listeners_1st_listener_removes_itself_then_2nd_listener_is_still_called():void
{
completed.add(selfRemover);
// addAsync verifies the second listener is called
completed.add(addAsync(newEmptyHandler(), 10));
completed.dispatch();
}
Expand All @@ -177,6 +178,18 @@ package org.osflash.signals
{
completed.remove(selfRemover);
}
//////
[Test]
public function dispatch_2_listeners_1st_listener_removes_all_then_2nd_listener_is_still_called():void
{
completed.add(addAsync(allRemover, 10));
completed.add(addAsync(newEmptyHandler(), 10));
completed.dispatch();
}

private function allRemover():void
{
completed.removeAll();
}
}
}

0 comments on commit 27880b7

Please sign in to comment.