イベントのデリバリ

SoundToysの中の音声波形表示は、WaveEditorで使われているGraphMorphのコードを、Tweakのプログラミングモデルにあわせて書き直しながら実装していっています。GraphMorphで実装している、リアルタイム性を実現するための非同期処理の仕組みをTweakに移すのに、Tweakのイベントのデリバリがどのようなタイミング・順番で実行されるのかよくわかっていなかったので、いまさらですが簡単な実験で確認しました。

テストコード

CPushButton subclass: #CTest
	instanceVariableNames: '<?xml  version="1.0" ?>
<fields>
</fields>'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Experimental'!

!CTest methodsFor: 'events' stamp: 'KR 4/6/2006 12:24'!
onFire
	<on: fire>
	Transcript show: 'startFire'; cr.
	Transcript show: '1'; cr.
	self signal: #XXX.
	Transcript show: '2'; cr.
	self signal: #XXX.
	Transcript show: 'endFire'; cr.! !

!CTest methodsFor: 'events' stamp: 'KR 4/6/2006 12:24'!
onXXX
	<on: XXX>
	Transcript show: 'startXXX'; cr.
	self signal: #YYY.
	Transcript show: 'endXXX'; cr.! !

!CTest methodsFor: 'events' stamp: 'KR 4/6/2006 12:24'!
onYYY
	<on: YYY>
	Transcript show: 'onYYY'; cr.
! !

実行結果

ウィジェットを作成してボタンを押したときのTranscriptへの出力

startFire
1
2
endFire
startXXX
endXXX
onYYY

わかったこと

  • イベントルーチンは他のイベントルーチンで割り込まれない。シリアルにスケジュールされて実行される。これは、Microsoft系言語であるような同期的なイベントルーチン呼び出しと異なるところです。慣れないといけないな。
  • 同じイベントが複数回 #signal: されてたまっている場合、実際に起動されるのは1回である(参照: http://tweak.impara.de/ABOUT/FAQ/#Q1C , http://impara.de/pipermail/tweak/2004-July/000088.html
  • Tweakのデバッガではイベントの連鎖が表示され、それぞれ独立して実行できるが、これはデバッガの中だけである。デバッガの中でなければ、上のようにスケジュールされて順に実行される(参照: http://tweak.impara.de/TECHNOLOGY/Whitepapers/TweakEventDebugging/ )
  • Transcript出力をしているコードをデバッガで実行している場合、TweakのTranscript表示処理もイベント経由で行われているため、思ったようなタイミングでTranscript表示されない。これはとても使いにくいので、回避策が欲しいところです。