EventThreadについて

個人的に結構悩んでいるのでまとめておこうと思う。最初に断っておくが主観満載である。

EventThreadは、eventを処理するためのThread. run()またはそこから呼ばれた関数でひたすらevent()を並べてそれを処理するThreadのこととする。そうめんではeventListenerのadd/removeから開放されるとかで長所の一つになっている。
さて、EventThreadはThreadなので、もちろんいくらでも同時に走らせることができる。たとえば、ウィンドウのなかにAというボタンとBというボタンがあって、AのMouseEvent.CLICKの処理と、BのMouseEvent.CLICKの処理は同じEventThreadに書いても書かなくてもいい。
で、この間、TLife内にあるEventThreadをまとめようかそうしないか悩んだのでこういうエントリになったわけだ。

とりあえずまとめたコードとまとめてないコードを両方おいておく。

// まとめた
public class ABEventThread extends Thread {
	protected override function run() : void {
		event(A, MouseEvent.CLICK, onClickA);
		event(B, MouseEvent.CLICK, onClickB);
	}

	private function onClickA(e : MouseEvent) : void {
		trace("A");
		next(run);
	}

	private function onClickB(e : MouseEvent) : void {
		trace("B");
		next(run);
	}
}

// 呼び出しコード例
new ABEventThread().start();
// まとめてない
public class AEventThread extends Thread {
	protected override function run() : void {
		event(A, MouseEvent.CLICK, onClickA);
	}

	private function onClickA(e : MouseEvent) : void {
		trace("A");
		next(run);
	}
}

public class BEventThread extends Thread {
	protected override function run() : void {
		event(B, MouseEvent.CLICK, onClickB);
	}

	private function onClickB(e : MouseEvent) : void {
		trace("B");
		next(run);
	}
}

// 呼び出しコード例
new AEventThread().start();
new BEventThread().start();

さて、これらには一長一短ある。それを述べる。便宜上、まとめた場合をX, まとめない場合をYとする。

Eventの同時発生

XとYで一番異なる挙動がここだと思う。たとえば、同じボタンでMouseEvent.CLICKとMouseEvent.MOUSE_DOWNをXで記述すると、どっちかが(CLICKだったかな)捨てられてしまいハンドラが呼ばれないが、Yだと捨てられない。この点でYは有利だが、こういう場合もある。
上の例で一方を押したときの処理中にもう一方を押させたくないという処理をXは自然に導入している。Yでこれを実現しようとすると、Threadのインスタンスを他のインスタンスから参照できるようにしなければならない。*1 *2

同一関数へのアクセス

たとえば、AとBの処理内で、同じ関数にアクセスしたいというときはどうだろう。他のクラスに関数を書く以外の選択肢なら、Xは勿論Threadの中に書けるが、Yは関数を複製してそれぞれのThreadに置くか、一方に置いた関数を読みに行かないといけない。他のクラスからその関数を使う機会がないのであれば、Thread内に書くのが一番簡潔なので、この点ではXが有利である。

ファイル数

AS3では大体1ファイル1クラスである。単純に考えるとYのほうがファイル数が多くなって少々辛い。だがぶっちゃけいうと、Threadを導入している段階で1ファイル増えているので、あんまり気にするべきではないかもしれない。

可読性・可搬性

もちろんYのほうがこの点では有利であるが、可読性・可搬性は最初2つと比べると些細な違いなんじゃないかなと思う。

このぐらいだろうか。ちなみにTLifeには、現時点ではX, Y両方採用している。メイン画面はイベントが同時発生しても処理できるようにYを、設定画面は同時発生しないようにXを採用している。

*1:enabled=falseにしろというのは無しで

*2:Aが押された場合にBを押せないようにして、Bが押された場合はAを押せるようにしろとかいう要求だったら逆に足を引っ張る