<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>www.imajuk.swf</title>
	<atom:link href="http://www.imajuk.com/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://www.imajuk.com/blog</link>
	<description>actionscript</description>
	<lastBuildDate>Mon, 25 Jul 2011 04:36:18 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>Threadの割り込みハンドラが失敗することがある（その3）</title>
		<link>http://www.imajuk.com/blog/archives/2010/01/thread3.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=thread3</link>
		<comments>http://www.imajuk.com/blog/archives/2010/01/thread3.html#comments</comments>
		<pubDate>Mon, 25 Jan 2010 03:29:42 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript3]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=58</guid>
		<description><![CDATA[この問題は先日のアップデートでパッチがあたりました。 最新のtrunkのThreadではこの問題は起きないようです。 http://www.libspark.org/ticket/117#comment:7 前回の続きで &#8230; <a href="http://www.imajuk.com/blog/archives/2010/01/thread3.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><b><font color="#FF0000">この問題は先日のアップデートでパッチがあたりました。</font></b></p>
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.75em; margin-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 1em; "><b><font color="#FF0000">最新のtrunkのThreadではこの問題は起きないようです。</font></b></p>
<div><a href="http://www.libspark.org/ticket/117#comment:7">http://www.libspark.org/ticket/117#comment:7</a></div>
<hr />
<p><a href="http://www.imajuk.com/blog/archives/2010/01/thread2.html">前回</a>の続きです。。</p>
<p>前回のパッチをSparkProjectにコミットしたところ、<a href="http://www.libspark.org/ticket/117">nobuさんから割り込み後もイベントを受け取ってしまうという問題を指摘してもらえました。</a>この事についてちょっと考えてみます。</p>
<p></p>
<p>おそらくThreadの仕様的には<strong>割り込み後の振る舞いというのはThreadのサブクラスにまかされていて、スーパークラスであるThreadでは特に定義されていない</strong>んだと思います。ところがこれまで見てきたように、割り込みとイベント配信が続けて行われた場合、<strong>サブクラスでは、タイミングによっては自分が割り込まれたかどうか知る事ができない</strong>という状況が発生します。</p>
<p></p>
<p>前回のパッチではこれをふまえ、<strong>Threadの仕様を「イベント待ちの時に割り込まれたThreadはイベントを処理しない（イベントハンドラを実行しない）」ように変更しています。</strong>ただ、2つあるテストのうち、後者のテストである[割り込み]〜[イベント配信]では割り込み後も1度イベントを受け取ってしまっていました。これは割り込み後実際に割り込みハンドラが割り当てられるまでに1サイクルのインターバルがあるためその隙に飛び込んできたイベントを受け取ってしまっていたためです。</p>
<p>まず、テストの、割り込まれた後のイベントチェック部分がおかしかったので修正します。
</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8">//300mSec<span style="font: 11.0px Hiragino Kaku Gothic ProN">後にテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6e6432">setTimeout<span style="color: #000000">(</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #6e6432">async</span>(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span>function<span style="color: #000000">():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//InterruptHandlerTestThread<span style="font: 11.0px Hiragino Kaku Gothic ProN">の割り込みハンドラが実行されたかどうかテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8; background-color:#FDE;"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//assertEquals(&#8220;interrupt<span style="color: #000000"> </span>event<span style="color: #000000"> </span>interrutHandler<span style="color: #000000"> </span>finalize<span style="color: #000000"> </span>&#8220;,<span style="color: #000000"> </span>Static.log);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995; background-color:#FDE;"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">assertEquals</span><span style="color: #000000">(</span>&#8220;interrupt interrutHandler finalize &#8220;<span style="color: #000000">, </span><span style="color: #505000">Static</span><span style="color: #000000">.</span><span style="color: #00009b">log</span><span style="color: #000000">);</span></p>
</div>
<p></p>
<p>テストを実行します。<br />
予想通り<strong>割り込まれた後もイベントを受け取ってしまうためテストに失敗</strong>します。</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">
..E
Time: 0.66
There was 1 failure:
1) inturruptHandlerExecution2(org.libspark.thread::InterruptHandlerTest)
Error: expected:&lt;interrupt []interrutHandler fina...&gt; but was:&lt;interrupt [event ]interrutHandler fina...&gt;</font></pre>
<p></p>
<p>そこで、Threadのコードにもう一つだけ処理を加えこの問題を回避する事にします。<br />
ここでは<strong>イベントを受け取ったとき割り込みが予約されていれば何もしない</strong>ようにしています。</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">private</span> <span style="color: #141195">function</span> eventHandler(e:<span style="color: #505000">Event</span>, handler:<span style="color: #505000">EventHandler</span>):<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8; background-color:#FDE;"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>割り込みが予約されていれば何もしない</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; <span style="color: #141195">var</span> me:<span style="color: #505000">Thread</span> = <span style="color: #505000">this</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; <span style="color: #141195">if</span>(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b; background-color:#FDE;"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span>_reserveInterrupt<span style="color: #000000">.some(</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">function</span>(thread : <span style="color: #505000">Thread</span>, &#8230;param):<span style="color: #505000">Boolean</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">return</span> thread == me;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; &nbsp; &nbsp; )</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE;">&nbsp; &nbsp; ) <span style="color: #141195">return</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>実行関数が割り込みハンドラならイベントハンドラをリセットして何もしない</p>
</div>
<p>&nbsp;</p>
<p>テストを実行すると無事にパスします。</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">
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)
</font></pre>
<p>&nbsp;</p>
<p>シーケンス図です。</p>
<p><img src="http://img.skitch.com/20100125-ns58x1t8f92q3cs98r1s5y2msn.jpg" alt="fixed" /></p>
<p></p>
<p>今回の修正をもう一度SparkProjectにコミットしました。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2010/01/thread3.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Threadの割り込みハンドラが失敗することがある（その2）</title>
		<link>http://www.imajuk.com/blog/archives/2010/01/thread2.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=thread2</link>
		<comments>http://www.imajuk.com/blog/archives/2010/01/thread2.html#comments</comments>
		<pubDate>Wed, 20 Jan 2010 11:29:47 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript3]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=57</guid>
		<description><![CDATA[この問題は先日のアップデートでパッチがあたりました。 最新のtrunkのThreadではこの問題は起きないようです。 http://www.libspark.org/ticket/117#comment:7 前回の続きで &#8230; <a href="http://www.imajuk.com/blog/archives/2010/01/thread2.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><b><font color="#FF0000">この問題は先日のアップデートでパッチがあたりました。</font></b></p>
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.75em; margin-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 1em; "><b><font color="#FF0000">最新のtrunkのThreadではこの問題は起きないようです。</font></b></p>
<div><a href="http://www.libspark.org/ticket/117#comment:7">http://www.libspark.org/ticket/117#comment:7</a></div>
<hr />
<p><a href="http://www.imajuk.com/blog/archives/2010/01/thread1.html">前回</a>の続きです。</p>
<p>問題をもう一度整理してみます。<br />
問題点は2つあります。</p>
<p>1・	ステートがWAITINGの状態でイベントハンドラが実行され即座にRUNNABLEになる。<br />
このステートが再びWAITINGになるのは次のサイクル。<br />
つまりサイクルとサイクルの間でステータスがRUNNABLEになってしまう事があり、このとき割り込まれると割り込みハンドラは失敗する。</p>
<p>2・	WAITINGの状態で割り込まれると割り込みハンドラは次の実行関数として正しく設定される。<br />しかしこの実行関数が次のサイクルで実行される前にイベントを受け取ってしまうとイベントハンドラ内に書かれた処理内容によっては実行関数を上書きしてしまう。</p>
<p></p>
<p>まず2から取りかかります。</p>
<p></p>
<p>割り込みハンドラとイベントハンドラは排他的な関係のように思えます。<br />
なぜならイベント待ちをしているThreadに割り込みをかけるという事は、もうイベントを受け取りたくないという事だからです。<br />
これをヒントに次のような方針でパッチを当てます。</p>
<p><strong>「イベントハンドラがイベントを受け取ったとき、実行関数が割り込みハンドラであれば（このThreadは割り込まれたので）、そのイベントは無視する。」</strong></p>
<p>以下がイベントハンドラの部分のパッチコードです。（1026行目）</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">private</span> <span style="color: #141195">function</span> eventHandler(e:<span style="color: #505000">Event</span>, handler:<span style="color: #505000">EventHandler</span>):<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8; background-color:#FDE"><span style="font: 11.0px Monaco; color: #000000;"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="font: 11.0px Monaco;">//</span>実行関数が割り込みハンドラならイベントハンドラをリセットして何もしない</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b; background-color:#FDE"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="color: #141195">if</span><span style="color: #000000"> (</span>_interruptedHandler<span style="color: #000000"> != </span><span style="color: #05870f">null</span><span style="color: #000000"> &amp;&amp; </span>_runHandler<span style="color: #000000"> == </span>_interruptedHandler<span style="color: #000000">)<span class="Apple-converted-space">&nbsp;</span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; </span>{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8; background-color:#FDE"><span style="font: 11.0px Monaco; color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span></span><span style="font: 11.0px Monaco">//</span> イベントハンドラをリセット</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span>resetEventHandlers();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #141195">return</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; </span>}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8;"><span style="font: 11.0px Monaco; color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="font: 11.0px Monaco">//</span><span style="font: 11.0px Monaco; color: #000000"> </span>既にイベントが起こっていれば何もしない</p>
</div>
<p>&nbsp;</p>
<p>つぎに1のほうですが以下のような方針でパッチを当てる事にします。</p>
<p>「<strong>ステータスがRUNNABLEになる瞬間を避けて、WAITINGの時に確実に割り込みの内部処理を実行する</strong>」</p>
<p>割り込み処理はinterrup()メソッド内に書かれています。interrupt()が呼ばれた時にすぐにこの処理を実行してしまわないで、ステータスがWAITINGの時にこの処理を行いたい。ではステータスが確実にWAITINGなのはどんなタイミングでしょうか？<strong>サイクルが終わった直後なら確実にWAITINGのはず</strong>です。サイクルが終わった直後に、イベントに先を越されないようすぐに割り込み処理を実行するようにします。</p>
<p>割り込み処理の遅延をするために、キュー用の変数を用意します。（138行目）</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195">public<span style="color: #000000"> </span>class<span style="color: #000000"> Thread </span>extends<span style="color: #000000"> </span><span style="color: #505000">Monitor</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span>private<span style="color: #000000"> </span>static<span style="color: #000000"> </span>var<span style="color: #000000"> </span><span style="color: #00009b">_executor</span><span style="color: #000000">:</span><span style="color: #505000">IThreadExecutor</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span>private<span style="color: #000000"> </span>static<span style="color: #000000"> </span>var<span style="color: #000000"> </span><span style="color: #00009b">_threadIndex</span><span style="color: #000000">:</span><span style="color: #505000">uint</span><span style="color: #000000"> = 0;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span>private<span style="color: #000000"> </span>static<span style="color: #000000"> </span>var<span style="color: #000000"> </span><span style="color: #00009b">_currentThread</span><span style="color: #000000">:</span><span style="color: #505000">Thread</span><span style="color: #000000"> = </span><span style="color: #05870f">null</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span>private<span style="color: #000000"> </span>static<span style="color: #000000"> </span>var<span style="color: #000000"> </span><span style="color: #00009b">_toplevelThreads</span><span style="color: #000000">:</span><span style="color: #505000">Array</span><span style="color: #000000"> = [];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="color: #141195">private</span><span style="color: #000000"> </span><span style="color: #141195">static</span><span style="color: #000000"> </span><span style="color: #141195">var</span><span style="color: #000000"> </span>_uncaughtErrorHandler<span style="color: #000000">:</span><span style="color: #505000">Function</span><span style="color: #000000"> = </span><span style="color: #05870f">null</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="color: #141195">private</span><span style="color: #000000"> </span><span style="color: #141195">static</span><span style="color: #000000"> </span><span style="color: #141195">var</span><span style="color: #000000"> </span>_defaultErrorHandlers<span style="color: #000000">:</span><span style="color: #505000">Dictionary</span><span style="color: #000000"> = </span><span style="color: #05870f">null</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b; background-color:#FDE"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="color: #141195">private</span><span style="color: #000000"> </span><span style="color: #141195">static</span><span style="color: #000000"> </span><span style="color: #141195">var</span><span style="color: #000000"> </span>_reserveInterrupt<span style="color: #000000"> : </span><span style="color: #505000">Array</span><span style="color: #000000"> = [];</span>
</p>
<p>
</div>
<p>&nbsp;</p>
<p>interrupt()が呼び出された時、呼び出されたThreadインスタンスをこのキューに格納します。<br />
また実際の割り込み処理の部分を、新しいメソッドinternalInterrupt()を作って丸ごと移動します。<br />
以下がinterrupt()部分のパッチコードです。（791行目）</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195">public<span style="color: #000000"> </span>function<span style="color: #000000"> interrupt():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8; background-color:#FDE"><span style="font: 11.0px Monaco; color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="font: 11.0px Monaco">//</span>割り込みを予約し、次のサイクルの最後に実行する</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b; background-color:#FDE"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span>_reserveInterrupt<span style="color: #000000">.push(</span><span style="color: #505000">this</span><span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px; background-color:#FDE"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span style="color: #7f0055">internal</span> <span style="color: #141195">function</span> internalInterrupt():<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="color: #141195">if</span><span style="color: #000000"> (</span>_state<span style="color: #000000"> == </span><span style="color: #505000">ThreadState</span><span style="color: #000000">.</span>WAITING<span style="color: #000000"> || </span>_state<span style="color: #000000"> == </span><span style="color: #505000">ThreadState</span><span style="color: #000000">.</span>TIMED_WAITING<span style="color: #000000">) {</span></p>
</div>
<p>&nbsp;</p>
<p>最後に、サイクルの最後に割り込み処理を実行するように、<strong>executeAllThreads()メソッドの最後に</strong>以下のコードを追加します。（350行目）</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195">public<span style="color: #000000"> </span>static<span style="color: #000000"> </span>function<span style="color: #000000"> executeAllThreads():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="font: 11.0px Monaco">//</span><span style="font: 11.0px Monaco; color: #000000"> </span>全てのトップレベルスレッドを呼び出す</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"><span class="Apple-converted-space">&nbsp;&nbsp; &nbsp;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8">〜〜　省略　〜〜</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"><span class="Apple-converted-space">&nbsp;&nbsp; &nbsp;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8; background-color:#FDE"><span style="font: 11.0px Monaco; color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span><span style="font: 11.0px Monaco">//</span>予約された割り込みハンドラがあれば実行する</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b; background-color:#FDE"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span>_reserveInterrupt<span style="color: #000000">.forEach(</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #141195">function</span>(thread:<span style="color: #505000">Thread</span>, &#8230;param):<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span>{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>thread.internalInterrupt();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; &nbsp; &nbsp; </span>}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; background-color:#FDE"><span class="Apple-converted-space">&nbsp; &nbsp; </span>);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b; background-color:#FDE"><span style="color: #000000"><span class="Apple-converted-space">&nbsp; &nbsp; </span></span>_reserveInterrupt<span style="color: #000000"> = [];</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
</div>
<p>&nbsp;</p>
<p>テストを実行すると無事にテストをパスします</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;
font-size:smaller;
color:#141195">CYCLE 0--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event  (RUNNABLE
〜〜　省略　〜〜
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
[DISPATCH]
@ eventHandler  (RUNNABLE
CYCLE 10--------------
@ internalExecute (RUNNABLE
# INTERRUPTED
CYCLE 11--------------
@ internalExecute (TERMINATING
# finalize() (TERMINATING
CYCLE 0--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event  (RUNNABLE
〜〜　省略　〜〜
CYCLE 6--------------
@ internalExecute (WAITING
!!!!!!!!!!!!!!!!!!! CALL INTERRUPT !!!!!!!!!!!!!!!!!!!
@ interrupt  (WAITING
[DISPATCH]
@ eventHandler  (WAITING
@ internalExecute (RUNNABLE
# received event (RUNNABLE
CYCLE 7--------------　（※このサイクルで割り込みハンドラが割り当てられる）
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event  (RUNNABLE
[DISPATCH]
@ eventHandler  (RUNNABLE
CYCLE 8--------------
@ internalExecute (RUNNABLE
# INTERRUPTED
CYCLE 9--------------
@ internalExecute (TERMINATING
# finalize() (TERMINATING
..
Time: 0.659
OK (2 tests)</pre>
<p></p>
<p></p>
<p>シーケンス図です</p>
<p><img src="http://img.skitch.com/20100120-qc7hn1ais13frg1ra5sks3a22k.jpg" alt="fixed the problem" /></p>
<hr />
<p>今回のテストと合わせて既存のすべてのテストをパスしたので、このパッチを当てる事で大きな問題は多分起きないんじゃないかと思いますが、何か問題が起きるようであれば教えてください。オフィシャルなパッチじゃないのでクレームはSparkProject<b>ではなく</b><a href="mailto:imajuk@mac.com">imajuk@mac.com</a>まで</p>
<p>追記：sparkProjectのThreadのbranchesにcommitしました。http://www.libspark.org/svn/as3/Thread/branches/imajuk</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2010/01/thread2.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Threadの割り込みハンドラが失敗することがある（その1）</title>
		<link>http://www.imajuk.com/blog/archives/2010/01/thread1.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=thread1</link>
		<comments>http://www.imajuk.com/blog/archives/2010/01/thread1.html#comments</comments>
		<pubDate>Wed, 20 Jan 2010 06:37:20 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript3]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=56</guid>
		<description><![CDATA[［追記］この問題は先日のアップデートでパッチがあたりました。 最新のtrunkのThreadではこの問題は起きないようです。 http://www.libspark.org/ticket/117#comment:7 Th &#8230; <a href="http://www.imajuk.com/blog/archives/2010/01/thread1.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><b><font color="#FF0000">［追記］この問題は先日のアップデートでパッチがあたりました。</font></b></p>
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.75em; margin-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 1em; "><b><font color="#FF0000">最新のtrunkのThreadではこの問題は起きないようです。</font></b></p>
<div><a href="http://www.libspark.org/ticket/117#comment:7">http://www.libspark.org/ticket/117#comment:7</a></div>
<hr />
<p>Threadを使っているとある問題に気づく事があります。<br />
それは「<strong>イベントをリスンするThreadでinterrupt()を呼び出した際に割り込みハンドラが実行されないことがある</strong>」問題です。<br />
event()を実行してイベントのリスンを開始したThreadは待機状態となり、その状態でinterrupt()を実行すると割り当てられた割り込みハンドラが実行されます。が、<strong>場合によっては期待する割り込みハンドラが実行されない事がある</strong>のです。</p>
<p>上記の問題は、サイクルとサイクルの狭間、つまり一つの<strong>Threadの実行関数が終わり次のThreadの実行関数が始まるまでの間に、イベントハンドラとinterrupt()の両方が実行された時</strong>におこります。</p>
<p>（※ここでいうサイクルとはThread.initialize()で渡すIThreadExecutorの実装によって定義されるThreadの実行の単位のことです。例えばEnterFrameThreadExecutorはユーザが定義したフレームレート、30fpsなら1/30秒に一回Threadが実行され、IntervalThreadExecutorならIntervalThreadExecutorのコンストラクタに渡したインターバルで一回Threadが実行されます。）
</p>
<p>この問題に気づく典型的な例は、マウスクリックに反応するようにイベントをリスンしているThreadをinterrupt()するケースやステージのリサイズを監視するThreadをinterrupt()するケースなど、<strong>短い間隔でイベントをキャッチするThreadに割り込むケース</strong>です。<br />
（参考：<a href="http://wonderfl.net/code/d4b2d19f61f08747bb14cae7608a6e225beda31d">Threadの割り込みがうまくいかないことがある</a>）
</p>
<p>このエントリはここから普段ユーザが意識する必要のないThread内部の振る舞いを見ていきます。<br />
<strong>もしこの問題の解決方法だけを知りたい場合は「Threadの割り込みハンドラが失敗することがある（その2）」を見てみてください。</strong></p>
<h4>問題が再現するテストを書く</h4>
<p>さて、この問題が再現するテストを書いてみて何がおきているかを調べてみます。<br />
以下がそのテストコードです。ThreadライブラリのリポジトリにあるtestディレクトリにTestSuiteが用意されているので、ここに今回のテストInterruptHandlerTest.asを追加しました。</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Courier"><font class="Apple-style-span" color="#141195"></font></p>
<p><font class="Apple-style-span" color="#141195">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">package</span> org.libspark.thread</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">import</span> flash.utils.setTimeout;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">import</span> flash.display.Sprite;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">import</span> org.libspark.as3unit.after;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">import</span> org.libspark.as3unit.assert.*;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">import</span> org.libspark.as3unit.before;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">import</span> org.libspark.as3unit.test;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>use<span style="color: #000000"> </span>namespace<span style="color: #000000"> </span><span style="color: #995600">test</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>use<span style="color: #000000"> </span>namespace<span style="color: #000000"> </span><span style="color: #995600">before</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>use<span style="color: #000000"> </span>namespace<span style="color: #000000"> </span><span style="color: #995600">after</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #6480c8">/**</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp;&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">*</span><span style="font: 11.0px Monaco; color: #000000"> </span>割り込みハンドラのテスト</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp;&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">*</span><span style="font: 11.0px Monaco; color: #000000"> &nbsp; </span>イベントをリスンする<span style="font: 11.0px Monaco">Thread</span>インスタンスがあり、</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp;&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">*</span><span style="font: 11.0px Monaco; color: #000000"> &nbsp; </span><span style="font: 11.0px Monaco">Thread</span>の実行タイミング間でイベントの配信と割り込みが両方行われた時に</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp;&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">*</span><span style="font: 11.0px Monaco; color: #000000"> &nbsp; </span>割り込みハンドラが正しく実行されるかテスト</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp;&nbsp; &nbsp; <span style="color: #6480c8">*/</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #7f0055">internal</span> <span style="color: #141195">class</span> InterruptHandlerTest <span style="color: #141195">extends</span> <span style="color: #505000">Sprite</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">private</span> <span style="color: #141195">var</span> <span style="color: #00009b">dispatcher</span> : <span style="color: #505000">Dispatcher</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #505000"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #141195">private</span><span style="color: #000000"> </span><span style="color: #141195">var</span><span style="color: #000000"> </span><span style="color: #00009b">thread</span><span style="color: #000000"> : </span>InterruptHandlerTestThread<span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #995600">before</span> <span style="color: #141195">function</span> setup() : <span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #505000"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>Thread<span style="color: #000000">.initialize(</span><span style="color: #141195">new</span><span style="color: #000000"> </span>EnterFrameThreadExecutor<span style="color: #000000">());</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Static</span>.<span style="color: #00009b">log</span> = <span style="color: #930995">&#8220;&#8221;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//<span style="font: 11.0px Hiragino Kaku Gothic ProN">イベント配信オブジェクト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">dispatcher</span> = <span style="color: #141195">new</span> <span style="color: #505000">Dispatcher</span>();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6480c8">//</span><span style="font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8">テスト用</span><span style="color: #6480c8">Thread</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">thread</span> =&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #505000"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #141195">new</span><span style="color: #000000"> </span>InterruptHandlerTestThread<span style="color: #000000">(</span><span style="color: #00009b">dispatcher</span><span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #995600">after</span> <span style="color: #141195">function</span> teardown() : <span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Thread</span>.initialize(<span style="color: #05870f">null</span>);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Static</span>.<span style="color: #00009b">log</span> = <span style="color: #930995">&#8220;&#8221;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>イベント配信直後に割り込みするケースのテスト</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #995600">test</span> <span style="color: #141195">function</span> inturruptHandlerExecution() : <span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//200mSec<span style="font: 11.0px Hiragino Kaku Gothic ProN">後に</span><span style="color: #000000"> </span>[<span style="font: 11.0px Hiragino Kaku Gothic ProN">イベント配信</span>]<span style="color: #000000"> </span>-&gt;<span style="color: #000000"> </span>[<span style="font: 11.0px Hiragino Kaku Gothic ProN">割り込み</span>]</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">setTimeout</span>(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">function</span>():<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6480c8">//Thread</span><span style="font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8">に向けてイベントを配信</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">dispatcher</span>.dispatch();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//Thread<span style="font: 11.0px Hiragino Kaku Gothic ProN">の</span>interrupt()<span style="font: 11.0px Hiragino Kaku Gothic ProN">を呼び出し</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">trace</span><span style="color: #000000">(</span>&#8220;¥n!!!!!!!!!!!!!!!!!!! CALL INTERRUPT !!!!!!!!!!!!!!!!!!!¥n&#8221;<span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">thread</span>.interrupt();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, 200</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//250mSec</span>後にもう一度イベント配信<span style="font: 11.0px Monaco">.</span>このイベントはキャッチしないはず</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">setTimeout</span>(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">function</span>():<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">dispatcher</span>.dispatch();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 250</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//300mSec<span style="font: 11.0px Hiragino Kaku Gothic ProN">後にテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">setTimeout</span>(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">async</span>(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">function</span>():<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//InterruptHandlerTestThread<span style="font: 11.0px Hiragino Kaku Gothic ProN">の割り込みハンドラが実行されたかどうかテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">assertEquals</span><span style="color: #000000">(</span>&#8220;event interrupt interrutHandler finalize &#8220;<span style="color: #000000">, </span><span style="color: #505000">Static</span><span style="color: #000000">.</span><span style="color: #00009b">log</span><span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6480c8">//</span><span style="font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8">割り込み後のステータスをテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">assertEquals</span>(<span style="color: #505000">ThreadState</span>.<span style="color: #00009b">TERMINATED</span>, <span style="color: #00009b">thread</span>.state);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ),&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 300</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//<span style="font: 11.0px Hiragino Kaku Gothic ProN">テスト用</span>Thread<span style="font: 11.0px Hiragino Kaku Gothic ProN">開始</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">thread</span>.start();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">import</span> org.libspark.thread.Thread;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">import</span> flash.events.Event;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">import</span> flash.events.EventDispatcher;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8">//<span style="font: 11.0px Hiragino Kaku Gothic ProN">テスト用</span>Thread</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">class</span> InterruptHandlerTestThread <span style="color: #141195">extends</span> <span style="color: #505000">Thread</span>&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">private</span> <span style="color: #141195">var</span> <span style="color: #00009b">dispatcher</span> : <span style="color: #505000">Dispatcher</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">public</span> <span style="color: #141195">function</span> InterruptHandlerTestThread(dispatcher:<span style="color: #505000">Dispatcher</span>)</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">super</span>();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">this</span>.<span style="color: #00009b">dispatcher</span> = dispatcher;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>override<span style="color: #000000"> </span>public<span style="color: #000000"> </span>function<span style="color: #000000"> interrupt():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Static</span>.<span style="color: #00009b">log</span> += <span style="color: #930995">&#8220;interrupt &#8220;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">super</span>.interrupt();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>override<span style="color: #000000"> </span><span style="color: #7f0055">protected</span><span style="color: #000000"> </span>function<span style="color: #000000"> run() : </span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">trace</span>(<span style="color: #930995">&#8220;&nbsp; &nbsp; # run()&#8221;</span>, printStatus(state));</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; </span>//<span style="font: 11.0px Hiragino Kaku Gothic ProN">割り込みハンドラを生成</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">var</span> interruptHandler : <span style="color: #505000">Function</span> =&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">function</span>():<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">trace</span><span style="color: #000000">(</span>&#8220;&nbsp; &nbsp; # INTERRUPTED¥n&#8221;<span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Static</span>.<span style="color: #00009b">log</span> += <span style="color: #930995">&#8220;interrutHandler &#8220;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>割り込みハンドラを設定</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; interrupted(interruptHandler);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>イベントをキャッチしたら再びイベントをリスンして待機状態へ</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; event(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">dispatcher</span>,</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">InternalEvent</span>.<span style="color: #00009b">COMPLETE</span>,</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">function</span>():<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">trace</span>(<span style="color: #930995">&#8220;&nbsp; &nbsp; # received event&#8221;</span>, printStatus(state));</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Static</span>.<span style="color: #00009b">log</span> += <span style="color: #930995">&#8220;event &#8220;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>イベントを受け取ったら再びイベントをリスン</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; next(run);&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">override</span> <span style="color: #7f0055">protected</span> <span style="color: #141195">function</span> finalize() : <span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Static</span>.<span style="color: #00009b">log</span> += <span style="color: #930995">&#8220;finalize &#8220;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">trace</span>(<span style="color: #930995">&#8220;&nbsp; &nbsp; # finalize()&#8221;</span>, printStatus(state));</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco">//</span>イベント配信オブジェクト</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #505000"><span style="color: #141195">class</span><span style="color: #000000"> Dispatcher </span><span style="color: #141195">extends</span><span style="color: #000000"> </span>EventDispatcher</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>public<span style="color: #000000"> </span>function<span style="color: #000000"> dispatch():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">trace</span><span style="color: #000000">(</span>&#8220;¥n [DISPATCH]¥n&#8221;<span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; dispatchEvent(<span style="color: #141195">new</span> <span style="color: #505000">InternalEvent</span>(<span style="color: #505000">InternalEvent</span>.<span style="color: #00009b">COMPLETE</span>));</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco">//</span>テスト用イベント</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">class</span> InternalEvent <span style="color: #141195">extends</span> <span style="color: #505000">Event</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>public<span style="color: #000000"> </span>static<span style="color: #000000"> </span>const<span style="color: #000000"> </span><span style="color: #00009b">COMPLETE</span><span style="color: #000000"> : </span><span style="color: #505000">String</span><span style="color: #000000"> = </span><span style="color: #930995">&#8220;COMPLETE&#8221;</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">public</span> <span style="color: #141195">function</span> InternalEvent(type : <span style="color: #505000">String</span>)&nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">super</span>(type, <span style="color: #05870f">false</span>, <span style="color: #05870f">false</span>);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">class</span> Static</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; </span>public<span style="color: #000000"> </span>static<span style="color: #000000"> </span>var<span style="color: #000000"> </span><span style="color: #00009b">log</span><span style="color: #000000">:</span><span style="color: #505000">String</span><span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
<p></font>
</p>
</div>
<p></p>
<p>さらに、Thread内の動きを観察するために、org.libspark.thread.Threadとorg.libspark.thread.EnterFrameThreadExecutorにtrace()を仕込みます。</p>
<p><strong>Threadにデバッグ用メソッドを追加</strong></p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco">//Thread</span>のステータスコードを文字列に変換するユーティリティ</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">public</span> <span style="color: #141195">static</span> <span style="color: #141195">function</span> printStatus(s : <span style="color: #505000">int</span>) : <span style="color: #505000">String</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">switch</span>(s)</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">case</span> <span style="color: #505000">ThreadState</span>.<span style="color: #00009b">NEW</span>:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">return</span> <span style="color: #930995">&#8220;(NEW&#8221;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">case</span> <span style="color: #505000">ThreadState</span>.<span style="color: #00009b">RUNNABLE</span>:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">return</span> <span style="color: #930995">&#8220;(RUNNABLE&#8221;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">case</span> <span style="color: #505000">ThreadState</span>.<span style="color: #00009b">TERMINATED</span>:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">return</span> <span style="color: #930995">&#8220;(TERMINATED&#8221;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">case</span> <span style="color: #505000">ThreadState</span>.<span style="color: #00009b">TERMINATING</span>:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">return</span> <span style="color: #930995">&#8220;(TERMINATING&#8221;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #141195">case</span><span style="color: #000000"> </span><span style="color: #505000">ThreadState</span><span style="color: #000000">.</span>TIMED_WAITING<span style="color: #000000">:</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #141195">return</span><span style="color: #000000"> </span>&#8220;(TIMED_WAITING&#8221;<span style="color: #000000">;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">case</span> <span style="color: #505000">ThreadState</span>.<span style="color: #00009b">WAITING</span>:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">return</span> <span style="color: #930995">&#8220;(WAITING&#8221;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">throw</span> <span style="color: #141195">new</span> <span style="color: #505000">Error</span>(s);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
</div>
<h5>Threadの以下のメソッドにtrace()を追加</h5>
<h5>event()メソッド</h5>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">public</span> <span style="color: #141195">static</span> <span style="color: #141195">function</span> event(dispatcher:<span style="color: #505000">IEventDispatcher</span>, type:<span style="color: #505000">String</span>, func:<span style="color: #505000">Function</span>, useCapture:<span style="color: #505000">Boolean</span> = <span style="color: #05870f">false</span>, priority:<span style="color: #505000">int</span> = 0, useWeakReference:<span style="color: #505000">Boolean</span> = <span style="color: #05870f">false</span>):<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432"><b>trace</b></span><b>(</b><span style="color: #930995"><b>&#8220;&nbsp; @ register event &#8220;</b></span><b>, printStatus(getCurrentThread().state));</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getCurrentThread().addEventHandler(dispatcher, type, func, useCapture, priority, useWeakReference);</p>
</div>
<h5>eventHandler()メソッド</h5>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">private</span> <span style="color: #141195">function</span> eventHandler(e:<span style="color: #505000">Event</span>, handler:<span style="color: #505000">EventHandler</span>):<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432"><b>trace</b></span><b>(</b><span style="color: #930995"><b>&#8221; &nbsp;@ eventHandler &#8220;</b></span><b>, printStatus(</b><span style="color: #00009b"><b>_state</b></span><b>));</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>実行関数が割り込みハンドラならイベントハンドラをリセットして何もしない</p>
</div>
<h5>interrupt()メソッド</h5>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195">public<span style="color: #000000"> </span>function<span style="color: #000000"> interrupt():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432"><b>trace</b></span><b>(</b><span style="color: #930995"><b>&#8221; &nbsp;@ interrupt &#8220;</b></span><b>, printStatus(</b><span style="color: #00009b"><b>_state</b></span><b>));</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>割り込みを予約し、次のサイクルの最後に実行する</p>
</div>
<h5>internalExecute()メソッド</h5>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">private</span> <span style="color: #141195">function</span> internalExecute(error:<span style="color: #505000">Object</span>, errorThread:<span style="color: #505000">Thread</span>):<span style="color: #505000">Boolean</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432"><b>trace</b></span><b>(</b><span style="color: #930995"><b>&#8221; &nbsp;@ internalExecute &#8220;</b></span><b> + [printStatus(</b><span style="color: #00009b"><b>_state</b></span><b>)]);</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #00009b"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #141195">if</span><span style="color: #000000"> (</span>_state<span style="color: #000000"> == </span><span style="color: #505000">ThreadState</span><span style="color: #000000">.</span>WAITING<span style="color: #000000"> || </span>_state<span style="color: #000000"> == </span><span style="color: #505000">ThreadState</span><span style="color: #000000">.</span>TIMED_WAITING<span style="color: #000000">) {</span></p>
</div>
<h5>EnterFrameThreadExecutorのenterFrameHandlerにtrace()を仕込みます。（カウンタ用の変数を一つ追加しています）</h5>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
"><font size="-2" color="#141195"></font>
</p>
<p><font class="Apple-style-span" color="#141195">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195"><b>private</b></span><b> </b><span style="color: #141195"><b>var</b></span><b> </b><span style="color: #00009b"><b>time</b></span><b> : </b><span style="color: #505000"><b>int</b></span><b> = 0;</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #141195">private</span> <span style="color: #141195">function</span> enterFrameHandler(e:<span style="color: #505000">Event</span>):<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000"><span class="Apple-tab-span" style="white-space:pre">	</span></span><span style="color: #6e6432"><b>trace</b></span><span style="color: #000000"><b>(</b></span><b>&#8220;¥nCYCLE &#8220;</b><span style="color: #000000"><b> + </b></span><span style="color: #00009b"><b>time</b></span><span style="color: #000000"><b>++ + </b></span><b>&#8220;&#8212;&#8212;&#8212;&#8212;&#8211;&#8221;</b><span style="color: #000000"><b>);</b></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-tab-span" style="white-space:pre">	</span><span style="color: #505000">Thread</span>.executeAllThreads();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
<p></font>
</p>
</div>
<p>これで準備完了。<br />
このテストでは、テスト開始100mSec後にイベント配信とThreadの割り込みを行い、その50mSec後にもう一度イベント配信、最後に200mSec後に割り込みハンドラが実行されたか確認しています。
</p>
<hr />
<h4>テスト</h4>
<p>テストしてみます。<br />
<strong>割り込みハンドラが実行されずにテストは失敗</strong>します。</p>
<p>以下はその出力結果です。</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">CYCLE 0--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event  (RUNNABLE
〜〜　省略　〜〜
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
[DISPATCH]
@ eventHandler  (WAITING
@ internalExecute (RUNNABLE
# received event (RUNNABLE
CYCLE 10--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event  (RUNNABLE
CYCLE 11--------------
@ internalExecute (WAITING</font>
.E
Time: 0.341
<b>There was 1 failure:</b>
1) inturruptHandlerExecution(org.libspark.thread::InterruptHandlerTest)
Error: <b>expected:&lt;event interrupt [interrutHandler finalize] &gt; but was:&lt;event interrupt [event] &gt;</b></pre>
<p>何が起きたか見ていきましょう。</p>
<p>@マークのある行はThread（スーパークラス）内部でおこった出来事、#マークのある行はThread（テスト用のサブクラス）で起こった出来事です。<br />
マークの後に何が起こったか、そしてその時のThreadのステータスを出力しています。<br />
例えば、
</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">@ internalExecute (RUNNABLE
</font></pre>
<p>はThread.internalExecuteが実行され、その時のステータスはRUNNABLEだったという感じです。<br />
（※このテストコードの出力結果は実行時のフレームレートやCPUの速度などに影響します。もしあなたがこのテストを実行した場合、テストの成否は同じはずですが出力結果は異なる可能性があります。今回は31FPSでこのテストを実行しました。）</p>
<p>まず、CYCLE0を見てみてください。</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">CYCLE 0--------------
@ internalExecute (RUNNABLE
# run (RUNNABLE
@ register event  (RUNNABLE
</font></pre>
<p>run()が実行されイベントハンドラが設定されています。<br />
ここでこのサイクルは終了です。</p>
<p></p>
<p>次に、CYCLE8を見てみます。<br />
このサイクルで<strong>割り込みハンドラが実行されない問題</strong>が起きています。</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">CYCLE 8--------------
@ internalExecute (WAITING
[DISPATCH]
@ eventHandler  (WAITING
@ internalExecute (RUNNABLE
# received event  (RUNNABLE</font></pre>
<p>まずイベントが配信されイベントハンドラが実行されるという期待した動作がスムーズに展開していきます&#8230;</p>
<p></p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">!!!!!!!!!!!!!!!!!!! CALL INTERRUPT !!!!!!!!!!!!!!!!!!!
@ interrupt  (RUNNABLE
CYCLE 9--------------
@ internalExecute (RUNNABLE
# run() (RUNNABLE
@ register event  (RUNNABLE
[DISPATCH]
@ eventHandler  (WAITING
@ internalExecute (RUNNABLE
# received event (RUNNABLE</font></pre>
<p>その後、interrupt()が実行されますが、次のサイクル9で実行されるはずの割り込みハンドラは実行されていません。<br />
また、割り込まれた後イベントのリスンをやめる事が期待されていますが、次のサイクルであるサイクル9でも何事もなかったようにイベントをリスンし続けています。
</p>
<p>何が起きたのでしょうか？</p>
<p></p>
<p>
もう一度割り込まれた時の出力結果を見てみます。</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">!!!!!!!!!!!!!!!!!!! CALL INTERRUPT !!!!!!!!!!!!!!!!!!!
@ interrupt (<strong>RUNNABLE</strong></font></pre>
<p>interrupt()が呼び出されたときThreadのステータスは<b>RUNNABLE</b>になっています。<br />
これは、<strong>interrupt()される直前にイベントハンドラが実行され、ステータスが変更されたためです。</strong></p>
<p><b><br /></b></p>
<p>Threadの仕様によると、割り込みハンドラが実行される条件はイベントハンドラが設定されている事、つまりステータスがWAITINGであることです。しかし割り込み直前でイベントハンドラが実行されたためにステータスがRUNNABLEになってしまいました。イベントハンドラが再度設定されステータスが再びWAITINGになるのは次のサイクルです。<strong>次のサイクルが始まる前に割り込みが実行されると、この時点ではまだステータスがRUNNABLEであるため、このエントリで取り上げている問題が起こります。</strong></p>
<p>テキストだけだとわかりにくいので図にしてみました。（<a href="http://www.imajuk.com/blog/archives/2009/03/post_6.html">前のエントリ</a>でも書いてみたシーケンス図です。見方がわからない場合は<a href="http://www.imajuk.com/blog/archives/2009/03/post_6.html">前のエントリ</a>を参照してください）</p>
<p>&nbsp;</p>
<p>まず、<strong>割り込みハンドラが意図する通りに実行されるケース</strong>です。</p>
<p><img src="http://img.skitch.com/20100120-emq6qwjmmxy22xtfxd86gf155y.jpg" alt="successfuly interruption" /></p>
<p>つぎに<strong>失敗したケース</strong>です。</p>
<p><img src="http://img.skitch.com/20100120-daiu1b29ch3itbfynm37j5x7y3.jpg" alt="failed interruption" /></p>
<p><b>サイクルとサイクルの間でイベントハンドラの実行と割り込みの実行の両方が起きている</b>のがわかります。<br />
イベントのキャッチによりThreadのステータスが一時的にRUNNABLEとなり、そのタイミングで割り込みが実行されると割り込みハンドラは失敗します。</p>
<p>「割り込みハンドラが実行されるのは待機状態に割り込まれた時」とThreadは仕様としているので、<strong>これは正しい動作と言えなくもない</strong>です。が、ユーザは（このテストのようなケースでは）「イベントを受け取ったら再びイベント待機状態」つまり「<strong>割り込まれるまでは常に待機状態</strong>」のThreadを意図していると思うのでバグのようにも思えます。<br />
この問題が仕様なのかバグなのか微妙なところです。</p>
<h4>運用でカバーできないのか？</h4>
<p><strong>ステータスが一時的にRUNNABLEになってしまう</strong>のが問題です。しかしステータスがRUNNABLEの時に割り込みが実行されるとすれば割り込みフラグ（isInterrupted）たつはずです。このフラグを利用すれば手動で割り込みハンドラを呼び出す事ができるのではないでしょうか？<br />
これを使って運用でカバーできないのでしょうか？</p>
<p>例えば以下のようなコードです。</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195">override<span style="color: #000000"> </span><span style="color: #7f0055">protected</span><span style="color: #000000"> </span>function<span style="color: #000000"> run() : </span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #6e6432">trace</span>(<span style="color: #930995">&#8220;&nbsp; &nbsp; # run()&#8221;</span>, printStatus(state));</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp;&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>割り込みハンドラを生成</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #141195">var</span> interruptHandler : <span style="color: #505000">Function</span> =&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span>function<span style="color: #000000">():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">trace</span><span style="color: #000000">(</span>&#8220;&nbsp; &nbsp; # INTERRUPTED¥n&#8221;<span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #505000">Static</span>.<span style="color: #00009b">log</span> += <span style="color: #930995">&#8220;interrutHandler &#8220;</span>;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; };</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; </span><span style="font: 11.0px Monaco"><b>//</b></span><b>割り込みフラグがたっていれば割り込みハンドラを実行して終了</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><b>&nbsp; &nbsp; </b><span style="color: #141195"><b>if</b></span><b> (isInterrupted)</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><b>&nbsp; &nbsp; {</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><b>&nbsp; &nbsp; &nbsp; &nbsp; interruptHandler();</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><b>&nbsp; &nbsp; &nbsp; &nbsp; </b><span style="color: #141195"><b>return</b></span><b>;</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><b>&nbsp; &nbsp; }</b></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>割り込みハンドラを設定</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; interrupted(interruptHandler);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>イベントをキャッチしたら再びイベントをリスンして待機状態へ</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; event(&#8230;</p>
</div>
<p></p>
<p>テストコードに上記の処理を追加すればテストは通ります。</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">  .
Time: 0.337
OK (1 test)</font></pre>
<p></p>
<p>うまくいったように思えます。<strong>が、まだ２つの問題を抱えています。</strong></p>
<p>1つ目は、待機状態（WAITING）でないのに割り込みハンドラを呼び出すという意味でThreadの仕様を変えてしまっている事です。<br />
2つ目は、実は<b>まだinterrupt()のタイミングによってはテストが失敗する</b>という事です。</p>
<p>後者について詳しく見ていきます。</p>
<p>まず、現段階のテストでは、イベントをキャッチした後割り込みが実行されています。（<strong>[イベント]　→　 [割り込み]</strong>）。しかし、割込みを実行した後にイベントをキャッチするケース（<strong>[割り込み]　→　[イベント]</strong>）をまだテストしていません。</p>
<p>テストコードにテストを追加してみます。</p>
<div style="<br />
padding: 10px;<br />
border: 1px solid #CCC;<br />
overflow: scroll;<br />
white-space: nowrap;<br />
">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco">//</span>割り込み直後にイベント配信</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color: #995600">test</span> <span style="color: #141195">function</span> inturruptHandlerExecution2() : <span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; </span>//200mSec<span style="font: 11.0px Hiragino Kaku Gothic ProN">後に</span><span style="color: #000000"> </span>[<span style="font: 11.0px Hiragino Kaku Gothic ProN">イベント配信</span>]<span style="color: #000000"> </span>-&gt;<span style="color: #000000"> </span>[<span style="font: 11.0px Hiragino Kaku Gothic ProN">割り込み</span>]</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6e6432"><span style="color: #000000">&nbsp; &nbsp; </span>setTimeout<span style="color: #000000">(</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span>function<span style="color: #000000">():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//Thread<span style="font: 11.0px Hiragino Kaku Gothic ProN">の</span>interrupt()<span style="font: 11.0px Hiragino Kaku Gothic ProN">を呼び出し</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">trace</span><span style="color: #000000">(</span>&#8220;¥n!!!!!!!!!!!!!!!!!!! CALL INTERRUPT !!!!!!!!!!!!!!!!!!!¥n&#8221;<span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">thread</span>.interrupt();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//Thread<span style="font: 11.0px Hiragino Kaku Gothic ProN">に向けてイベントを配信</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">dispatcher</span>.dispatch();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; }, 200</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px"></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//250mSec</span>後にもう一度イベント配信<span style="font: 11.0px Monaco">.</span>このイベントはキャッチしないはず</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6e6432"><span style="color: #000000">&nbsp; &nbsp; </span>setTimeout<span style="color: #000000">(</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #141195"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; </span>function<span style="color: #000000">():</span>void</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00009b">dispatcher</span>.dispatch();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; },</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; 250</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; </span>//300mSec<span style="font: 11.0px Hiragino Kaku Gothic ProN">後にテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6e6432"><span style="color: #000000">&nbsp; &nbsp; </span>setTimeout<span style="color: #000000">(</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">async</span>(</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #141195">function</span>():<span style="color: #141195">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//InterruptHandlerTestThread<span style="font: 11.0px Hiragino Kaku Gothic ProN">の割り込みハンドラが実行されたかどうかテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #930995"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #6e6432">assertEquals</span><span style="color: #000000">(</span>&#8220;interrupt event interrutHandler&nbsp;finalize&nbsp;&#8221;<span style="color: #000000">, </span><span style="color: #505000">Static</span><span style="color: #000000">.</span><span style="color: #00009b">log</span><span style="color: #000000">);</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>//<span style="font: 11.0px Hiragino Kaku Gothic ProN">割り込み後のステータスをテスト</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">assertEquals</span>(<span style="color: #505000">ThreadState</span>.<span style="color: #00009b">TERMINATED</span>, <span style="color: #00009b">thread</span>.state);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Hiragino Kaku Gothic ProN; color: #6480c8"><span style="font: 11.0px Monaco; color: #000000">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font: 11.0px Monaco">//</span>割り込み後の割り込みフラグをチェック（待機状態での割り込みなので<span style="font: 11.0px Monaco">false</span>のはず）</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #6e6432">assertFalse</span>(<span style="color: #00009b">thread</span>.isInterrupted);</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; ),&nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; &nbsp; &nbsp; 300</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #6480c8"><span style="color: #000000">&nbsp; &nbsp; </span>//<span style="font: 11.0px Hiragino Kaku Gothic ProN">テスト用</span>Thread<span style="font: 11.0px Hiragino Kaku Gothic ProN">開始</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&nbsp; &nbsp; <span style="color: #00009b">thread</span>.start();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
</div>
<p>前は「イベント配信」「割り込み」という順番でしたが、今度のテストは「割り込み」「イベント配信」という順番です。前のテストとはこの呼び出しの順番だけが違います。</p>
<p></p>
<p>このテストを実行してみるとテストは失敗します。
</p>
<pre style="
padding: 10px;
border: 1px solid #CCC;"><font size="-2" color="#141195">.E.
Time: 0.658
<b>There was 1 failure:</b>
1) inturruptHandlerExecution2(org.libspark.thread::InterruptHandlerTest)
Error: <b>expected:&lt;interrupt event [interrutHandler] &gt; but was:&lt;interrupt event [event] &gt;</b></font></pre>
<p>これは<a href="http://wonderfl.net/code/dda875b0618d9e877b2b2ea8aabacf12f65624f5" target="_blank">wonderflでsoundkitchenさんが指摘していること</a>と同じことが起こっています。</p>
<p>図にすると以下のような感じです。</p>
<p><img src="http://img.skitch.com/20100120-r4u6cuaihajhwth5q65ctet71g.jpg" alt="another failure case" /></p>
<p>このケースでは<strong>割り込み後のイベントハンドラの動作で、割り込みフラグと割り込みハンドラが上書きされてしまいます。</strong><br />
こうなるともはやThreadは自分が割り込まれたかどうかを知る手段がありません。運用でカバーするのは無理そうです。<br />やはりこの問題を解決するにはThreadのソースコードに手を入れる必要があるかもしれません。</p>
<p>
次回のエントリでは解決編として、Threadのソースにパッチを当てる方法を書いてみます。</p>
<p></p>
<p>つづく</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2010/01/thread1.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Threadはええぞ〜</title>
		<link>http://www.imajuk.com/blog/archives/2009/09/thread.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=thread</link>
		<comments>http://www.imajuk.com/blog/archives/2009/09/thread.html#comments</comments>
		<pubDate>Mon, 07 Sep 2009 18:34:57 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript3]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=55</guid>
		<description><![CDATA[前に一度org.libspark.threadライブラリについてエントリーを書きましたが、このライブラリは本当に素晴らしいです。フレキシブルに使えるし、使っているだけで自然とOOPの作法が身に付いていくような気もします。 &#8230; <a href="http://www.imajuk.com/blog/archives/2009/09/thread.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>前に一度<a href="http://www.libspark.org/wiki/Thread">org.libspark.threadライブラリ</a>についてエントリーを書きましたが、このライブラリは本当に素晴らしいです。フレキシブルに使えるし、使っているだけで自然とOOPの作法が身に付いていくような気もします。<br />
なんでこんなに使い心地がいいのかつらつら考えているのですが、いまだうまくエントリーにまとめられそうにありません。が、</p>
<p>とりあえず、今回は<strong>「Threadは新しいデザインパターンの実装なのではないか」</strong>という大胆な仮説を唱えてみようかと思いますw</p>
<h4>まずは 同期処理、非同期処理のおさらい</h4>
<p>さて、タスクAのあとタスクBを実行したいという状況があるとします。</p>
<p>以下のようなコードからスタートします。</p>
<pre class="brush: as3;">
package
{
    import flash.display.Sprite;

    public class AboutThread extends Sprite
    {
        public function AboutThread()
        {
            /**
            * タスクAが終わった後タスクBをすませたい
            */
            doTask();
        }

        //タスク実行
        private function doTask():void
        {
            //タスクAを生成
            var a:A = new A();
            //タスクを実行
            a.execute();
            //タスクBを生成
            var b:B = new B();
            //タスクを実行
            b.execute();
        }
    }
}
</pre>
<p>とってもシンプルで清々しいコードですね。何の問題もありません。平和な世界。</p>
<p>ただ現実はこのように甘くはないかもしれません。<br />
<strong>タスクAは非同期なタスクかもしれない</strong>からです。<br />
もし非同期の場合は、タスクの終了を通知してもらう手続きをして、さらに通知を受け取るイベントハンドラも必要になりますね。<br />
あと、一度だけ通知してもらいたい場合（よくある！）は、ハンドラ内で通知解除の手続きも必要です。</p>
<p>コードは以下のような感じです。</p>
<pre class="brush: as3;">
package
{
    import flash.events.Event;
    import flash.display.Sprite;

    public class AboutThread extends Sprite
    {
        public function AboutThread()
        {
            /**
            * タスクAが終わった後タスクBをすませたい
            */
            doTaskA();
        }

        //タスクAを実行
        private function doTaskA():void
        {
            //タスクAを生成
            var a:A = new A();
            //タスク終了を通知してもらう
            a.addEventListener(Event.COMPLETE, taskACompleteHandler);
            //タスクを実行
            a.execute();
        }

        //タスクAが終了した
        private function taskACompleteHandler(event:Event):void
        {
            //リスナの登録を解除
            A(event.target).removeEventListener(Event.COMPLETE, taskACompleteHandler);
            //タスクBスタート
            doTaskB();
        }

        //タスクBを実行
        private function doTaskB():void
        {
            //タスクBを生成
            var b:B = new B();
            //タスク終了を通知してもらう
            b.addEventListener(Event.COMPLETE, taskBCompleteHandler);
            //タスクを実行
            b.execute();
        }

        //タスクBが終了した
        private function taskBCompleteHandler(event:Event):void
        {
            //リスナの登録を解除
            B(event.target).removeEventListener(Event.COMPLETE, taskACompleteHandler);
            //...続く
        }
    }
}
</pre>
<p>突然コード量が増えてしまいました。ざっと倍くらいでしょうか。</p>
<h4>何が問題なのか？</h4>
<p><strong>単純にコードの量が増えたことを問題にしているわけではありません。</strong><br />
最近の気の利いたエディタを使っていれば半自動でリスナ登録やハンドラの記述をやってくれますもんね。<br />
コードを書くときはそれほど負担にはならないんです。でも、<strong>コードを読むときはどうでしょうか？</strong></p>
<p>本来書きたかった処理は、<strong>「タスクAのあとにタスクBを実行したい」</strong>という物だったはずです。<br />
もちろん残念ながらコンパイラは自然言語で書かれた命令のような抽象的なことを理解することはできないので（死ぬまでにはそんなコンパイラが出てくることを望みますが）、<br />
それなりの手続きを記述していく必要があります。<br />
問題にしているのは手続きの細かさです。</p>
<p>上記のコードは、<strong>「タスクAのあとにタスクBを実行したい」ということを記述したいはずのコードなのに、その一段低レベルなイベントシステムの手続きという層がむき出しになっています。</strong><br />
また、これが、「Aのあと、Bのあと、Cのあと、Dのあと、Eしたい」の様なケースではイベントの手続きという低レベルなコードがほとんどを全体のほとんどをしめてしまうでしょう。</p>
<h4>Threadはこれを解決する？</h4>
<p><strong>はい。解決します。</strong><br />
このように</p>
<pre class="brush: as3;">
package
{
    import org.libspark.thread.Thread;

    public class AboutThread extends Thread
    {
        public function AboutThread()
        {
            /**
            * タスクAが終わった後タスクBをすませたい
            */
            doTaskA();
        }

        //タスクAを実行
        private function doTaskA():void
        {
            //タスクAを生成
            var t:Thread = new DoAThread();
            //タスクを実行
            t.start();
            //タスクの終了を待つ
            t.join();
            //終わったらタスクB開始
            next(doTaskB);
        }

        //タスクBを実行
        private function doTaskB():void
        {
            //タスクBを生成
            var t:Thread = new DoBThread();
            //タスクを実行
            t.start();
            //タスクの終了を待つ
            t.join();
            //終わったら次の...
            next(doSomething);
        }
    }
}
</pre>
<p>コード量も減りましたが、何より嬉しいのは上から流れるように処理を記述できる点です。<br />
イベントという仕組みは一見隠蔽され、<strong>一段抽象的なレベルで処理を記述できています。</strong>直感的とも言えますね。<br />
start()やnext()などとても直感的な記述で、もし初めてThreadを使ったコードを見た人でも何をやっているか想像できるんじゃないでしょうか？<br />
t.join()というちょっと違和感を感じるかもしれない記述がありますが、これは<strong>「tの終了を待つ」</strong>と読み替えてもらうといいです。</p>
<hr />
<p><em>ちょっと脱線</em><br />
個人的にはjoin()という名前に違和感を感じる。startやnextと意味の階層が違う気がしてて、うまく言えないけど利用者視点じゃなく設計者視点な名前という感じで。<br />
これがもし、waitForFinishing()とか（ださいけど）だと意味がつながる気がする。さらに、join()とnext()をまとめたシンタックスを用意して、<br />
さらにさらに流れるようなインターフェイスで、t.start().andThen(func)とか書けると最高だー。</p>
<hr />
<h4>非同期処理のコード大盛り問題を解決するだけの物ではない</h4>
<p>本題です。<br />
最近、自分は<strong>コントローラはすべてThreadで書いています。同期、非同期関係なく</strong>です。<br />
たとえ同期なタスクでもjoin()してしまいます。そうすると何が嬉しいのかと言うと、<br />
もし、コードを書き始めた当初同期だったあるタスクがあとから非同期になっても、クライアントコードはいっさい変更する必要がありません。<br />
いいかえれば、<strong>クライアントはそのタスクが同期か非同期かを意識する必要なく処理を記述できる</strong>んです。</p>
<p>「AしてBしてCしてDして&#8230;」<br />
それらのタスクが同期なタスクか非同期なタスクかいっさい気にかけることなく流れるように処理を記述でき、後から読むときも流れるようにコードを読めます。<br />
エントリーの最初にあげた大胆な仮説、「Threadは新しいデザインパターンの実装なのではないか」というのはこれです。<br />
<strong>「同期か非同期かを意識する必要なく処理を記述する」パターン。</strong></p>
<p>ThreadはCommandパターンとCompositeパターンの応用だとは思うんですが、そのどちらにもない<strong>同期、非同期性の隠蔽</strong>という機能があるんですよね。<br />
少なくともGoFの23のパターンにはないパターンだという気が。。<br />
こういうパターンに既に名前がついているかどうか知っている人がいたら教えてください〜。</p>
<h4>と書いては見たものの</h4>
<p>うーん、新しいパターンはちょっと言い過ぎたかも。やっぱりw<br />
ほとんどのCommand系のライブラリは非同期なタスクをサポートしてますもんね。<br />
でも、いろいろあるCommand系のライブラリの中でも、クライアントコードの記述の簡潔さは一歩抜きん出ていると思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2009/09/thread.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>最適化してます？</title>
		<link>http://www.imajuk.com/blog/archives/2009/04/post_7.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=post_7</link>
		<comments>http://www.imajuk.com/blog/archives/2009/04/post_7.html#comments</comments>
		<pubDate>Fri, 10 Apr 2009 15:06:17 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript3]]></category>
		<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=54</guid>
		<description><![CDATA[最適化（と言ってもいろいろあるけど）って、ひたすらコードに制限を加えていくことになりますよね。ドラスティックに効果がある最適化は特に。 融通の利かないコードと引き換えに速度を得られるんですね。わかります。 コードの資産化 &#8230; <a href="http://www.imajuk.com/blog/archives/2009/04/post_7.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>最適化（と言ってもいろいろあるけど）って、ひたすらコードに制限を加えていくことになりますよね。ドラスティックに効果がある最適化は特に。<br />
融通の利かないコードと引き換えに速度を得られるんですね。わかります。<br />
コードの資産化をいつも心がけている自分としては、いままで最適化にはあまり興味がなかったんですけど、<a href="http://jp.max.adobe.com/player.html?2-10">城戸さんの公演のビデオ</a>を見て少し考え方が変わりました。<br />
曰く、<strong>「浮いた分のパフォーマンスを別の表現にまわせる」</strong>。<br />
たしかに。</p>
<p>というわけで、今回は最適化のプラクティスです。<br />
テーマは魚っぽいノードの群れ。</p>
<p><a href='http://www.imajuk.com/blog/wp-content/uploads/2011/07/node1k.swf' rel="shadowbox;width=800;height=300"><img src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/node1k.png" width="400" height="230" /><br />
<small>ノード数1000</small></a></p>
<p><a href='http://www.imajuk.com/blog/wp-content/uploads/2011/07/node3k.swf' rel="shadowbox;width=800;height=300"><img src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/node3k.png" width="400" height="230"  /><br />
<small>ノード数3000</small></a></p>
<p>僕の環境では、ノード数1000だと60/60fpsキープできるのですが、<br />
ノード数を3000まで増やすとで32/60fpsどまりでした。<br />
にわかオプティマイザーだとこんなもんですかね。くやしい。<br />
まだまだ早くできる余地がある気がします。</p>
<p>施した最適化は以下のとおり<br />
・オブジェクト複製による残像効果は使わない。<br />
・ノードはaddChild()しないでBitmapDataに描画<br />
・ループ内でオンデマンドでやる必要のない計算は全て前もってやっておく<br />
・ループ内で極力newしない<br />
・全てビットマップ化<br />
・flockポイ動きだけどいんちき<br />
・その他、ちまたにあふれている重箱の隅をつつくような最適化Tipsいろいろ<br />
CS4のVector使えばもうちょっと早くなるのかな。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2009/04/post_7.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>絵で見るThread</title>
		<link>http://www.imajuk.com/blog/archives/2009/03/post_6.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=post_6</link>
		<comments>http://www.imajuk.com/blog/archives/2009/03/post_6.html#comments</comments>
		<pubDate>Mon, 23 Mar 2009 14:19:13 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript3]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=53</guid>
		<description><![CDATA[Flasher各方面で話題のorg.libspark.thread.Threadだけど、最近ようやく使ってみた。 評判がいいのもうなづける素晴らしいライブラリだと思う。 もっと早く使ってみればよかった。。 ドキュメントが &#8230; <a href="http://www.imajuk.com/blog/archives/2009/03/post_6.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Flasher各方面で話題の<a href="http://www.libspark.org/wiki/Thread">org.libspark.thread.Thread</a>だけど、最近ようやく使ってみた。<br />
評判がいいのもうなづける素晴らしいライブラリだと思う。<br />
もっと早く使ってみればよかった。。<br />
<a href="http://www.libspark.org/htdocs/as3/thread-files/document/">ドキュメント</a>がとてもよく出来ているので、使い方についてほとんど付け加えることはないんだけど、文章とコードだけだと、処理の実行単位とか実行順がわかりにくいかもしれないと思い（自分がそうだった）シーケンス図でまとめてみた。<br />
<strong>ここまちがってるんじゃないの？</strong>みたいなつっこみ、絶賛募集してます。</p>
<h4>シーケンス図の見方、超投げやりな説明</h4>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-4.jpg" width="231" height="197"  /><br />
シーケンス図は、<strong>プログラムの実行時における</strong>インスタンスの処理の流れや、インスタンス間のコラボレーションの様子を表現できる。<br />
インスタンスとインスタンスの寿命はこのように表現する。</p>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-3-2.jpg" width="284" height="175"  /><br />
時間は上から下へ流れる。<br />
この図では、<br />
1・ENTER_FRAMEイベントが起きた<br />
2・誰かがnew A()を呼び出した<br />
3・インスタンスAが生成された<br />
事を表している。</p>
<h4>Threadの実行単位は「実行関数」</h4>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-6.jpg" width="311" height="209"  /><br />
Threadの実行単位は「実行関数」。<br />
<strong>1フレーム<small>※1</small>に一度、Threadが持っている実行関数が1つだけ実行される。<br />
2つは実行されない。<small>※2</small></strong>これ大事。<br />
※1（1フレームと書いたが、フレームベースではなくintervalベースにすることもできるみたい）<br />
※2（例外あり。event()参照）<br />
runとfinalizeはデフォルトで用意されている実行関数。<br />
runは必ず最初に呼び出される実行関数。<br />
finalizeはThreadが終了する前に必ず呼び出される実行関数。</p>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-7.jpg" width="377" height="273"  /><br />
実行関数の中でnext()を呼ぶと、次の実行関数を<strong>予約</strong>できる。<br />
予約された実行関数は、1フレーム1実行関数の原則に従い、次のフレームで実行される</p>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-8.jpg" width="451" height="297"  /><br />
実行関数の中でevent()を呼ぶと、任意のイベントが発生するまで<strong>待機状態</strong>になる。<br />
イベントが発生すると予約した実行関数を実行する。<br />
その後特に実行関数がなければ、finalize()が実行される<br />
※（1フレーム1実行関数が基本だが、この場合は例外的に2つの実行関数（fとfinalize）が1フレームで実行される）</p>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-10.jpg" width="315" height="325"  /><br />
実行関数内でsleep()を呼ぶと、指定された時間のあいだ<strong>待機状態</strong>になる。<br />
時間が過ぎると次の実行関数が実行される。</p>
<h4>実行関数の定義まとめ</h4>
<p>Threadの実行単位は実行関数なので、なにが実行関数なのかを意識した方が良い。<br />
実行関数は、</p>
<ul>
<li><strong>run()</strong></li>
<li><strong>next()に渡された関数</strong></li>
<li><strong>event()に渡された関数</strong></li>
<li><strong>finalize()</strong></li>
</ul>
<p>上記に含まれないThread内の関数は実行関数ではないので注意。</p>
<h4>Threadの親子関係</h4>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-11.jpg" width="427" height="341"  /><br />
実行関数の中で新しいThreadを生成すると、Threadの親子関係が出来る。<br />
AはBの親、BはCの親。<br />
<strong>親子関係のあるスレッドは、それぞれ独立した時間軸を持ち実行関数を実行していく</strong>。</p>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-12.jpg" width="451" height="425"  /><br />
子Threadの実行関数は必ず親Threadの実行関数より先に実行される。</p>
<p><img alt="Thread.graffle-19.jpg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-19.jpg" width="439" height="497"  /><br />
子Threadがjoin()された時は、親Threadは子Threadのすべての実行関数が終了するまで次の実行関数の実行を待機する（<strong>待機状態</strong>になる）。<br />
つまり、<strong>各Threadの独立した時間軸の一本化</strong>。</p>
<h4>Monitor</h4>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-14.jpg" width="381" height="414"  /><br />
実行関数内で、Monitor::wait()を呼び出すと、そのThreadはMonitor::notify()が呼び出されるまで<strong>待機状態</strong>になる。<br />
nonify()が呼び出された場合は即座に待機状態が解除され、notify()された同じフレームで実行関数が実行される。</p>
<h4>待機状態まとめ</h4>
<p>待機状態は、「時間指定あり待機状態」と「時間指定なし待機状態」に分けられる。</p>
<table cellpadding="0" cellspacing="0">
<tr>
<td>時間指定</td>
<td>あり</td>
<td>なし</td>
</tr>
<tr>
<td> </td>
<td valign="top"><strong>・join(timeout time)したとき</strong><br/><strong>・sleep()したとき</strong></td>
<td><strong>・join()したとき（引数なし）</strong><br/><strong>・event()したとき</strong><br/><strong>・Monitor.wait()したとき</strong></td>
</tr>
</table>
<h4>割り込み</h4>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-15.jpg" width="323" height="410"  /><br />
interrupt()を呼び出すと、割り込みフラグが立つ。<br />
割り込み処理はこのフラグを使って実装する。<br />
ちなみにinterrupt()は実行関数ではないので注意。</p>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-17.jpg" width="355" height="574"  /><br />
<strong>待機状態のときに割り込まれると</strong>、指定した割り込みハンドラが実行される。<br />
割り込みハンドラは、Thread.interrupted ( )をつかって<strong>各実行関数ごとに</strong>記述する。<br />
待機状態で割り込まれ、割り込みハンドラがない場合はエラーとなる。</p>
<p><img alt="" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/Thread.graffle-18.jpg" width="532" height="353"  /><br />
<strong>たとえ親子関係にあっても、割り込みは子Threadに伝播しない</strong>。<br />
もし伝播させたい場合は<a href="http://www.libspark.org/htdocs/as3/thread/org/libspark/thread/utils/ParallelExecutor.html">org.libspark.thread.utils.ParallelExecutor</a>または<a href="http://www.libspark.org/htdocs/as3/thread/org/libspark/thread/utils/SerialExecutor.html">org.libspark.thread.utils.SerialExecutor</a>を使用する。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2009/03/post_6.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ConvolutionFilterで遊ぶ その4</title>
		<link>http://www.imajuk.com/blog/archives/2009/03/convolutionfilter_4.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=convolutionfilter_4</link>
		<comments>http://www.imajuk.com/blog/archives/2009/03/convolutionfilter_4.html#comments</comments>
		<pubDate>Sat, 14 Mar 2009 20:07:27 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=52</guid>
		<description><![CDATA[ConvolutionFilterを使ったアニメーションの可能性 前回からの続きです。前回までを見てないと今回の話はわからないと思うので、もしまだであれば以下のリンクからど〜ぞ。 ConvolutionFilterで遊ぶ &#8230; <a href="http://www.imajuk.com/blog/archives/2009/03/convolutionfilter_4.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h4>ConvolutionFilterを使ったアニメーションの可能性</h4>
<p>前回からの続きです。前回までを見てないと今回の話はわからないと思うので、もしまだであれば以下のリンクからど〜ぞ。</p>
<ul>
<li><a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html">ConvolutionFilterで遊ぶ その1</a></li>
<li><a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_2.html">ConvolutionFilterで遊ぶ その2</a></li>
<li><a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_3.html">ConvolutionFilterで遊ぶ その3</a></li>
</ul>
<p>ここに黒背景に1pxの画像があります。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/img1.jpg" alt="img1.jpg" width="151" height="171" /></span><br />
この画像に以下のような行列でConvolutionFilterを適用すると&#8230;<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k1.jpg" alt="k1.jpg" width="108" height="102" /></span><br />
以下のようになります。<a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_3.html">前回</a>までで見てきたように、ターゲットピクセルの50％の強さで、斜め4方向にピクセルを移動コピーしています。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/img2.jpg" alt="img2.jpg" width="151" height="171" /></span></p>
<hr />
<p>さて、このフィルタの適用結果に、さらにフィルタをかけ続けるといったいどうなるのか？とても気になったので、ツールに連続してフィルタを適用する機能を追加しました。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/tool.jpg" alt="tool.jpg" width="223" height="53" /></span><br />
三角形の再生ボタンを押すと、フィルタを連続して適用していきます。<br />
スライダーを右に動かすと、フィルタをかけるインターバルが長くなっていきます。（注：上の画像はスナップショットなので、機能しませんよ〜）</p>
<hr />
<p>再生ボタンを押すと、ドットで出来た円が拡大し、画面端で折り返した後、画像全体が白に収束します。<br />
(下の画像どれかをクリックすると、アニメーションが再生されます。）<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/1px.png&amp;k=0.5,0,0.5,0,0,0,0.5,0,0.5&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim1.jpg" alt="anim1.jpg" width="401" height="300" /></span></a><br />
<small>1・ドットで出来た円が拡大していく&#8230;</small><br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/1px.png&amp;k=0.5,0,0.5,0,0,0,0.5,0,0.5&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim2.jpg" alt="anim2.jpg" width="401" height="300" /></span></a><br />
<small>2・画面端で折り返す&#8230;</small><br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/1px.png&amp;k=0.5,0,0.5,0,0,0,0.5,0,0.5&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim3.jpg" alt="anim3.jpg" width="401" height="300" /></span></a><br />
<small>3・最後は白に収束する</small><br />
円が拡大していくとこまではなんとなく予想してましたが、<strong>その後が想像を超えてました</strong>。<br />
では、シンプルなグレースケール画像ではなく、フルカラーの画像で同じ事をやると何が起こるのでしょうか？<br />
下の画像に、同じConvolutionFilterを連続して適用してみると&#8230;<br />
(下の画像をクリックすると、アニメーションが再生されます。）<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0.5,0,0.5,0,0,0,0.5,0,0.5&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim0.jpg" alt="anim0.jpg" width="400" height="299" /></span><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim4.jpg" alt="anim4.jpg" width="401" height="300" /></span></a><br />
結果は、一瞬で<strong>白に収束</strong>してしまいます。。<br />
まぁ、さっきのような黒背景に1ピクセルの白があるだけの画像ではなく、<br />
明るさを持ったピクセルが無数にあるフルカラー画像では当たり前の結果ですよね。<br />
ということは、行列の値がまずかったと。<br />
そこで、プリセットにあるガウスぼかしを連続で適用してみました。<br />
(下の画像をクリックすると、アニメーションが再生されます。）<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0.03,0.11,0.03,0.11,0.44,0.11,0.03,0.11,0.03&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim5.jpg" alt="anim5.jpg" width="401" height="300" /></span></a><br />
なんとなく味わいのあるフェードアウトで、最終的には黒に収束します。<br />
ところで、ガウスぼかしの行列は以下のとおりで、全ての数値を足し合わせると「1」になります。<br />
<strong>（0.33*4 + 0.11*4 + 0.44 = 1）</strong><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k2.jpg" alt="k2.jpg" width="111" height="105" /></span><br />
いろいろやってわかったのですが、ConvolutionFilterを連続して適用する際、<br />
<strong>行列の数値を足し合わせて1以下の場合、画像は黒（0）に収束する傾向があり、1より大きい場合は白（255）に収束していく</strong>ようです。<br />
（あとでみますが、どちらにも収束せずに発散することもあります。）<br />
たとえば、ターゲットセルに対応する値をほんの少しだけ大きくしてみます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k3.jpg" alt="k3.jpg" width="111" height="105" /></span><br />
このように、列の数値を足し合わせた数を1より大きくすると、画像は白に収束していきます。RGBの各チャンネルが255方向へ収束するのでとてもきれいです。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0.03,0.11,0.03,0.11,0.45,0.11,0.03,0.11,0.03&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim6.jpg" alt="anim6.jpg" width="400" height="299" /></span><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim7.jpg" alt="anim7.jpg" width="400" height="299" /></span></a><br />
さきほど、黒にも白にも収束しない場合があると言いましたが、<br />
たとえば、以下のような行列の場合です。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k5.jpg" alt="k5.jpg" width="108" height="103" /></span><br />
この行列で、ConvolutionFilterを適用し続けると、黒にも白にも収束せずに不思議なモアレ模様を描き続けます。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,0.2,0,0.2,1.9,-0.8,0,-0.8,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim8.jpg" alt="anim8.jpg" width="400" height="300" /></span></a><br />
これがそのまま、何かの表現に使えるとは思いませんが、<br />
このライフゲームのような不思議なアニメーションは面白いです。<br />
ターゲットピクセルの値を少し変えてみると、<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k6.jpg" alt="k6.jpg" width="111" height="105" /></span><br />
黒に収束してしまいましたが、よりライフゲーム感が出てきました。シマシマの中を何かが泳いでいます（笑。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,0.2,0,0.2,1.22,-0.8,0,-0.8,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim9.jpg" alt="anim9.jpg" width="400" height="300" /></span></a></p>
<hr />
<p>他にも面白いものがいくつか発見できたので、ならべておきます。<br />
(画像をクリックすると、アニメーションが再生されます。）<br />
ガウスぼかしのフェードアウトに似ていますが、終わりがけに一部カラーハーフトーンのような効果が見られます。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/parrot.png&amp;k=0,0,0.11,-0.01,0.72,0,0,-0.01,0.22&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim10.jpg" alt="anim10.jpg" width="399" height="301" /></span></a><br />
色面の色彩が荒くなっていき、最終的に点描のような状態で収束します。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,-0.01,0.01,-0.01,1.04,-0.01,0.01,-0.01,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim11.jpg" alt="anim11.jpg" width="399" height="301" /></span></a><br />
画像が流れ落ちていく。。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0.1,0.1,0.1,0,0.98,0,-0.1,-0.05,-0.1&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim12.jpg" alt="anim12.jpg" width="399" height="301" /></span></a><br />
コメントしにくいけど綺麗。。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,0.01,0.01,0,0.976,0.01,0,0,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim14.jpg" alt="anim14.jpg" width="399" height="301" /></span></a><br />
これもコメントしにくい。ななめ。。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,0,0,-1,2.9,0,1,-1,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim15.jpg" alt="anim15.jpg" width="399" height="301" /></span></a></p>
<h4>行列作成のこつ</h4>
<p>行列の数値を色々変えながら遊んでいましたが、<br />
コントロールしやすいのはピクセルの移動方向ぐらいで、<br />
<strong>ほとんどの場合予想がつかない変化となります。。</strong><br />
それでも、いくつかコツと言えるようなものがあったので、あげてみます。</p>
<ol>
<li> <strong>最終結果を暗くする、明るくする</strong><br />
上でも書きましたが、行列の足し合わせた数が1を超えると白（255方向）へ収束し、1以下だと黒（0方向）へ収束します。ただしどちらにも収束しない場合もあります。</li>
<li><strong>方向を変える</strong>例えば、以下のような行列は上側の数値よりも下側の数値の方が大きいです。このように下に重みをつけた場合、ピクセルは上に移動します。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,-0.2,0,0,1.15,0,0,0.1,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k8.jpg" alt="k8.jpg" width="111" height="107" /></span></a><br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,-0.2,0,0,1.15,0,0,0.1,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><br />
<img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim22.jpg" alt="anim22.jpg" width="399" height="300" /></span></a><br />
下に移動させたい場合は、上下反転させて、上に重みをつければればOK。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,0.1,0,0,1.15,0,0,-0.2,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k9.jpg" alt="k9.jpg" width="109" height="104" /></span><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><br />
<img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim23.jpg" alt="anim23.jpg" width="399" height="300" /></span></a><br />
同じ理屈で、45度回転させれば、斜め右上に重みがつくので斜め移動、さらに45度回転させれば、右の重みがつくので横移動になります。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,0,0.1,0,1.15,0,-0.2,0,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k10.jpg" alt="k10.jpg" width="109" height="104" /></span><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim21.jpg" alt="anim21.jpg" width="399" height="300" /></span></a><br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/textures_rainbow_lfstexturas_724600_l.png&amp;k=0,0,0,-0.2,1.15,0.1,0,0,0&amp;a=true" target="sub"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/k11.jpg" alt="k11.jpg" width="109" height="104" /></span><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img class="mt-image-none" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/anim20.jpg" alt="anim20.jpg" width="399" height="300" /></span></a></p>
<p>また、<strong> 縦横方向の重みは収束結果にピクセルが残りやすく、斜め方向の重みは収束結果にピクセルが残りにくい</strong>みたいです。</li>
<li><strong>面白い行列を発見出来たら細かく微調整</strong>行列の合計が1以下の黒への収束と、1より大きい白への<strong>収束の境界付近が、収束するまでに長く時間がかかる</strong>ので面白い効果が出来やすい気がします。<br />
面白い行列を発見出来たら、ターゲットピクセルの数値を増減させてこの境界を探してみましょう。<br />
0.01増減させただけで、見た目が大きく変わることもあります。</li>
</ol>
<h4>ConvolutionFilterを使ったアニメーションの利用の可能性</h4>
<p>さて、ConvolutionFilterを使ったアニメーションの可能性を探ってみたわけですが、<br />
「で、これなんかに使えるの？」という疑問が聞こえてくる気がします。<br />
さすがに、クライアントワークなどにそのまま使えるとは思いません。ただ、表現の種（素材）として考えたときには一定のポテンシャルを感じます。<br />
たとえば、最初の1pxを拡張していくグレースケールのアニメーションなんかは、<br />
<strong>アルファチャンネルマスクとして</strong>使えば、スライドショーのトランジションとかに利用できるんじゃないかと思います。（綺麗かどうかはやってみてないのでわからんですが）<br />
もしかしたら、白方向、黒方向へ収束するものは、そのままトランジションとして利用できるものもあるかもしれません。<br />
他には、<strong>オリジナルの元画像を残しつつ、BlendMode.SREEN等で合成</strong>しながらアニメーションさせてみるとか、アニメーション中に別の画像を重ねて見るとか。。<br />
個人的には、置き換えマップ（DisplacementMapFilter）のソースとして、ConvolutionFilterを使ったアニメーションを利用するとどんな事が可能になるか探ってみたいとこだったりします。<br />
また何か発見があったらレポートします。<br />
とりあえずこのシリーズは今回で終了です。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2009/03/convolutionfilter_4.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ConvolutionFilterで遊ぶ その3</title>
		<link>http://www.imajuk.com/blog/archives/2009/02/convolutionflter_3.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=convolutionflter_3</link>
		<comments>http://www.imajuk.com/blog/archives/2009/02/convolutionflter_3.html#comments</comments>
		<pubDate>Tue, 24 Feb 2009 10:26:18 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=51</guid>
		<description><![CDATA[ピクセル変換の過程を追いかけてみる 前回のエントリーで紹介したツールを使って、ConvolutionFilterの詳細を追いかけてみたいと思います。にアクセスして、テスト用画像を開いて下さい。 黒い背景の中央に1ピクセル &#8230; <a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_3.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h4>ピクセル変換の過程を追いかけてみる </h4>
<p><a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_2.html">前回のエントリー</a>で紹介した<a href="http://www.imajuk.com/conv/cnvExpr.html">ツール</a>を使って、ConvolutionFilterの詳細を追いかけてみたいと思います。<<<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/1px.png&#038;k=0,0,0,0,1,0,0,0,0&#038;a=false">ここ</a>>>にアクセスして、テスト用画像を開いて下さい。<br />
黒い背景の中央に1ピクセルの白いピクセルが表示されていると思います。<br />
この画像を使ってConvolutionFilterによるピクセル変換を見ていきたいと思います。<br />
（Convolutionでどのような計算が行われているかは<a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html">ConvolutionFlterで遊ぶ その1</a>を参照）</p>
<div>さて、いま、行列は以下のようになっています。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
</table>
</div>
<p>この行列を使ってConvolutonFilterを適用する事の意味を考えてみます。<br />
ターゲットとなるピクセル（<strong>以下、ターゲットピクセルと表記します</strong>）の周辺にある8ピクセルはずべて0です。<br />
<strong>周辺にどんな色のピクセルがあったとしても、0倍されるので結果は0</strong>です。<br />
言い換えると、<strong>ターゲットピクセルの周辺のピクセルは全く考慮しない</strong>ということになります。<br />
一方、ターゲットピクセルに対応する行列の数値は1です。<br />
<strong>自身のピクセルの強さ（色）を1倍するわけですから、ターゲットピクセルは元の色そのまま</strong>ということになります。<br />
つまり、この行列は、<strong>なんのピクセル操作もしない行列</strong>です。</p>
<h4>平行に移動コピー</h4>
<div>では、行列を以下のように変更してみます。<br />
何が起こるでしょうか？<br />
Kernelの数値を変更して実際に結果を確認してみて下さい。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
</table>
</div>
<p>ピクセルを1倍してそのまま表示するという意味では、先ほどの「何もしない行列」と同じですが、<br />
<strong>1倍するピクセルがターゲットピクセルの右隣</strong>になっています。<br />
つまり、<strong>ターゲットピクセルを「ターゲットピクセルの右隣のピクセルにそのまま置き換える」という意味</strong>になり、<br />
その結果、画像全体が1ピクセル左に移動します。<br />
（メインビューにマウスカーソルをのせて、拡大画像で確認できます。）<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="convEx1.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx1.jpeg" width="319" height="176" class="mt-image-none" style="" /></span></p>
<h4>両側に移動コピー </h4>
<div>次はターゲットピクセルの左の数値も1にしてみましょう。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>1</strong></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
</table>
</div>
<p>今度はターゲットピクセルの右隣だけでなく、左隣のピクセルもコピーします。<br />
<strong>左方向の平行移動と右方向の平行移動を重ね合わせた</strong>ようなイメージです。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="convEx2.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx2.jpeg" width="319" height="176" class="mt-image-none" style="" /></span></p>
<h4>4方向に移動コピー </h4>
<div>ということは、以下のような行列は、</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>1</strong></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>0</strong></td>
</tr>
</table>
</div>
<p>予想通りこうなります↓。<br />
このように1倍する行列はすごくわかりやすいですね。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="convEx3.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx3.jpeg" width="319" height="176" class="mt-image-none" style="" /></span></p>
<h4>ガウスぼかし</h4>
<p>1倍する行列はこのくらいにして、つぎはガウスぼかしについてみていきます。<br />
<strong>Presetから「gauss」を選択して下さい。</strong><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="convEx4.jpg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx4.jpg" width="135" height="148" class="mt-image-none" style="" /></span></p>
<div>行列が次のように変更されると思います。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0.03</strong></td>
<td><strong>0.11</strong></td>
<td><strong>0.03</strong></td>
</tr>
<tr>
<td><strong>0.11</strong></td>
<td><strong>0.44</strong></td>
<td><strong>0.11</strong></td>
</tr>
<tr>
<td><strong>0.03</strong></td>
<td><strong>0.11</strong></td>
<td><strong>0.03</strong></td>
</tr>
</table>
</div>
<p>これも、わりと行列から結果が推測しやすいと思います。<br />
行列をみると、タ<strong>ーゲットピクセルの色を44％に薄めて、薄まった分を周辺のピクセルのから少しずつ足してる</strong>のがわかります。<br />
イメージとしては、ターゲットピクセルを周りの色と馴染ませる感じですね。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="convEx14.jpg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx14.jpg" width="316" height="174" class="mt-image-none" style="" /></span></p>
<h4>エッジ検出</h4>
<p>エッジ検出はややこしいのですこしずつ理解していきます。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html#?i=http://www.imajuk.com/conv/rect.png&#038;k=0,0,0,0,1,0,0,0,0&#038;a=false"><<ここ>></a>にアクセスして、次のテスト画像を開いて下さい。<br />
黒い背景に白い四角形の画像が表示されます。</p>
<div>行列を次のように変更してみて下さい。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>-1</strong></td>
<td><strong>1</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
</table>
</div>
<p>四角形の左辺だけが抽出されました。おもしろいですね。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx6.jpg"><img alt="convEx6.jpg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx6-thumb-420x173-18.jpg" width="420" height="173" class="mt-image-none" style="" /></a></span><br />
何が起こっているのか考えてみます。<br />
メインビューにカーソルを移動して、四角形の左上角のピクセルをポイントして下さい。<br />
以下のようにその部分を拡大してみる事ができます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="convEx7.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx7.jpeg" width="319" height="176" class="mt-image-none" style="" /></span><br />
ターゲットピクセルを、四角形の左上角のピクセルにして考えてみます。<br />
まず、<strong>行列の数値0は無視していい</strong>のを思い出して下さい。（0倍なので計算に影響しない）<br />
そうすると、<strong>考慮するのはターゲットピクセル（行列の1）とその左隣のピクセル（行列の-1）</strong>です。<br />
また、ターゲットピクセルの左隣の<strong>ピクセルは黒（0）です。<br />
黒（0）を何倍しても0なのでこれも無視できます。</strong><br />
つまり、この場合、考慮するのはターゲットピクセルのみということになります。<br />
<strong>結果、ターゲットピクセルを1倍してそのまま</strong>です。<br />
次に、今見たピクセルの右隣のピクセルをターゲットピクセルにして考えてみます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="convEx8.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx8.jpeg" width="319" height="176" class="mt-image-none" style="" /></span><br />
行列から、考慮するのはターゲットピクセルとその左隣のピクセルです。<br />
今度は先ほどと違い、ターゲットピクセルの左隣のピクセルは白（255）です。<br />
対応する行列の数値は-1。かけ算すると255 x -1 = -255。<br />
これをターゲットピクセル（白255）と足し合わせます。<br />
結果、255 + (-255) = 0 で、もともと<strong>白だったターゲットピクセルが黒に変更</strong>されました。<br />
ちょっと乱暴にまとめると、<br />
自分（ターゲットピクセル）の左隣がxで、自分もx（x以下）だったら黒にする。そうじゃなければ、なにもしない。<br />
これを言い換えると、<strong>ある色が連続して平行に並んでいる場合、その一番左の色を残し他は黒（0）にする</strong>と言えます。<br />
この結果、左端の輪郭が抽出されます。</p>
<div><strong>「両側にコピー」でやった事を応用</strong>すれば、右辺も抽出できます。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>-1</strong></td>
<td><strong>2</strong></td>
<td><strong>-1</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
</table>
</div>
<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx9.jpeg"><img alt="convEx9.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx9-thumb-420x174-21.jpeg" width="420" height="174" class="mt-image-none" style="" /></a></span></p>
<div>同様に、上辺と下辺を抽出することで、基本的な輪郭検出の行列になります。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>-1</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>-1</strong></td>
<td><strong>4</strong></td>
<td><strong>-1</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>-1</strong></td>
<td><strong>0</strong></td>
</tr>
</table>
</div>
<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx10.jpeg"><img alt="convEx10.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx10-thumb-420x174-22.jpeg" width="420" height="174" class="mt-image-none" style="" /></a></span><br />
※ちなみに、この行列を使ったエッジ検出をラプラシアンフィルタというらしい。</p>
<h4>エンボス</h4>
<div>エンボスは輪郭検出に似ています。<br />
<strong>輪郭検出と違うところは、斜め1方向だけにとどめるところ</strong>です。</div>
<div style='clear: none;'>
<table>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>0</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td><strong>0</strong></td>
<td><strong>-1</strong></td>
</tr>
</table>
</div>
<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx11.jpeg"><img alt="convEx11.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx11-thumb-420x174-27.jpeg" width="420" height="174" class="mt-image-none" style="" /></a></span><br />
このままだとただの輪郭ですが、行列の計算時に各値を128加算（オフセット）すると、以下のようになります。<br />
（いまのところ、このツールにはオフセットを設定する機能は省略してあるので、実際には↓のような画面を見ることはできません。。）<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx12.jpeg"><img alt="convEx12.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx12-thumb-420x174-29.jpeg" width="420" height="174" class="mt-image-none" style="" /></a></span><br />
四角形の上辺と左辺に影が落ちてみえるのが不思議ですよね。<br />
なぜ128オフセットしたのに、ここだけ黒（0）なのでしょうか？<br />
四角形の左上角のひとつ斜め左上のピクセルをポイントしてみましょう。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx13.jpeg"><img alt="convEx13.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/convEx13-thumb-420x253-31.jpeg" width="420" height="253" class="mt-image-none" style="" /></a></span><br />
見た目は黒ですが、計算結果である「new pixel」値が(-255)になっています。<br />
このため、1<strong>28が加算されてもグレーにはならず</strong>黒い影のように見えるというわけです。<br />
それに対し、<strong>値が0の黒いピクセルは、オフセットにより128となり</strong>グレーになります。<br />
うまいことできてますね。</p>
<h4>カラー画像の場合</h4>
<p>今回は単純なグレースケール画像で色々見てきましたが、カラー画像になっても理屈は同じだと思います。<br />
R、G、B各チャンネル（グレースケール画像）に対して同じ事が行われるだけです。</p>
<h4>ここまでのまとめ</h4>
<p>webで検索してもなかなかリソースが少ないConvolutionFilterですが、正直、人文系Flash使いとしては、ロジカルにこれを追いかけるのはこの辺りが限界。数学的バックグラウンドを持っている人は、もっとエレガントに説明してくれるはず。<br />
奇才の登場を待ちましょう。。<br />
次回は、ConvolutionFilterを使ったアニメーションの可能性について探ってみたいと思います。<br />
<a href="http://www.imajuk.com/blog/archives/2009/03/convolutionfilter_4.html">つづく&#8230;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2009/02/convolutionflter_3.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ConvolutionFilterで遊ぶ その2</title>
		<link>http://www.imajuk.com/blog/archives/2009/02/convolutionflter_2.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=convolutionflter_2</link>
		<comments>http://www.imajuk.com/blog/archives/2009/02/convolutionflter_2.html#comments</comments>
		<pubDate>Fri, 20 Feb 2009 20:41:15 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript2]]></category>
		<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=50</guid>
		<description><![CDATA[前回の続きです。 ConvolutionFilterの理解を深めながら遊ぶためのツールを作ってみました。 >>ツールを表示する 画面左上の大きな画像がメインビューです。ここにフィルタの適用結果が表示されます。 メインビュ &#8230; <a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_2.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html">前回</a>の続きです。<br />
ConvolutionFilterの理解を深めながら遊ぶためのツールを作ってみました。<br />
<a href="http://www.imajuk.com/conv/cnvExpr.html" target="_blank"> >>ツールを表示する</a></p>
<hr />
画面左上の大きな画像がメインビューです。ここにフィルタの適用結果が表示されます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="mainView.jpg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/mainView.jpg" width="406" height="306" class="mt-image-none" style="" /></span><br />
メインビューの下にあるボタンをクリックすると、ローカルまたはネット上にある他の画像と差し替える事もできます。<br />
<strong>（ネット上にある画像を読み込むにはFlashからのアクセスを許可するためのcrossdomain.xmlが設置されている必要があります。）</strong><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="loadgui.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/loadgui.jpeg" width="238" height="22" class="mt-image-none" style="" /></span><br />
メインビューにマウスカーソルを移動すると、カーソル付近の拡大画像が表示されます。<br />
左がフィルタ適用後で右がオリジナル画像です。<br />
<strong>中央のピクセルが、いまカーソルがポイントしているピクセルになります。</strong><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="zoomView.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/zoomView.jpeg" width="333" height="188" class="mt-image-none" style="" /></span><br />
オリジナルのピクセルがどういう計算を経て新しいピクセルに変換されるかをExpressionで確認できます。<br />
計算方法については<a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html">前回のエントリー</a>を参照して下さい。<br />
「use Hex」をチェックすると、数値が16進数表記になります。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="expression.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/expression.jpeg" width="200" height="316" class="mt-image-none" style="" /></span><br />
KernelはConvolutionFilterに使う行列です。<br />
いまのところ<strong>3&#215;3の固定</strong>になっています。(将来拡張予定)<br />
この数値を変更すると、フィルタの適用結果がメインビューの画像に反映されます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="kernel.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/kernel.jpeg" width="136" height="115" class="mt-image-none" style="" /></span><br />
いくつかの代表的な行列が、あらかじめプリセットとして用意されています。<br />
プリセットから何か選択するとKernelとメインビューに反映されます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="preset.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/preset.jpeg" width="136" height="80" class="mt-image-none" style="" /></span><br />
Kernelの数値を変更して、気に入ったエフェクトが出来たら、「Add」をクリックするとプリセットに追加されます。<br />
これはSharedObjectに保存されるので、次回ツールを起動したときにもプリセットに表示されます。<br />
プリセットからアイテムを削除したい場合は、Controlキー（MacはCommandキー）を押しながら<br />
プリセット全体をデフォルトにリセットしたい時は「Revert」をクリックします。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="add_revert.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/add_revert.jpeg" width="136" height="101" class="mt-image-none" style="" /></span><br />
ConvolutionFilterを連続して適用するとどうなるかを実験するにはこのインターフェイスを使います。<br />
&#9654;ボタンをクリックすると、連続してフィルタを適用します。<br />
×ボタンをクリックすると、適用されたフィルタをリセットします。<br />
スライダーでフィルタを適用するインターバルを調節できます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="repeat.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/repeat.jpeg" width="221" height="60" class="mt-image-none" style="" /></span><br />
作業中の画像やカーネルの値等は、URLパラメータとして渡すことができます。<br />
パラメータつきURLが画面下部に表示されているので、このURLを保存しておけば作業の続きが再開できます。<br />
また「Save as Bookmark」をクリックするとブラウザのブックマークとして保存できます。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="bookmark.jpeg" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/bookmark.jpeg" width="725" height="31" class="mt-image-none" style="" /></span></p>
<hr />
次回はこのツールを使って、さらにConvolutionFilterの挙動を探っていきたいと思います。<br />
<a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_3.html">つづく&#8230;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2009/02/convolutionflter_2.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ConvolutionFilterで遊ぶ その１</title>
		<link>http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=convolutionflter</link>
		<comments>http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html#comments</comments>
		<pubDate>Thu, 19 Feb 2009 14:03:33 +0000</pubDate>
		<dc:creator>imajuk</dc:creator>
				<category><![CDATA[ActionScript2]]></category>
		<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://imajuk.sakura.ne.jp/blog/?p=49</guid>
		<description><![CDATA[Flash8からネイティブに実装されているConvolutionFilterですが、自分はあまり理解していなかったので色々遊んでみました。 ConvolutionFilterで出来る事 ConvolutionFilter &#8230; <a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html">続きを読む <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Flash8からネイティブに実装されている<a href="http://livedocs.adobe.com/flex/201_jp/langref/flash/filters/ConvolutionFilter.html">ConvolutionFilter</a>ですが、自分はあまり理解していなかったので色々遊んでみました。</p>
<h4>ConvolutionFilterで出来る事</h4>
<p>ConvolutionFilterを使うとガウスぼかしやエンボス等、いわゆるビットマップエフェクトが可能になるようです。<br />
DisplacementMapFilterと併用すると、Photoshopのフィルターの多くをFlashでシミュレートできるんじゃないかと妄想しています。</p>
<h4>ConvolutionFilterとは</h4>
<p>ConvolutionFilterは、一言でいうと<strong>ピクセルの色を変更するフィルター</strong>です。<br />
ピクセルの色を変換するという意味ではColorTransformに似ていますが、<br />
ColorTransformは係数のみでピクセルの色を計算、変更するのに対し、<br />
ConvolutionFilterは計算時に、<strong>変更対象になるピクセルの周辺のピクセルも考慮します。<br />
この係数は行列を使って定義します。</strong></p>
<div>
<table>
<tr>
<td>&nbsp;</td>
<td><strong>ColorTransform</strong></td>
<td><strong>Convolution</strong></td>
</tr>
<tr>
<td><strong>周辺のピクセル</strong></td>
<td>考慮しない</td>
<td>考慮する</td>
</tr>
</table>
</div>
<h4>ConvolutionFilterで行われる計算</h4>
<p>話を簡単にするため、7x7pxのグレースケールの画像を例に考えてみます。<br />
以下の図は、7x7pxのグレースケールの画像を拡大したものです。<br />
各ピクセルは0（黒）〜255（白）の強さを持っています。<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="File.png" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/File.png" width="151" height="151" class="mt-image-none" style="" /></span><br />
図中に示したピクセルeに、以下のような3&#215;3の行列を使ってConvolutionFilterを適用した場合、次のような計算が行われます。</p>
<div style='clear: none;'>
<table>
<tr>
<td>a <strong>-.5</strong></td>
<td>b <strong>0</strong></td>
<td>c <strong>0</strong></td>
</tr>
<tr>
<td>d <strong>0</strong></td>
<td>e <strong>.5</strong></td>
<td>f <strong>.5</strong></td>
</tr>
<tr>
<td>g <strong>0</strong></td>
<td>h <strong>0</strong></td>
<td>i <strong>0</strong></td>
</tr>
</table>
</div>
<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="File-1.png" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/File-1.png" width="151" height="151" class="mt-image-none" style="" /></span></p>
<ol>
<li>ピクセルeを含む周囲9ピクセル（a~i）と行列の数値が1:1で対応し、各ピクセルの強さと対応する行列の数値をかけ算します。<br />
例えば、ピクセルaは白（255）で、行列のaの数値（-0.5）とかけ算します。<br />
<strong>a x -0.5 = 255 x -0.5 = -128</strong><br />
同様に、bからiまでのピクセルを計算します。<br />
<strong>b x 0 = 255 x 0 = 0<br />
c x 0 = 255 x 0 = 0<br />
d x 0 = 255 x 0 = 0<br />
e x 0.5 = 255 x 0.5 = 128<br />
f x 0.5 = 255 x 0.5 = 128<br />
g x 0 = 255 x 0 = 0<br />
h x 0 = 255 x 0 = 0<br />
i x 0 = 255 x 0 = 0</strong>
</li>
<li>9ピクセル全てについてかけ算が終わったら計算結果を足し合わせます。<br />
<strong>-128 + 0 + 0 + 0 + 128 + 128 + 0 + 0 + 0 = 128</strong><br />
この足し合わせた数値<strong>128</strong>が、新しいピクセルの強さです。<br />
つまり、255（白）だったピクセルeが128（グレー）に変更されます。<br />
<strong><em>（この計算結果をさらに割ったりオフセットしたりすることもありますが、このエントリーでは詳しくは扱いません。）</em></strong>
</li>
<li>この操作を、画像の全てのピクセルに対してそれぞれ行います。<br />
図は、ConvolutionFilterの最終的な適用結果です。<br />
<strong>before</strong><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="before.png" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/before.png" width="151" height="151" class="mt-image-none" style="" /></span><br />
<strong>after</strong><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="after.png" src="http://www.imajuk.com/blog/wp-content/uploads/fromOldBlog/after.png" width="151" height="151" class="mt-image-none" style="" /></span>
</li>
</ol>
<p>理屈は簡単ですよね？<br />
例では3&#215;3の行列を使いましたが、4&#215;4でも3&#215;1でも行列であればどんな行列でも使えるようです。<br />
<strong>行列の大きさが変わるとフィルタ適用時に考慮する周辺ピクセルの数が変わる</strong>というわけですね。<br />
さて、理屈は非常にシンプルなConvolutionFIlterですが、行列から適用結果を想像する事がすごーく難しいです。<br />
そこで、理解を深めるためにツールを作ってみました。<br />
ツールの使い方を簡単に説明した後、このツールを使ってさらにConvolutionFilterを探求していきます。<br />
<a href="http://www.imajuk.com/blog/archives/2009/02/convolutionflter_2.html">つづく&#8230;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

