root/as3/Thread/trunk/src/org/libspark/thread/Monitor.as

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

Thread: branches/soumen を trunk にマージ

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.utils.Dictionary;
31         import flash.utils.setTimeout;
32         import flash.utils.clearTimeout;
33
34         /**
35          * Monitor クラスは IMonitor インターフェイスの実装クラスで、モニタ機構の最も一般的な実装を提供します.
36          *
37          * @author      yossy:beinteractive
38          */
39         public class Monitor implements IMonitor
40         {
41                 /**
42                  * 新しい Monitor クラスのインスタンスを生成します.
43                  */
44                 public function Monitor()
45                 {
46                 }
47                
48                 private var _waitors:Array;
49                 private var _timeoutList:Dictionary;
50                
51                 /**
52                  * ウェイトセットを返します.
53                  *
54                  * @return      ウェイトセット
55                  * @private
56                  */
57                 private function getWaitors():Array
58                 {
59                         return _waitors || (_waitors = []);
60                 }
61                
62                 /**
63                  * タイムアウトを設定します.
64                  *
65                  * @param       thread  設定するスレッド
66                  * @param       timeout タイムアウトするまでの時間
67                  * @private
68                  */
69                 private function registerTimeout(thread:Thread, timeout:uint):void
70                 {
71                         // マップがなければ生成
72                         if (_timeoutList == null) {
73                                 _timeoutList = new Dictionary();
74                         }
75                        
76                         // タイムアウトを設定して、thread をキーにして タイムアウトID を保存
77                         _timeoutList[thread] = setTimeout(timeoutHandler, timeout, thread);
78                 }
79                
80                 /**
81                  * タイムアウトを解除します.
82                  *
83                  * @param       thread  解除するスレッド
84                  * @private
85                  */
86                 private function unregisterTimeout(thread:Thread):void
87                 {
88                         // マップがなければ何もしない
89                         if (_timeoutList == null) {
90                                 return;
91                         }
92                        
93                         // thread をキーにして タイムアウトID を検索
94                         var id:Object = _timeoutList[thread];
95                        
96                         // 見つかったらタイムアウトを解除する
97                         if (id != null) {
98                                 clearTimeout(uint(id));
99                                 delete _timeoutList[thread];
100                         }
101                 }
102                
103                 /**
104                  * @inheritDoc
105                  */
106                 public function wait(timeout:uint = 0):void
107                 {
108                         // カレントスレッドを取得
109                         var thread:Thread = Thread.getCurrentThread();
110                        
111                         // スレッドに wait するよう依頼
112                         thread.monitorWait(timeout != 0, this);
113                        
114                         // 待機セットに並ばせる
115                         getWaitors().push(thread);
116                        
117                         // 待機時間が設定されている場合、タイムアウトハンドラを設定
118                         if (timeout != 0) {
119                                 registerTimeout(thread, timeout);
120                         }
121                 }
122                
123                 /**
124                  * @inheritDoc
125                  */
126                 public function notify():void
127                 {
128                         // 待機しているスレッドがいなければ何もしない
129                         if (_waitors == null || _waitors.length < 1) {
130                                 return;
131                         }
132                        
133                         // スレッドをひとつ取り出す
134                         var thread:Thread = Thread(_waitors.shift());
135                        
136                         // タイムアウトを解除
137                         unregisterTimeout(thread);
138                        
139                         // スレッドを起こす
140                         thread.monitorWakeup(this);
141                 }
142                
143                 /**
144                  * @inheritDoc
145                  */
146                 public function notifyAll():void
147                 {
148                         // 待機しているスレッドがいなければ何もしない
149                         if (_waitors == null || _waitors.length < 1) {
150                                 return;
151                         }
152                        
153                         // 例外保存用
154                         var ex:Object = null;
155                        
156                         // 全てのスレッドを起こす
157                         for each (var thread:Thread in _waitors) {
158                                
159                                 // タイムアウトを解除
160                                 unregisterTimeout(thread);
161                                
162                                 // ここで try-catch を行うのは確実に全てのスレッドを起こすため
163                                 try {
164                                         thread.monitorWakeup(this);
165                                 }
166                                 catch (e:Object) {
167                                         // 最初に起きた例外は保存
168                                         if (ex == null) {
169                                                 ex = e;
170                                         }
171                                 }
172                         }
173                        
174                         // 待機セットを空にする
175                         _waitors.length = 0;
176                        
177                         // 例外が発生していた場合は再スロー
178                         if (ex != null) {
179                                 throw ex;
180                         }
181                 }
182                
183                 /**
184                  * タイムアウトした際に実行されるハンドラです.
185                  *
186                  * @param       thread  タイムアウトしたスレッド
187                  * @private
188                  */
189                 private function timeoutHandler(thread:Thread):void
190                 {
191                         // 既に待機セットが空になっていたら何もしない
192                         if (_waitors == null || _waitors.length < 1) {
193                                 return;
194                         }
195                        
196                         // 待機セットから該当するスレッドを検索
197                         var index:int = _waitors.indexOf(thread);
198                        
199                         // 見つからなければ何もしない
200                         if (index == -1) {
201                                 return;
202                         }
203                        
204                         // 待機セットから削除
205                         _waitors.splice(index, 1);
206                        
207                         // スレッドを起こす
208                         thread.monitorTimeout(this);
209                 }
210                
211                 /**
212                  * @inheritDoc
213                  */
214                 public function leave(thread:Thread):void
215                 {
216                         // 既に待機セットが空になっていたら何もしない
217                         if (_waitors == null || _waitors.length < 1) {
218                                 return;
219                         }
220                        
221                         // 待機セットから該当するスレッドを検索
222                         var index:int = _waitors.indexOf(thread);
223                        
224                         // 見つからなければ何もしない
225                         if (index == -1) {
226                                 return;
227                         }
228                        
229                         // 待機セットから削除
230                         _waitors.splice(index, 1);
231                        
232                         // タイムアウトを解除
233                         unregisterTimeout(thread);
234                 }
235         }
236 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。