« Threadの割り込みハンドラが失敗することがある(その2) | メイン

Threadの割り込みハンドラが失敗することがある(その3)

この問題は先日のアップデートでパッチがあたりました。

最新の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)

 

シーケンス図です。

fixed


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

トラックバック

このエントリーのトラックバックURL:
http://www.imajuk.com/mt4/mt-tb.cgi/49

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

About

2010年1月25日 12:29に投稿されたエントリーのページです。

ひとつ前の投稿は「Threadの割り込みハンドラが失敗することがある(その2)」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。