root/as3/Thread/branches/soumen/src/org/libspark/thread/Thread.as

リビジョン 637, 49.8 kB (コミッタ: yossy, コミット時期: 4 年 前)

Thread(soumen): どきゅどきゅどっきゅん☆ASDoc 完遂

Line 
1 /*
2  * ActionScript Thread Library
3  *
4  * Licensed under the MIT License
5  *
6  * Copyright (c) 2008 BeInteractive! (www.be-interactive.org) and
7  *                    Spark project  (www.libspark.org)
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  *
27  */
28 package org.libspark.thread
29 {
30         import flash.events.Event;
31         import flash.events.IEventDispatcher;
32         import flash.utils.Dictionary;
33         import flash.utils.getQualifiedClassName;
34         import flash.utils.getQualifiedSuperclassName;
35         import flash.utils.getDefinitionByName;
36         import org.libspark.thread.errors.CurrentThreadNotFoundError;
37         import org.libspark.thread.errors.IllegalThreadStateError;
38         import org.libspark.thread.errors.InterruptedError;
39         import org.libspark.thread.errors.ThreadLibraryNotInitializedError;
40        
41         /**
42          * Thread クラスは ActionScript Thread Library 1.0 (そうめん) の核となるクラスで、擬似スレッドを実現します.
43          *
44          * <p>ここで実現される擬似スレッドは、タスクシステムと Java のスレッドモデルをベースとしています。
45          * 処理をいくつかのメソッドに切り分け、呼び出すメソッド (「<em>実行関数</em>」と呼びます) を切り替えつつ
46          * 順々に実行していくことで、処理を進めます。</p>
47          *
48          * <p>新しいスレッドを作成するためには、まず Thread クラスのサブクラスを作成します。
49          * このサブクラスは、 Thread クラスの run メソッドをオーバーライドする必要があります。
50          * たとえば、「Hello, Thread!!」と出力するスレッドは、次のようになります。</p>
51          * <listing>public class HelloThread extends Thread
52          * {
53          *     override protected function run():void
54          *     {
55          *         trace('Hello, Thread!!');
56          *     }
57          * }</listing>
58          *
59          * <p>作成したスレッドを実行するためには、 Thread Library を初期化する必要があります。
60          * 次のように、 Thread クラスの静的メソッド initialize を呼び出すことで初期化を行います。
61          * このとき、引数に IThreadExecutor インターフェイスの実装クラスのインスタンスを指定します。
62          * この IThreadExecutor インスタンスは、「いつスレッドを実行するか」を決める重要な役割を担っています。
63          * ここでは、 EnterFrameThreadExecutor クラスのインスタンスを渡し、フレーム実行のタイミングで
64          * スレッドが実行されるようにしています。初期化処理は、アプリケーションの最初で一度だけ行えば、その後呼び出す必要はありません。</p>
65          * <listing>Thread.initialize(new EnterFrameThreadExecutor());</listing>
66          *
67          * <p>最後に、次のように HelloThread クラスのインスタンスを作り、 start メソッドを呼び出すことで、
68          * スレッドの実行を開始します。</p>
69          * <listing>var t:Thread = new HelloThread();
70          * t.start();</listing>
71          *
72          * <p>スレッドは親子関係を形成します。この親子関係は、スレッドの実行開始時に決定されます。
73          * スレッドの start を呼び出したスレッド (つまりカレントスレッド) は、親スレッドとなり、
74          * start が呼び出されたスレッドは、その親スレッドの子スレッドとなります。
75          * ただし、 start の呼び出しがスレッドの外 (つまりカレントスレッドが null のとき) に行われた場合、
76          * start が呼び出されたスレッドはトップレベルスレッドとなります。</p>
77          *
78          * <p>スレッドの親子関係は、スレッドの実行順序と例外の伝播において重要になります。
79          * スレッドの実行は、一番最初に開始されたトップレベルスレッドから始まります。今、このスレッドを A と呼ぶことにします。
80          * A に子スレッドがいる場合、 A の実行よりも先にまず、子スレッドが、開始された順番で実行されます。
81          * この子スレッドが実行されるとき、その子スレッドにさらに子スレッド (Aから見て孫スレッド) がいる場合、
82          * その子スレッドの実行より先に孫スレッドが開始された順番で実行され、これが子スレッドがいなくなるまで続けられます。
83          * 全ての A の子スレッドの実行が終了すると、 A が実行され、次に、A の次に開始されたトップレベルスレッドの実行が
84          * 同様にして続きます。</p>
85          *
86          * <p>スレッド内で例外が発生し、その例外が、例外が発生したスレッド内で捕捉されなかった場合、
87          * 例外は親スレッドに伝播します。例外が発生したのがトップレベルスレッドで、親スレッドがいない場合、
88          * 例外は uncaughtErrorHandler に渡されます。</p>
89          *
90          * <p>子スレッドよりも先に親スレッドが終了した場合、その親スレッドの全ての子スレッドは孤児スレッドとなり、
91          * トップレベルスレッドとして再配置されます。</p>
92          *
93          * <p>スレッドはある時点で、以下のいずれかの状態を取ります。これらの値は ThreadState クラスで定義されており、
94          * state プロパティを通して知ることができます。</p>
95          * <ul>
96          * <li>NEW</li>
97          * <li>RUNNABLE</li>
98          * <li>WAITING</li>
99          * <li>TIMED_WAITING</li>
100          * <li>TERMINATING</li>
101          * <li>TERMINATED</li>
102          * </ul>
103          *
104          * <p>スレッドが生成されると、まずはじめに状態は「NEW」に設定されます。この後、 start メソッドによって
105          * スレッドが開始されると、状態は「RUNNABLE」に設定されます。「NEW」以外の状態のスレッドを start メソッドによって
106          * 開始することはできません。</p>
107          *
108          * <p>wait メソッド、 join メソッド等の呼び出しによってスレッドが待機状態になる場合、状態は「WAITING」に
109          * 設定されます。このとき、タイムアウトが設定されるか、sleep メソッドの呼び出しである場合、状態は「TIMED_WAITING」に
110          * 設定されます。待機状態が解除されると状態は元に戻ります。</p>
111          *
112          * <p>スレッドが終了フェーズに移行すると、状態は「TERMINATING」に設定されます。スレッドが終了フェーズから
113          * 実行フェーズに戻ることは無く、同様に状態が「TERMINATING」から「RUNNABLE」に戻ることもありません。
114          * 終了フェーズが終わり、完全にスレッドが終了すると、状態は「TERMINATED」に設定されます。</p>
115          *
116          * <p>スレッドの動作を視覚的に知りたい場合、以下の動作チャートを見ることをお勧めします。</p>
117          * <ul>
118          * <li>http://www.libspark.org/htdocs/as3/thread-files/behavior-chart.png</li>
119          * </ul>
120          *
121          * @author      yossy:beinteractive
122          * @see #run()
123          * @see #initialize()
124          * @see #start()
125          * @see #uncaughtErrorHandler()
126          * @see #state
127          * @see ThreadState
128          * @see http://www.libspark.org/htdocs/as3/thread-files/behavior-chart.png
129          */
130         public class Thread extends Monitor
131         {
132                 private static var _executor:IThreadExecutor;
133                 private static var _threadIndex:uint = 0;
134                 private static var _currentThread:Thread = null;
135                 private static var _toplevelThreads:Array = [];
136                 private static var _uncaughtErrorHandler:Function = null;
137                
138                 /**
139                  * スレッドライブラリを初期化します.
140                  *
141                  * <p>このメソッドは、最初に一度だけ呼び出してください。</p>
142                  *
143                  * <p>スレッドの実行は、指定された IThreadExecutor インスタンスによって行われます。
144                  * (このメソッド内で、 IThreadExectuor#start が呼び出されます)</p>
145                  *
146                  * @param       executor        スレッドの実行を行う IThreadExecutor
147                  * @see IThreadExecutor
148                  */
149                 public static function initialize(executor:IThreadExecutor):void
150                 {
151                         _threadIndex = 0;
152                         _currentThread = null;
153                         _toplevelThreads.length = 0;
154                        
155                         // 古い IThreadExecutor の実行を止める
156                         if (_executor != null) {
157                                 _executor.stop();
158                         }
159                        
160                         _executor = executor;
161                        
162                         // 新しい IThreadExecutor の実行を開始
163                         if (_executor != null) {
164                                 _executor.start();
165                         }
166                 }
167                
168                 /**
169                  * initialize メソッドの呼び出しによって IThreadExecutor が設定され、スレッドが実行可能な状態であれば true、そうでなければ false を返します.
170                  *
171                  * @see #initialize()
172                  */
173                 public static function get isReady():Boolean
174                 {
175                         return _executor != null;
176                 }
177                
178                 /**
179                  * 現在実行中のスレッドを返します.
180                  *
181                  * <p>現在実行中のスレッドがない場合、 null を返します。</p>
182                  */
183                 public static function get currentThread():Thread
184                 {
185                         return _currentThread;
186                 }
187                
188                 /**
189                  * 現在実行中のスレッドを返します.
190                  *
191                  * <p>ただし、現在実行中のスレッドがない(currentThread が null)の場合は CurrentThreadNotFoundError をスローします。</p>
192                  *
193                  * @return      現在実行中のスレッド
194                  * @throws      org.libspark.thread.errors.CurrentThreadNotFoundError   現在実行中のスレッドがない場合
195                  * @private
196                  */
197                 internal static function getCurrentThread():Thread
198                 {
199                         var t:Thread = currentThread;
200                        
201                         if (t != null) {
202                                 return t;
203                         }
204                        
205                         throw new CurrentThreadNotFoundError('Expected Thread.currentThread is not null, but actual null.');
206                 }
207                
208                 /**
209                  * どのスレッドにも捕捉されなかった例外のためのハンドラを設定します.
210                  *
211                  * <p>スレッド内で例外が発生し、処理されないままトップレベルまで到達するとこのハンドラが呼び出されます。</p>
212                  *
213                  * <p>ここに登録する関数は、第一引数に発生した例外である Object と、第二引数に発生元のスレッドである Thread を引数としてとる必要があります。</p>
214                  */
215                 public static function get uncaughtErrorHandler():Function
216                 {
217                         return _uncaughtErrorHandler;
218                 }
219                
220                 /**
221                  * @private
222                  */
223                 public static function set uncaughtErrorHandler(value:Function):void
224                 {
225                         _uncaughtErrorHandler = value;
226                 }
227                
228                 /**
229                  * 例外ハンドラを取得します.
230                  *
231                  * <p>ただし、ユーザーによって例外ハンドラが設定されていない場合、デフォルトのハンドラを返します。</p>
232                  *
233                  * @return      ユーザーによって設定された例外ハンドラ。無い場合はデフォルトのハンドラ。
234                  * @private
235                  */
236                 private static function getUncaughtErrorHandler():Function
237                 {
238                         return uncaughtErrorHandler || defaultUncaughtErrorHandler;
239                 }
240                
241                 /**
242                  * 例外ハンドラのデフォルトの実装です.
243                  *
244                  * @param       e       発生した例外
245                  * @param       t       例外が発生したスレッド
246                  * @private
247                  */
248                 private static function defaultUncaughtErrorHandler(e:Object, t:Thread):void
249                 {
250                         trace((t ? t.toString() + ' ' : '') + (e is Error ? Error(e).getStackTrace() : e.toString()));
251                 }
252                
253                 /**
254                  * 全てのスレッドを実行します.
255                  *
256                  * <p>通常、このメソッドは IThreadExector インターフェイスの実装クラスによって呼び出されます。</p>
257                  */
258                 public static function executeAllThreads():void
259                 {
260                         // 全てのトップレベルスレッドを呼び出す
261                         var threads:Array = _toplevelThreads;
262                         var l:uint = threads.length;
263                         for (var i:uint = 0; i < l;) {
264                                 var thread:Thread = Thread(threads[i]);
265                                 if (!thread.execute()) {
266                                         // スレッドが終了した場合は削除
267                                         threads.splice(i, 1);
268                                         --l;
269                                 }
270                                 else {
271                                         ++i;
272                                 }
273                                 // 伝播すべき例外が発生している場合はキャッチされない例外ハンドラを呼び出す
274                                 // Note: _errorThread が null の場合、この例外はまだ伝播すべきではないことを示す
275                                 if (thread._error != null && thread._errorThread != null) {
276                                         try {
277                                                 getUncaughtErrorHandler()(thread._error, thread._errorThread);
278                                         }
279                                         catch (e:Object) {
280                                                 defaultUncaughtErrorHandler(e, null);
281                                         }
282                                         thread._error = null;
283                                         thread._errorThread = null;
284                                 }
285                         }
286                 }
287                
288                 /**
289                  * 指定されたスレッドをトップレベルスレッドとして追加します.
290                  *
291                  * @param       thread  追加するスレッド
292                  * @private
293                  */
294                 private static function addToplevelThread(thread:Thread):void
295                 {
296                         _toplevelThreads.push(thread);
297                 }
298                
299                 /**
300                  * 指定されたスレッドをトップレベルスレッドとして追加します.
301                  *
302                  * @param       threads 追加するスレッドの配列
303                  * @private
304                  */
305                 private static function addToplevelThreads(threads:Array):void
306                 {
307                         _toplevelThreads.push.apply(_toplevelThreads, threads);
308                 }
309                
310                 /**
311                  * 現在実行中のスレッドが次に実行する実行関数を設定します.
312                  *
313                  * <p>この設定は、スレッドの実行のたびにリセットされます。</p>
314                  *
315                  * <p>このメソッドの呼び出しによって次に実行する実行関数が設定されない場合、スレッドは終了フェーズへと移行します。</p>
316                  *
317                  * @param       func    次に実行する実行関数
318                  */
319                 public static function next(func:Function):void
320                 {
321                         getCurrentThread()._runHandler = func;
322                 }
323                
324                 /**
325                  * 現在実行中のスレッドおよびその子スレッドで例外が発生した場合に実行する実行関数を設定します.
326                  *
327                  * <p>ここで設定される実行関数は、発生した例外である Object と、例外が発生したスレッドである Thread のふたつの引数をとる関数である必要があります。</p>
328                  *
329                  * <p>この関数によって例外を処理できた (この関数内で再び例外が発生しなかった) 場合で、この関数内で
330                  * next メソッドによる実行関数の設定が行われなかった場合、例外が発生する前の実行関数の設定を復元します。</p>
331                  *
332                  * <p>この設定は、reset 引数が false に設定されない限り、スレッドの実行のたびにリセットされます。</p>
333                  *
334                  * @param       klass   どの型の例外が発生した場合に関数を実行するかを示すクラス
335                  * @param       func    例外が発生した際に実行される実行関数
336                  * @param       reset   次の実行のタイミングでこの設定を削除する場合には true、そうでなければ false
337                  */
338                 public static function error(klass:Class, func:Function, reset:Boolean = true):void
339                 {
340                         if (func != null) {
341                                 getCurrentThread().addErrorHandler(klass, func, reset);
342                         }
343                         else {
344                                 getCurrentThread().removeErrorHandler(klass);
345                         }
346                 }
347                
348                 /**
349                  * 現在実行中のスレッドが待機中にタイムアウトした場合に実行する実行関数を設定します.
350                  *
351                  * <p>この設定は、スレッドの実行のたびにリセットされます。</p>
352                  *
353                  * @param       func    タイムアウトした場合に実行する実行関数
354                  */
355                 public static function timeout(func:Function):void
356                 {
357                         getCurrentThread()._timeoutHandler = func;
358                 }
359                
360                 /**
361                  * 現在実行中のスレッドが指定されたイベントが発生した場合に実行する実行関数を設定します.
362                  *
363                  * <p>ここで設定される実行関数は、発生したイベントである Event を引数にとる関数である必要があります。</p>
364                  *
365                  * <p>このメソッドによってイベントハンドラが設定される場合、スレッドは自動的にイベントが発生するまで待機状態となります。
366                  * ただし、 next メソッドによって次に実行する実行関数が設定される場合、待機状態にはならず、実行が継続されます。</p>
367                  *
368                  * <p>この設定は、スレッドの実行のたびにリセットされます。</p>
369                  *
370                  * @param       dispatcher      イベントリスナーの登録先となるディスパッチャ
371                  * @param       type    捕捉するイベント名
372                  * @param       func    イベントが発生した場合に実行する実行関数
373                  * @param       useCapture      flash.events.IEventDispatcher#addEventListener() の該当する引数を参照してください。
374                  * @param       priority        flash.events.IEventDispatcher#addEventListener() の該当する引数を参照してください。
375                  * @param       useWeakReference        flash.events.IEventDispatcher#addEventListener() の該当する引数を参照してください。
376                  * @see flash.events.IEventDispatcher#addEventListener()
377                  */
378                 public static function event(dispatcher:IEventDispatcher, type:String, func:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
379                 {
380                         getCurrentThread().addEventHandler(dispatcher, type, func, useCapture, priority, useWeakReference);
381                 }
382                
383                 /**
384                  * 現在実行中のスレッドの実行を、指定された時間だけ中断させます.
385                  *
386                  * <p>指定された時間が経過すると、 sleep メソッドが呼び出されなかった場合と同様に実行が再開されます。</p>
387                  *
388                  * <p>スレッドの実行が中断しても、子スレッドの実行が中断されることはありません。</p>
389                  *
390                  * @param       time    実行を中断させる時間 (ミリ秒)
391                  */
392                 public static function sleep(time:uint):void
393                 {
394                         // time が 0 だと永遠に待ってしまうので最低でも 1 にする
395                         if (time == 0) {
396                                 time = 1;
397                         }
398                        
399                         // カレントスレッドを取得
400                         var current:Thread = getCurrentThread();
401                        
402                         // sleep 用のモニタがなければ生成
403                         if (current._sleepMonitor == null) {
404                                 current._sleepMonitor = new Monitor();
405                         }
406                        
407                         // sleep 用のモニタを使って wait をかけて指定時間眠らせる
408                         current._sleepMonitor.wait(time);
409                 }
410                
411                 /**
412                  * 現在実行中のスレッドが待機中に割り込まれた場合に実行する実行関数を設定します.
413                  *
414                  * <p>このメソッドによって割り込みハンドラが設定されていない状態で、待機中に割り込みが発生すると、
415                  * 例外 InterruptedError が発生します。</p>
416                  *
417                  * <p>この設定はスレッドの実行のたびにリセットされます。</p>
418                  *
419                  * @param       func    待機中に割り込まれた場合に実行する実行関数
420                  */
421                 public static function interrupted(func:Function):void
422                 {
423                         getCurrentThread()._interruptedHandler = func;
424                 }
425                
426                 /**
427                  * 現在のスレッドが割り込まれているかどうかを調べます.
428                  *
429                  * <p>このメソッドによりスレッドの「割り込みステータス」がクリアされます。
430                  * つまり、このメソッドが続けて2回呼び出された場合、2回目の呼び出しは false を返します。</p>
431                  *
432                  * @return      現在のスレッドが割り込まれている場合は true、そうでない場合は false
433                  */
434                 public static function checkInterrupted():Boolean
435                 {
436                         // カレントスレッドを取得
437                         var current:Thread = getCurrentThread();
438                        
439                         // 割り込みステータスを取得
440                         var status:Boolean = current._isInterrupted;
441                        
442                         // ステータスが設定されている場合はクリア
443                         if (status) {
444                                 current._isInterrupted = false;
445                         }
446                        
447                         // ステータスを返す
448                         return status;
449                 }
450                
451                 /**
452                  * 新しい Thread クラスのインスタンスを生成します.
453                  */
454                 public function Thread()
455                 {
456                         _id = ++_threadIndex;
457                         _name = 'Thread' + _id;
458                         _state = ThreadState.NEW;
459                         _runningState = ThreadState.NEW;
460                         _children = null;
461                         _runHandler = null;
462                         _savedRunHandler = null;
463                         _timeoutHandler = null;
464                         _interruptedHandler = null;
465                         _waitMonitor = null;
466                         _joinMonitor = null;
467                         _sleepMonitor = null;
468                         _eventMonitor = null;
469                         _event = null;
470                         _errorHandlers = null;
471                         _error = null;
472                         _errorThread = null;
473                         _eventHandlers = null;
474                         _isInterrupted = false;
475                 }
476                
477                 private var _id:uint;
478                 private var _name:String;
479                 private var _state:uint;
480                 private var _runningState:uint;
481                 private var _children:Array;
482                 private var _runHandler:Function;
483                 private var _savedRunHandler:Function;
484                 private var _timeoutHandler:Function;
485                 private var _interruptedHandler:Function;
486                 private var _waitMonitor:IMonitor;
487                 private var _joinMonitor:IMonitor;
488                 private var _sleepMonitor:IMonitor;
489                 private var _eventMonitor:IMonitor;
490                 private var _event:Event;
491                 private var _errorHandlers:Dictionary;
492                 private var _error:Object;
493                 private var _errorThread:Thread;
494                 private var _eventHandlers:Array;
495                 private var _isInterrupted:Boolean;
496                
497                 /**
498                  * このスレッドのユニークな識別子を返します.
499                  *
500                  * <p>initialize メソッドが呼び出されない限り、ふたつのスレッドに同じ id が割り振られることはありません。</p>
501                  */
502                 public function get id():uint
503                 {
504                         return _id;
505                 }
506                
507                 /**
508                  * このスレッドの名前を設定します.
509                  */
510                 public function get name():String
511                 {
512                         return _name;
513                 }
514                
515                 /**
516                  * @private
517                  */
518                 public function set name(value:String):void
519                 {
520                         _name = value;
521                 }
522                
523                 /**
524                  * このスレッドのクラス名を返します.
525                  *
526                  * <p>デフォルトでは、 getQualifiedClassName メソッドを使用してクラス名を取得します。</p>
527                  */
528                 public function get className():String
529                 {
530                         var names:Array = getQualifiedClassName(this).split(/::/);
531                         return names.length == 2 ? names[1] : names[0];
532                 }
533                
534                 /**
535                  * このスレッドの状態を返します.
536                  *
537                  * <p>返される値は、 ThreadState クラスで定義されている定数のいずれかになります。</p>
538                  *
539                  * @see ThreadState
540                  */
541                 public function get state():uint
542                 {
543                         return _state;
544                 }
545                
546                 /**
547                  * このスレッドが割り込まれている場合は true、そうでない場合は false を返します.
548                  *
549                  * <p>このプロパティが true を返すようになるのは、待機状態<em>でない</em>スレッドに対して、
550                  * interrupt メソッドで割り込んだ場合です。</p>
551                  *
552                  * @see #interrupt()
553                  */
554                 public function get isInterrupted():Boolean
555                 {
556                         return _isInterrupted;
557                 }
558                
559                 /**
560                  * スレッドを開始します.
561                  *
562                  * <p>スレッドが既に開始されている場合 (state が NEW でない場合) は IllegalThreadStateError が
563                  * スローされます。</p>
564                  *
565                  * <p>スレッドライブラリが初期化されていない状態の場合 (isReady が false の場合) は ThreadLibraryNotInitializedError が
566                  * スローされます。</p>
567                  *
568                  * <p>あるスレッドの実行中にこのメソッドが呼び出された場合、そのスレッドはこのメソッドが呼び出されたスレッドの親スレッドとなり、
569                  * このメソッドが呼び出されたスレッドは子スレッドとなります。</p>
570                  *
571                  * <p>スレッドが実行中で無い場合にこのメソッドが呼び出された場合、このメソッドが呼び出されたスレッドはトップレベルスレッドとなります。</p>
572                  *
573                  * <p>このメソッドが呼び出されると、実行関数はまず run メソッドに設定されます。</p>
574                  *
575                  * @throws      org.libspark.thread.errors.IllegalThreadStateError      スレッドが既に開始されている場合
576                  * @throws      org.libspark.thread.errors.ThreadLibraryNotInitializedError     スレッドライブラリが初期化されていない場合
577                  */
578                 public function start():void
579                 {
580                         // 初期化されていなければエラー
581                         if (!isReady) {
582                                 throw new ThreadLibraryNotInitializedError('Thread Library is not initialized. Please call Thread#initialize before.');
583                         }
584                        
585                         // 既に実行されていたらエラー
586                         if (_state != ThreadState.NEW) {
587                                 throw new IllegalThreadStateError('Thread is already running.');
588                         }
589                        
590                         // state を実行フェーズに切り替える
591                         _state = ThreadState.RUNNABLE;
592                         _runningState = ThreadState.RUNNABLE;
593                        
594                         // 次の実行関数を run に設定
595                         _runHandler = run;
596                        
597                         // カレントスレッドを取得
598                         var current:Thread = currentThread;
599                        
600                         if (current != null) {
601                                 // カレントスレッドがある(=別のスレッド内で start された)場合はそのスレッドの子となる
602                                 current.addChildThread(this);
603                         }
604                         else {
605                                 // カレントスレッドがない場合はトップレベルスレッドとなる
606                                 addToplevelThread(this);
607                         }
608                 }
609                
610                 /**
611                  * このスレッドを待機状態に移行させます.
612                  *
613                  * <p>このメソッドは IMonitor インターフェイスの実装クラスによって内部的にのみ呼び出されます。</p>
614                  *
615                  * @param       timeout タイムアウト付かどうか
616                  * @param       monitor 待機先のモニタ
617                  * @private
618                  */
619                 internal function monitorWait(timeout:Boolean, monitor:IMonitor):void
620                 {
621                         // wait できる状態でなければエラー
622                         if ((_state != ThreadState.RUNNABLE && _state != ThreadState.TERMINATING) || _waitMonitor != null) {
623                                 throw new IllegalThreadStateError('Thread can not wait.');
624                         }
625                        
626                         // state を待機状態に切り替える
627                         _state = timeout ? ThreadState.TIMED_WAITING : ThreadState.WAITING;
628                        
629                         // モニタを保存
630                         _waitMonitor = monitor;
631                 }
632                
633                 /**
634                  * このスレッドを待機状態から復帰させます.
635                  *
636                  * <p>このメソッドは IMonitor インターフェイスの実装クラスによって内部的にのみ呼び出されます。</p>
637                  *
638                  * @param       monitor 待機先のモニタ
639                  * @private
640                  */
641                 internal function monitorWakeup(monitor:IMonitor):void
642                 {
643                         // 待機状態でなければエラー
644                         if ((_state != ThreadState.WAITING && _state != ThreadState.TIMED_WAITING) || _waitMonitor != monitor) {
645                                 throw new IllegalThreadStateError('Thread can not wakeup.');
646                         }
647                        
648                         // state を実行状態に切り替える
649                         _state = _runningState;
650                        
651                         // 保存されていたモニタを破棄
652                         _waitMonitor = null;
653                 }
654                
655                 /**
656                  * このスレッドを待機状態からタイムアウトさせます.
657                  *
658                  * <p>このメソッドは IMonitor インターフェイスの実装クラスによって内部的にのみ呼び出されます。</p>
659                  *
660                  * @param       monitor 待機先のモニタ
661                  * @private
662                  */
663                 internal function monitorTimeout(monitor:IMonitor):void
664                 {
665                         // 待機時間付の待機状態でなければエラー
666                         if (_state != ThreadState.TIMED_WAITING || _waitMonitor != monitor) {
667                                 throw new IllegalThreadStateError('Thread can not wakeup.');
668                         }
669                        
670                         // state を実行状態に切り替える
671                         _state = _runningState;
672                        
673                         // sleep によるタイムアウトではない場合
674                         if (_waitMonitor != _sleepMonitor) {
675                                 // 次に実行する実行関数をタイムアウト用のものに切り替える
676                                 if (_timeoutHandler != null) {
677                                         _runHandler = _timeoutHandler;
678                                 }
679                         }
680                        
681                         // 保存されていたモニタを破棄
682                         _waitMonitor = null;
683                 }
684                
685                 /**
686                  * join 用のモニタを返します.
687                  *
688                  * @return      join 用のモニタ
689                  * @private
690                  */
691                 private function getJoinMonitor():IMonitor
692                 {
693                         return _joinMonitor || (_joinMonitor = new Monitor());
694                 }
695                
696                 /**
697                  * このスレッドが終了するまで、現在のスレッドを待機させます.
698                  *
699                  * @param       timeout 待機させる時間 (ミリ秒)。 0 を指定した場合、永遠に待ち続けます
700                  * @return      待機する必要がある場合は true、そうでない場合は false
701                  */
702                 public function join(timeout:uint = 0):Boolean
703                 {
704                         // 既に終了していたらそのまま帰る
705                         if (_state == ThreadState.TERMINATED) {
706                                 return false;
707                         }
708                        
709                         // join 用のモニタで wait する
710                         getJoinMonitor().wait(timeout);
711                        
712                         return true;
713                 }
714                
715                 /**
716                  * このスレッドに割り込みます.
717                  *
718                  * <p>このスレッドが待機中である場合、割り込みステータスはクリアされ、スレッドが起床します。
719                  * このとき、割り込みハンドラが設定されていれば実行関数を割り込みハンドラに設定して実行を再開し、
720                  * そうでない場合は InterruptedError を発生させます。</p>
721                  *
722                  * <p>待機中でない場合、このスレッドの割り込みステータスが設定されます。</p>
723                  */
724                 public function interrupt():void
725                 {
726                         if (_state == ThreadState.WAITING || _state == ThreadState.TIMED_WAITING) {
727                                 // 待機中の場合
728                                 // モニタに対して待機セットから抜けることを伝える
729                                 _waitMonitor.leave(this);
730                                 _waitMonitor = null;
731                                 // state を切り替える
732                                 _state = _runningState;
733                                 // 割り込みハンドラがあれば実行関数を割り込みハンドラに設定
734                                 if (_interruptedHandler != null) {
735                                         _runHandler = _interruptedHandler;
736                                 }
737                                 else {
738                                         // 割り込みハンドラがなければ例外を発生
739                                         _error = new InterruptedError();
740                                 }
741                         }
742                         else {
743                                 // そうでない場合は割り込みステータスを設定
744                                 _isInterrupted = true;
745                         }
746                 }
747                
748                 /**
749                  * 子スレッドの配列を返します.
750                  *
751                  * @return      子スレッドの配列
752                  * @private
753                  */
754                 private function getChildren():Array
755                 {
756                         return _children || (_children = []);
757                 }
758                
759                 /**
760                  * 子スレッドを子スレッドの配列に追加します.
761                  *
762                  * @param       thread  追加する子スレッド
763                  * @private
764                  */
765                 private function addChildThread(thread:Thread):void
766                 {
767                         getChildren().push(thread);
768                 }
769                
770                 /**
771                  * エラーハンドラマップを返します.
772                  *
773                  * @return      エラーハンドラマップ
774                  * @private
775                  */
776                 private function getErrorHandlers():Dictionary
777                 {
778                         return _errorHandlers || (_errorHandlers = new Dictionary());
779                 }
780                
781                 /**
782                  * エラーハンドラをエラーハンドラマップに追加します.
783                  *
784                  * @param       klass   エラークラス
785                  * @param       handler エラーハンドラ
786                  * @param       reset   リセットするか
787                  * @private
788                  */
789                 private function addErrorHandler(klass:Class, handler:Function, reset:Boolean):void
790                 {
791                         getErrorHandlers()[getQualifiedClassName(klass)] = new ErrorHandler(handler, reset);
792                 }
793                
794                 /**
795                  * エラーハンドラをエラーハンドラマップから削除します.
796                  *
797                  * @param       klass   エラークラス
798                  * @private
799                  */
800                 private function removeErrorHandler(klass:Class):void
801                 {
802                         // ハンドラマップが存在しなければ何もしない
803                         if (_errorHandlers == null) {
804                                 return;
805                         }
806                        
807                         // ハンドラマップから削除
808                         delete _errorHandlers[getQualifiedClassName(klass)];
809                 }
810                
811                 /**
812                  * エラーハンドラマップをリセットします.
813                  *
814                  * @private
815                  */
816                 private function resetErrorHandlers():void
817                 {
818                         // ハンドラマップが存在しなければ何もしない
819                         if (_errorHandlers == null) {
820                                 return;
821                         }
822                        
823                         // 登録されているハンドラを巡回
824                         for (var key:String in _errorHandlers) {
825                                 // reset が true であればハンドラを削除する
826                                 if (ErrorHandler(_errorHandlers[key]).reset) {
827                                         delete _errorHandlers[key];
828                                 }
829                         }
830                 }
831                
832                 /**
833                  * 指定されたエラーに該当するエラーハンドラを返します.
834                  *
835                  * @param       error   エラー
836                  * @return      該当するエラーハンドラ。無ければ null
837                  * @private
838                  */
839                 private function getErrorHandler(error:Object):ErrorHandler
840                 {
841                         // ハンドラマップが存在しなければ null を返す
842                         if (_errorHandlers == null) {
843                                 return null;
844                         }
845                        
846                         // error のクラス名を取得
847                         var className:String = getQualifiedClassName(error);
848                        
849                         // クラス名が取得できる限り回す
850                         while (className != null) {
851                                 // ハンドラマップからクラス名をキーにしてハンドラを検索する
852                                 var handler:ErrorHandler = _errorHandlers[className];
853                                 // 見つかればそれを返す
854                                 if (handler != null) {
855                                         return handler;
856                                 }
857                                 // 見つからなければ、スーパークラスを辿る
858                                 try {
859                                         className = getQualifiedSuperclassName(getDefinitionByName(className));
860                                 }
861                                 catch (e:ReferenceError) {
862                                         // ここで出る ReferenceError は getDefinitionByName によるもの
863                                         // プライベートクラス等の場合に起こりうる
864                                         className = null;
865                                 }
866                         }
867                        
868                         return null;
869                 }
870                
871                 /**
872                  * イベント待機用のモニタを返します.
873                  *
874                  * @return      イベント待機用のモニタ
875                  * @private
876                  */
877                 private function getEventMonitor():IMonitor
878                 {
879                         return _eventMonitor || (_eventMonitor = new Monitor());
880                 }
881                
882                 /**
883                  * イベントハンドラの配列を返します.
884                  *
885                  * @return      イベントハンドラの配列
886                  * @private
887                  */
888                 private function getEventHandlers():Array
889                 {
890                         return _eventHandlers || (_eventHandlers = []);
891                 }
892                
893                 /**
894                  * イベントハンドラをイベントハンドラの配列に追加します.
895                  *
896                  * @param       dispatcher      ディスパッチャ
897                  * @param       type    イベントタイプ
898                  * @param       func    イベントハンドラ
899                  * @param       useCapture      addEventListener 参照
900                  * @param       priority        addEventListener 参照
901                  * @param       useWeakReference        addEventListener 参照
902                  * @private
903                  */
904                 private function addEventHandler(dispatcher:IEventDispatcher, type:String, func:Function, useCapture:Boolean, priority:int, useWeakReference:Boolean):void
905                 {
906                         // イベントハンドラを作成してリストに追加
907                         getEventHandlers().push(new EventHandler(dispatcher, type, eventHandler, func, useCapture, priority, useWeakReference));
908                 }
909                
910                 /**
911                  * イベントハンドラの配列をリセットします.
912                  *
913                  * @private
914                  */
915                 private function resetEventHandlers():void
916                 {
917                         // イベントハンドラリストがなければ何もしない
918                         if (_eventHandlers == null) {
919                                 return;
920                         }
921                        
922                         // 全てのイベントハンドラの登録を解除
923                         for each (var handler:EventHandler in _eventHandlers) {
924                                 handler.unregister();
925                         }
926                        
927                         // 配列を初期化
928                         _eventHandlers.length = 0;
929                 }
930                
931                 /**
932                  * イベントが発生した際に実行されるハンドラです.
933                  *
934                  * @param       e       発生したイベント
935                  * @param       handler 該当するイベントハンドラ
936                  * @private
937                  */
938                 private function eventHandler(e:Event, handler:EventHandler):void
939                 {
940                         // 既にイベントが起こっていれば何もしない
941                         if (_event != null) {
942                                 return;
943                         }
944                        
945                         // イベントを保存
946                         _event = e;
947                        
948                         // 該当するイベントハンドラを次の実行関数に設定
949                         _runHandler = handler.func;
950                        
951                         // イベントハンドラをリセット
952                         resetEventHandlers();
953                        
954                         // 待機状態である場合
955                         if (_waitMonitor != null) {
956                                 // モニタに対して待機セットから抜けることを伝える
957                                 _waitMonitor.leave(this);
958                                 // 保存されていたモニタを破棄
959                                 _waitMonitor = null;
960                         }
961                        
962                         // state を実行状態に切り替える
963                         _state = _runningState;
964                        
965                         // 入れ子になる場合があるのでカレントスレッドを保存
966                         var current:Thread = _currentThread;
967                        
968                         try {
969                                 // そしてすぐ実行してみる
970                                 internalExecute(null, this);
971                         }
972                         finally {
973                                 // カレントスレッドを復元
974                                 _currentThread = current;
975                         }
976                 }
977                
978                 /**
979                  * 子スレッドを含め、このスレッドを実行します.
980                  *
981                  * @return      このスレッドの実行が継続していれば true、そうでなければ (実行が終了したら) false
982                  * @private
983                  */
984                 private function execute():Boolean
985                 {
986                         // まだ start していなければ何もしない
987                         if (_state == ThreadState.NEW) {
988                                 return true;
989                         }
990                         // 既に終了していれば何もしない
991                         if (_state == ThreadState.TERMINATED) {
992                                 return false;
993                         }
994                        
995                         // 発生した例外
996                         var error:Object = _error;
997                         var errorThread:Thread = _errorThread || this;
998                        
999                         // すべての子スレッドを呼び出す
1000                         var children:Array = _children;
1001                         if (children != null) {
1002                                 var cl:uint = children.length;
1003                                 for (var ci:uint = 0; ci < cl; ) {
1004                                         var child:Thread = Thread(children[ci]);
1005                                         if (!child.execute()) {
1006                                                 // 終了したら削除
1007                                                 children.splice(ci, 1);
1008                                                 --cl;
1009                                         }
1010                                         else {
1011                                                 ++ci;
1012                                         }
1013                                         // 子スレッドで例外が起きていたら一番最初のものを保存
1014                                         // Note: _errorThread が null の場合、その例外はまだ親に伝播するべきではないことを示す
1015                                         if (child._error != null && child._errorThread != null && error == null) {
1016                                                 error = child._error;
1017                                                 errorThread = child._errorThread;
1018                                                 child._error = null;
1019                                                 child._errorThread = null;
1020                                         }
1021                                 }
1022                         }
1023                        
1024                         return internalExecute(error, errorThread);
1025                 }
1026                
1027                 /**
1028                  * このスレッドを実行します.
1029                  *
1030                  * <p>子スレッドは実行されません。</p>
1031                  *
1032                  * @param       error   ここに来るまでに発生したエラー
1033                  * @param       errorThread     エラーが発生した場合、その発生元のスレッド
1034                  * @return      このスレッドの実行が継続していれば true、そうでなければ (実行が終了したら) false
1035                  * @private
1036                  */
1037                 private function internalExecute(error:Object, errorThread:Thread):Boolean
1038                 {
1039                         if (_state == ThreadState.WAITING || _state == ThreadState.TIMED_WAITING) {
1040                                 if (error != null) {
1041                                         // 待機状態で子スレッドによる例外発生していた場合は無理やり起きる
1042                                         // モニタに対して待機セットから抜けることを伝える
1043                                         _waitMonitor.leave(this);
1044                                         _waitMonitor = null;
1045                                         // state を切り替える
1046                                         _state = _runningState;
1047                                 }
1048                                 else {
1049                                         // 例外が発生していない場合はここでリターン
1050                                         return true;
1051                                 }
1052                         }
1053                        
1054                         // 今回実行する実行関数
1055                         var runHandler:Function = null;
1056                         // エラーハンドラ
1057                         var errorHandler:ErrorHandler = null;
1058                        
1059                         if (error != null) {
1060                                
1061                                 // 例外が発生していた場合は例外ハンドラを選択する
1062                                 errorHandler = getErrorHandler(error);
1063                                
1064                                 if (errorHandler != null) {
1065                                         // ハンドラが見つかった場合
1066                                         // 例外が子から伝播してきた場合、割り込まれていると考え実行関数を保存する
1067                                         if (errorThread != this) {
1068                                                 _savedRunHandler = _runHandler;
1069                                         }
1070                                         else {
1071                                                 // 子からの伝播でない場合、自力で処理したということで保存されている例外をクリア
1072                                                 _error = null;
1073                                         }
1074                                         // 実行関数をエラーハンドラに設定
1075                                         runHandler = errorHandler.handler;
1076                                 }
1077                                 else {
1078                                         // 見つからなかった場合はこのスレッドは終了フェーズに移行し親に例外を伝播する
1079                                         if (_runningState != ThreadState.TERMINATING) {
1080                                                 // 既に終了フェーズでない場合のみ
1081                                                 // state を終了フェーズに切り替える
1082                                                 _state = ThreadState.TERMINATING;
1083                                                 _runningState = ThreadState.TERMINATING;
1084                                                 // 実行関数を finalize に設定
1085                                                 runHandler = finalize;
1086                                         }
1087                                         // 親に伝播するよう例外を保存
1088                                         _error = error;
1089                                         _errorThread = errorThread;
1090                                 }
1091                         }
1092                         else {
1093                                 // 子スレッドによる例外が発生していない場合は前回指定された実行関数を設定
1094                                 runHandler = _runHandler;
1095                         }
1096                        
1097                         // 実行関数をリセット
1098                         _runHandler = null;
1099                         // タイムアウトハンドラをリセット
1100                         _timeoutHandler = null;
1101                         // イベントハンドラをリセット
1102                         resetEventHandlers();
1103                         // エラーハンドラをリセット
1104                         resetErrorHandlers();
1105                         // 割り込みハンドラをリセット
1106                         _interruptedHandler = null;
1107                        
1108                         // エラーハンドラが実行されようとしている場合、実行終了後に復帰できるように保存しておいた実行関数を設定
1109                         if (errorHandler != null) {
1110                                 _runHandler = _savedRunHandler;
1111                         }
1112                        
1113                         // Note: finalize の最後で wait が入って待機状態になった後に起きた等の場合に、
1114                         //       runHandler が null の状態でここに到達することがある
1115                         if (runHandler != null) {
1116                                
1117                                 // カレントスレッドを設定
1118                                 _currentThread = this;
1119                                
1120                                 try {
1121                                         // 実行関数を呼び出す
1122                                         if (errorHandler != null) {
1123                                                 // エラーハンドラである場合は例外と例外の発生元のスレッドを引数として渡す
1124                                                 runHandler.apply(this, [error, errorThread]);
1125                                         }
1126                                         else if (_event != null) {
1127                                                 var ev:Event = _event;
1128                                                 _event = null;
1129                                                 // イベントハンドラである場合はイベントを渡す
1130                                                 runHandler.apply(this, [ev]);
1131                                         }
1132                                         else {
1133                                                 // それ以外の場合は引数なしで呼び出す
1134                                                 runHandler.apply(this);
1135                                         }
1136                                 }
1137                                 catch (e:Object) {
1138                                         // 例外が発生した場合例外を保存
1139                                         _error = e;
1140                                         // エラーハンドラ以外で例外が発生し、かつ該当するエラーハンドラが存在する場合
1141                                         if (errorHandler == null && getErrorHandler(e) != null) {
1142                                                 // 自力で例外を回復できる可能性があるので強制的に runHandler を非 null にして次に繰り越す
1143                                                 // このとき、エラーハンドラ実行後に復帰するために runHandler を保存しておく
1144                                                 // run はダミーで意味はない
1145                                                 _savedRunHandler = _runHandler;
1146                                                 _runHandler = run;
1147                                         }
1148                                         else {
1149                                                 // それ以外の場合は例外を親に伝播する必要がある
1150                                                 // 例外が親に伝播するように発生元スレッドを設定
1151                                                 _errorThread = this;
1152                                                 // 実行関数の設定をクリアして強制的に終了フェーズに移行させる
1153                                                 _runHandler = null;
1154                                         }
1155                                        
1156                                 }
1157                                 finally {
1158                                         // カレントスレッドを元に戻す
1159                                         _currentThread = null;
1160                                 }
1161                         }
1162                        
1163                         // 今エラーハンドラを実行し、かつエラーが発生していない場合、保存しておいた実行関数はもう必要ないので破棄
1164                         if (errorHandler != null && _error == null) {
1165                                 _savedRunHandler = null;
1166                         }
1167                        
1168                         // イベントハンドラが設定された場合
1169                         if (_eventHandlers != null && _eventHandlers.length > 0) {
1170                                 // エラーが発生していなければ
1171                                 if (_error == null) {
1172                                         // 全てのイベントハンドラを登録
1173                                         for each (var eventHandler:EventHandler in _eventHandlers) {
1174                                                 eventHandler.register();
1175                                         }
1176                                         // 次に実行する実行関数が設定されていない場合で
1177                                         if (_runHandler == null) {
1178                                                 // まだ待機状態で無い場合、自動で待機状態に移行する
1179                                                 if (_waitMonitor == null) {
1180                                                         try {
1181                                                                 _currentThread = this;
1182                                                                 getEventMonitor().wait();
1183                                                         }
1184                                                         finally {
1185                                                                 _currentThread = null;
1186                                                         }
1187                                                 }
1188                                         }
1189                                 }
1190                         }
1191                        
1192                         if (_runHandler != null) {
1193                                 // 次に実行する実行関数が設定されている場合実行を継続
1194                         }
1195                         else {
1196                                 // 次に実行する実行関数が設定されていない場合
1197                                 if (_state == ThreadState.WAITING || _state == ThreadState.TIMED_WAITING) {
1198                                         // 待機状態に入っている場合は次に繰り越す
1199                                 }
1200                                 else if (_runningState == ThreadState.TERMINATING) {
1201                                         // 終了フェーズだった場合は実行を終了する
1202                                         // 自分の子スレッドを、孤児スレッドとしてトップレベルに移動する
1203                                         if (_children != null) {
1204                                                 addToplevelThreads(_children);
1205                                                 // 子スレッドは破棄
1206                                                 _children = null;
1207                                         }
1208                                         // state を終了状態に切り替える
1209                                         _state = ThreadState.TERMINATED;
1210                                         _runningState = ThreadState.TERMINATED;
1211                                         // join 用のモニタが存在(=join 待ちしているスレッドが存在)すれば notifyAll で起こす
1212                                         if (_joinMonitor != null) {
1213                                                 _joinMonitor.notifyAll();
1214                                                 _joinMonitor = null;
1215                                         }
1216                                         // 終了
1217                                         return false;
1218                                 }
1219                                 else {
1220                                         // 終了フェーズでない場合は終了フェーズに入る
1221                                         // state を終了フェーズに切り替える
1222                                         _state = ThreadState.TERMINATING;
1223                                         _runningState = ThreadState.TERMINATING;
1224                                         // 次の実行関数を finalize に設定
1225                                         _runHandler = finalize;
1226                                 }
1227                         }
1228                        
1229                         return true;
1230                 }
1231                
1232                 /**
1233                  * このメソッドをオーバーライドして、スレッドの処理を記述します.
1234                  *
1235                  * <p>start メソッドが呼び出され、スレッドの実行が開始されると、まずはじめにこのメソッドが実行関数として設定され、
1236                  * スレッドが実行されます。</p>
1237                  *
1238                  * <p>このメソッド内で next メソッドを呼び出すことにより、次の実行関数を設定することができます。
1239                  * 次の実行関数が設定されない場合、スレッドは終了フェーズへと移行します。</p>
1240                  *
1241                  * <p>next メソッドのほか、 wait, join, sleep, event, timeout, error, interrupted といった
1242                  * メソッドを呼び出すことで、スレッドの動作を様々に制御することができます。</p>
1243                  *
1244                  * @see #next()
1245                  * @see #join()
1246                  * @see #sleep()
1247                  * @see #event()
1248                  * @see #timeout()
1249                  * @see #error()
1250                  * @see #interrupted()
1251                  * @see #interrupt()
1252                  * @see #finalize()
1253                  */
1254                 protected function run():void
1255                 {
1256                        
1257                 }
1258                
1259                 /**
1260                  * このメソッドをオーバーライドして、スレッドの終了処理を記述します.
1261                  *
1262                  * <p>スレッドが終了フェーズに移行すると、必ずこのメソッドが実行関数に設定され、スレッドが実行されます。
1263                  * 例外が発生したりした場合でも、必ず終了フェーズに移行するので、スレッドが終了する前にはこのメソッドが実行されることが
1264                  * 確実に保証されています。</p>
1265                  *
1266                  * <p>このメソッドも実行関数と同じ扱いであるため、 next をはじめとするメソッドによってスレッドを制御することが可能です。</p>
1267                  *
1268                  * <p>スレッドはこのメソッドを利用して終了処理を行い、いかなる状況でも安全に終了することを保証するべきです。</p>
1269                  */
1270                 protected function finalize():void
1271                 {
1272                        
1273                 }
1274                
1275                 /**
1276                  * このスレッドの名前を整形して返します.
1277                  *
1278                  * <p>デフォルトでは、</p>
1279                  * <pre>'[' + className + ' ' + name + ']'</pre>
1280                  * <p>と等価な値が返されます。</p>
1281                  *
1282                  * <p>このメソッドの呼び出し結果は、 toString メソッドなどで使用されます。</p>
1283                  *
1284                  * @param       name    スレッドの名前
1285                  * @return      整形された名前
1286                  */
1287                 protected function formatName(name:String):String
1288                 {
1289                         return '[' + className + ' ' + name + ']';
1290                 }
1291                
1292                 /**
1293                  * このスレッドの文字列表現を返します.
1294                  *
1295                  * <p>デフォルトでは、 formatName メソッドを、このスレッドの名前を引数にして呼び出した結果です。</p>
1296                  *
1297                  * @return      このスレッドの文字列表現
1298                  */
1299                 public function toString():String
1300                 {
1301                         return formatName(name);
1302                 }
1303         }
1304 }
1305
1306 import flash.events.Event;
1307 import flash.events.IEventDispatcher;
1308
1309 class ErrorHandler
1310 {
1311         public function ErrorHandler(handler:Function, reset:Boolean)
1312         {
1313                 this.handler = handler;
1314                 this.reset = reset;
1315         }
1316        
1317         public var handler:Function;
1318         public var reset:Boolean;
1319 }
1320
1321 class EventHandler
1322 {
1323         public function EventHandler(dispatcher:IEventDispatcher, type:String, listener:Function, func:Function, useCapture:Boolean, priority:int, useWeakReference:Boolean)
1324         {
1325                 this.dispatcher = dispatcher;
1326                 this.type = type;
1327                 this.listener = listener;
1328                 this.func = func;
1329                 this.useCapture = useCapture;
1330                 this.priority = priority;
1331                 this.useWeakReference = useWeakReference;
1332         }
1333        
1334         public var dispatcher:IEventDispatcher;
1335         public var type:String;
1336         public var listener:Function;
1337         public var func:Function;
1338         public var useCapture:Boolean;
1339         public var priority:int;
1340         public var useWeakReference:Boolean;
1341        
1342         public function register():void
1343         {
1344                 dispatcher.addEventListener(type, handler, useCapture, priority, useWeakReference);
1345         }
1346        
1347         public function unregister():void
1348         {
1349                 dispatcher.removeEventListener(type, handler, useCapture);
1350         }
1351        
1352         private function handler(e:Event):void
1353         {
1354                 listener(e, this);
1355         }
1356 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。