この問題は先日のアップデートでパッチがあたりました。
最新のtrunkのThreadではこの問題は起きないようです。
前回の続きです。。
前回のパッチをSparkProjectにコミットしたところ、nobuさんから割り込み後もイベントを受け取ってしまうという問題を指摘してもらえました。この事についてちょっと考えてみます。
おそらくThreadの仕様的には割り込み後の振る舞いというのはThreadのサブクラスにまかされていて、スーパークラスであるThreadでは特に定義されていないんだと思います。ところがこれまで見てきたように、割り込みとイベント配信が続けて行われた場合、サブクラスでは、タイミングによっては自分が割り込まれたかどうか知る事ができないという状況が発生します。
前回のパッチではこれをふまえ、Threadの仕様を「イベント待ちの時に割り込まれたThreadはイベントを処理しない(イベントハンドラを実行しない)」ように変更しています。ただ、2つあるテストのうち、後者のテストである[割り込み]〜[イベント配信]では割り込み後も1度イベントを受け取ってしまっていました。これは割り込み後実際に割り込みハンドラが割り当てられるまでに1サイクルのインターバルがあるためその隙に飛び込んできたイベントを受け取ってしまっていたためです。
まず、テストの、割り込まれた後のイベントチェック部分がおかしかったので修正します。
//300mSec後にテスト
setTimeout(
async(
function():void
{
//InterruptHandlerTestThreadの割り込みハンドラが実行されたかどうかテスト
//assertEquals("interrupt event interrutHandler finalize ", Static.log);
assertEquals("interrupt interrutHandler finalize ", Static.log);
テストを実行します。
予想通り割り込まれた後もイベントを受け取ってしまうためテストに失敗します。
..E Time: 0.66 There was 1 failure: 1) inturruptHandlerExecution2(org.libspark.thread::InterruptHandlerTest) Error: expected:<interrupt []interrutHandler fina...> but was:<interrupt [event ]interrutHandler fina...>
そこで、Threadのコードにもう一つだけ処理を加えこの問題を回避する事にします。
ここではイベントを受け取ったとき割り込みが予約されていれば何もしないようにしています。
private function eventHandler(e:Event, handler:EventHandler):void
{
//割り込みが予約されていれば何もしない
var me:Thread = this;
if(
_reserveInterrupt.some(
function(thread : Thread, ...param):Boolean
{
return thread == me;
}
)
) return;
//実行関数が割り込みハンドラならイベントハンドラをリセットして何もしない
テストを実行すると無事にパスします。
CYCLE 0--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event (RUNNABLE
CYCLE 1--------------
@ internalExecute (WAITING
〜〜 省略 〜〜
CYCLE 8--------------
@ internalExecute (WAITING
[DISPATCH]
@ eventHandler (WAITING
@ internalExecute (RUNNABLE
# received event (RUNNABLE
!!!!!!!!!!!!!!!!!!! CALL INTERRUPT !!!!!!!!!!!!!!!!!!!
@ interrupt (RUNNABLE
CYCLE 9--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event (RUNNABLE
@ internalExecute (WAITING
[DISPATCH]
@ eventHandler (RUNNABLE
CYCLE 10--------------
@ internalExecute (RUNNABLE
# INTERRUPTED
CYCLE 11--------------
@ internalExecute (TERMINATING
# finalize() (TERMINATING
CYCLE 0--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event (RUNNABLE
CYCLE 1--------------
@ internalExecute (WAITING
〜〜 省略 〜〜
CYCLE 6--------------
@ internalExecute (WAITING
!!!!!!!!!!!!!!!!!!! CALL INTERRUPT !!!!!!!!!!!!!!!!!!!
@ interrupt (WAITING
[DISPATCH]
@ eventHandler (WAITING
CYCLE 7--------------
@ internalExecute (WAITING
@ internalExecute (WAITING
[DISPATCH]
@ eventHandler (RUNNABLE
CYCLE 8--------------
@ internalExecute (RUNNABLE
# INTERRUPTED
CYCLE 9--------------
@ internalExecute (TERMINATING
# finalize() (TERMINATING
..
Time: 0.654
OK (2 tests)
シーケンス図です。

今回の修正をもう一度SparkProjectにコミットしました。