チェンジセット 520
- コミット日時:
- 2008/05/27 14:16:31 (6 ヶ月前)
- ファイル:
凡例:
- 変更無し
- 追加
- 削除
- 更新
- コピー
- 移動
as3/Thread/branches/soumen/src/org/libspark/thread/IMonitor.as
r509 r520 21 21 */ 22 22 function notifyAll():void; 23 24 /** 25 * 待機中に例外が発生した等の理由で、指定されたスレッドがこのモニタの待機セットから抜けることを伝えます。 26 * 通常、このメソッドは内部的にのみ使用され、ユーザーが呼び出す必要はありません。 27 * 28 * @param thread 待機セットから抜けるスレッド 29 */ 30 function leave(thread:Thread):void; 23 31 } 24 32 } as3/Thread/branches/soumen/src/org/libspark/thread/Monitor.as
r514 r520 54 54 55 55 // スレッドに wait するよう依頼 56 thread.monitorWait(timeout != 0 );56 thread.monitorWait(timeout != 0, this); 57 57 58 58 // 待機セットに並ばせる … … 79 79 80 80 // スレッドを起こす 81 thread.monitorWakeup( );81 thread.monitorWakeup(this); 82 82 } 83 83 … … 100 100 // ここで try-catch を行うのは確実に全てのスレッドを起こすため 101 101 try { 102 thread.monitorWakeup( );102 thread.monitorWakeup(this); 103 103 } 104 104 catch (e:Object) { … … 138 138 139 139 // スレッドを起こす 140 thread.monitorTimeout(); 140 thread.monitorTimeout(this); 141 } 142 143 public function leave(thread:Thread):void 144 { 145 // 既に待機セットが空になっていたら何もしない 146 if (_waitors == null || _waitors.length < 1) { 147 return; 148 } 149 150 // 待機セットから該当するスレッドを検索 151 var index:int = _waitors.indexOf(thread); 152 153 // 見つからなければ何もしない 154 if (index == -1) { 155 return; 156 } 157 158 // 待機セットから削除 159 _waitors.splice(index, 1); 160 161 // タイムアウトを解除 162 unregisterTimeout(thread); 141 163 } 142 164 as3/Thread/branches/soumen/src/org/libspark/thread/Thread.as
r517 r520 2 2 { 3 3 import flash.events.IEventDispatcher; 4 import flash.utils.Dictionary; 5 import flash.utils.getQualifiedClassName; 6 import flash.utils.getQualifiedSuperclassName; 7 import flash.utils.getDefinitionByName; 4 8 import org.libspark.thread.errors.CurrentThreadNotFoundError; 5 9 import org.libspark.thread.errors.IllegalThreadStateError; … … 11 15 private static var _currentThread:Thread = null; 12 16 private static var _toplevelThreads:Array = []; 17 private static var _uncaughtErrorHandler:Function = null; 13 18 14 19 /** … … 21 26 public static function initialize(executor:IThreadExecutor):void 22 27 { 23 //_threadIndex = 0;28 _threadIndex = 0; 24 29 _currentThread = null; 25 30 _toplevelThreads.length = 0; … … 71 76 public static function get uncaughtErrorHandler():Function 72 77 { 73 return null;78 return _uncaughtErrorHandler; 74 79 } 75 80 … … 79 84 public static function set uncaughtErrorHandler(value:Function):void 80 85 { 81 86 _uncaughtErrorHandler = value; 87 } 88 89 private static function getUncaughtErrorHandler():Function 90 { 91 return uncaughtErrorHandler || defaultUncaughtErrorHandler; 92 } 93 94 private static function defaultUncaughtErrorHandler(e:Object, t:Thread):void 95 { 96 trace((t ? t.toString() + ' ' : '') + (e is Error ? Error(e).getStackTrace() : e.toString())); 82 97 } 83 98 … … 100 115 ++i; 101 116 } 117 // 伝播すべき例外が発生している場合はキャッチされない例外ハンドラを呼び出す 118 // Note: _errorThread が null の場合、この例外はまだ伝播すべきではないことを示す 119 if (thread._error != null && thread._errorThraed != null) { 120 try { 121 getUncaughtErrorHandler()(thread._error, thread._errorThraed); 122 } 123 catch (e:Object) { 124 defaultUncaughtErrorHandler(e, null); 125 } 126 thread._error = null; 127 thread._errorThraed = null; 128 } 102 129 } 103 130 } … … 142 169 public static function error(klass:Class, func:Function, reset:Boolean = true):void 143 170 { 144 171 if (func != null) { 172 getCurrentThread().addErrorHandler(klass, func, reset); 173 } 174 else { 175 getCurrentThread().removeErrorHandler(klass); 176 } 145 177 } 146 178 … … 188 220 _children = null; 189 221 _runHandler = null; 222 _savedRunHandler = null; 190 223 _timeoutHandler = null; 224 _waitMonitor = null; 191 225 _joinMonitor = null; 226 _errorHandlers = null; 227 _error = null; 228 _errorThraed = null; 192 229 } 193 230 … … 198 235 private var _children:Array; 199 236 private var _runHandler:Function; 237 private var _savedRunHandler:Function; 200 238 private var _timeoutHandler:Function; 239 private var _waitMonitor:IMonitor; 201 240 private var _joinMonitor:IMonitor; 241 private var _errorHandlers:Dictionary; 242 private var _error:Object; 243 private var _errorThraed:Thread; 202 244 203 245 public function get id():uint … … 253 295 } 254 296 255 internal function monitorWait(timeout:Boolean ):void297 internal function monitorWait(timeout:Boolean, monitor:IMonitor):void 256 298 { 257 299 // wait できる状態でなければエラー 258 if ( _state != ThreadState.RUNNABLE && _state != ThreadState.TERMINATING) {300 if ((_state != ThreadState.RUNNABLE && _state != ThreadState.TERMINATING) || _waitMonitor != null) { 259 301 throw new IllegalThreadStateError('Thread can not wait.'); 260 302 } … … 262 304 // state を待機状態に切り替える 263 305 _state = timeout ? ThreadState.TIMED_WAITING : ThreadState.WAITING; 264 } 265 266 internal function monitorWakeup():void 306 307 // モニタを保存 308 _waitMonitor = monitor; 309 } 310 311 internal function monitorWakeup(monitor:IMonitor):void 267 312 { 268 313 // 待機状態でなければエラー 269 if ( _state != ThreadState.WAITING && _state != ThreadState.TIMED_WAITING) {314 if ((_state != ThreadState.WAITING && _state != ThreadState.TIMED_WAITING) || _waitMonitor != monitor) { 270 315 throw new IllegalThreadStateError('Thread can not wakeup.'); 271 316 } … … 273 318 // state を実行状態に切り替える 274 319 _state = _runningState; 275 } 276 277 internal function monitorTimeout():void 320 321 // 保存されていたモニタを破棄 322 _waitMonitor = null; 323 } 324 325 internal function monitorTimeout(monitor:IMonitor):void 278 326 { 279 327 // 待機時間付の待機状態でなければエラー 280 if (_state != ThreadState.TIMED_WAITING ) {328 if (_state != ThreadState.TIMED_WAITING || _waitMonitor != monitor) { 281 329 throw new IllegalThreadStateError('Thread can not wakeup.'); 282 330 } … … 284 332 // state を実行状態に切り替える 285 333 _state = _runningState; 334 335 // 保存されていたモニタを破棄 336 _waitMonitor = null; 286 337 287 338 // 次に実行する実行関数をタイムアウト用のものに切り替える … … 324 375 } 325 376 377 private function getErrorHandlers():Dictionary 378 { 379 return _errorHandlers || (_errorHandlers = new Dictionary()); 380 } 381 382 private function addErrorHandler(klass:Class, handler:Function, reset:Boolean):void 383 { 384 getErrorHandlers()[getQualifiedClassName(klass)] = new ErrorHandler(handler, reset); 385 } 386 387 private function removeErrorHandler(klass:Class):void 388 { 389 // ハンドラマップが存在しなければ何もしない 390 if (_errorHandlers == null) { 391 return; 392 } 393 394 // ハンドラマップから削除 395 delete _errorHandlers[getQualifiedClassName(klass)]; 396 } 397 398 private function resetErrorHandlers():void 399 { 400 // ハンドラマップが存在しなければ何もしない 401 if (_errorHandlers == null) { 402 return; 403 } 404 405 // 登録されているハンドラを巡回 406 for (var key:String in _errorHandlers) { 407 // reset が true であればハンドラを削除する 408 if (ErrorHandler(_errorHandlers[key]).reset) { 409 delete _errorHandlers[key]; 410 } 411 } 412 } 413 414 private function getErrorHandler(error:Object):ErrorHandler 415 { 416 // ハンドラマップが存在しなければ null を返す 417 if (_errorHandlers == null) { 418 return null; 419 } 420 421 // error のクラス名を取得 422 var className:String = getQualifiedClassName(error); 423 424 // クラス名が取得できる限り回す 425 while (className != null) { 426 // ハンドラマップからクラス名をキーにしてハンドラを検索する 427 var handler:ErrorHandler = _errorHandlers[className]; 428 // 見つかればそれを返す 429 if (handler != null) { 430 return handler; 431 } 432 // 見つからなければ、スーパークラスを辿る 433 try { 434 className = getQualifiedSuperclassName(getDefinitionByName(className)); 435 } 436 catch (e:ReferenceError) { 437 // ここで出る ReferenceError は getDefinitionByName によるもの 438 // プライベートクラス等の場合に起こりうる 439 className = null; 440 } 441 } 442 443 return null; 444 } 445 326 446 private function execute():Boolean 327 447 { … … 334 454 return false; 335 455 } 456 457 // 発生した例外 458 var error:Object = _error; 459 var errorThread:Thread = _errorThraed || this; 336 460 337 461 // すべての子スレッドを呼び出す … … 349 473 ++ci; 350 474 } 351 } 352 } 353 354 // 待機状態であればここでリターン 475 // 子スレッドで例外が起きていたら一番最初のものを保存 476 // Note: _errorThread が null の場合、その例外はまだ親に伝播するべきではないことを示す 477 if (child._error != null && child._errorThraed != null && error == null) { 478 error = child._error; 479 errorThread = child._errorThraed; 480 child._error = null; 481 child._errorThraed = null; 482 } 483 } 484 } 485 355 486 if (_state == ThreadState.WAITING || _state == ThreadState.TIMED_WAITING) { 356 return true; 357 } 358 359 // 今回実行する実行関数を保存 360 var runHandler:Function = _runHandler; 361 362 // ハンドラ郡の設定をクリア 487 if (error != null) { 488 // 待機状態で子スレッドによる例外発生していた場合は無理やり起きる 489 // モニタに対して待機セットから抜けることを伝える 490 _waitMonitor.leave(this); 491 _waitMonitor = null; 492 // state を切り替える 493 _state = _runningState; 494 } 495 else { 496 // 例外が発生していない場合はここでリターン 497 return true; 498 } 499 } 500 501 // 今回実行する実行関数 502 var runHandler:Function = null; 503 // エラーハンドラ 504 var errorHandler:ErrorHandler = null; 505 506 if (error != null) { 507 508 // 例外が発生していた場合は例外ハンドラを選択する 509 errorHandler = getErrorHandler(error); 510 511 if (errorHandler != null) { 512 // ハンドラが見つかった場合 513 // 例外が子から伝播してきた場合、割り込まれていると考え実行関数を保存する 514 if (errorThread != this) { 515 _savedRunHandler = _runHandler; 516 } 517 else { 518 // 子からの伝播でない場合、自力で処理したということで保存されている例外をクリア 519 _error = null; 520 } 521 // 実行関数をエラーハンドラに設定 522 runHandler = errorHandler.handler; 523 } 524 else { 525 // 見つからなかった場合はこのスレッドは終了フェーズに移行し親に例外を伝播する 526 if (_runningState != ThreadState.TERMINATING) { 527 // 既に終了フェーズでない場合のみ 528 // state を終了フェーズに切り替える 529 _state = ThreadState.TERMINATING; 530 _runningState = ThreadState.TERMINATING; 531 // 実行関数を finalize に設定 532 runHandler = finalize; 533 } 534 // 親に伝播するよう例外を保存 535 _error = error; 536 _errorThraed = errorThread; 537 } 538 } 539 else { 540 // 子スレッドによる例外が発生していない場合は前回指定された実行関数を設定 541 runHandler = _runHandler; 542 } 543 544 // 実行関数をリセット 363 545 _runHandler = null; 546 // タイムアウトハンドラをリセット 364 547 _timeoutHandler = null; 548 // エラーハンドラをリセット 549 resetErrorHandlers(); 550 551 // エラーハンドラが実行されようとしている場合、実行終了後に復帰できるように保存しておいた実行関数を設定 552 if (errorHandler != null) { 553 _runHandler = _savedRunHandler; 554 } 365 555 366 556 // Note: finalize の最後で wait が入って待機状態になった後に起きた等の場合に、 … … 373 563 try { 374 564 // 実行関数を呼び出す 375 runHandler.apply(this); 565 // エラーハンドラである場合は例外と例外の発生元のスレッドを引数として渡す 566 runHandler.apply(this, errorHandler != null ? [error, errorThread] : null); 567 } 568 catch (e:Object) { 569 // 例外が発生した場合例外を保存 570 _error = e; 571 // エラーハンドラ以外で例外が発生し、かつ該当するエラーハンドラが存在する場合 572 if (errorHandler == null && getErrorHandler(e) != null) { 573 // 自力で例外を回復できる可能性があるので強制的に runHandler を非 null にして次に繰り越す 574 // このとき、エラーハンドラ実行後に復帰するために runHandler を保存しておく 575 // run はダミーで意味はない 576 _savedRunHandler = _runHandler; 577 _runHandler = run; 578 } 579 else { 580 // それ以外の場合は例外を親に伝播する必要がある 581 // 例外が親に伝播するように発生元スレッドを設定 582 _errorThraed = this; 583 // 実行関数の設定をクリアして強制的に終了フェーズに移行させる 584 _runHandler = null; 585 } 586 376 587 } 377 588 finally { … … 379 590 _currentThread = null; 380 591 } 592 } 593 594 // 今エラーハンドラを実行し、かつエラーが発生していない場合、保存しておいた実行関数はもう必要ないので破棄 595 if (errorHandler != null && _error == null) { 596 _savedRunHandler = null; 381 597 } 382 598 … … 814 1030 } 815 1031 } 1032 1033 class ErrorHandler 1034 { 1035 public function ErrorHandler(handler:Function, reset:Boolean) 1036 { 1037 this.handler = handler; 1038 this.reset = reset; 1039 } 1040 1041 public var handler:Function; 1042 public var reset:Boolean; 1043 }
