/as3/Thread/trunk/src/org/libspark/thread/Thread.as (DL, SVN)


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