OSDN Git Service

mavenによるビルドに変更
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / graphics / AsyncImageBuilder.java
1 package charactermanaj.graphics;\r
2 \r
3 import java.util.logging.Level;\r
4 import java.util.logging.Logger;\r
5 \r
6 \r
7 /**\r
8  * 各パーツ情報をもとに非同期にイメージを合成する\r
9  * @author seraphy\r
10  */\r
11 public class AsyncImageBuilder extends ImageBuilder implements Runnable {\r
12 \r
13         /**\r
14          * ロガー\r
15          */\r
16         private static final Logger logger = Logger.getLogger(AsyncImageBuilder.class.getName());\r
17 \r
18         /**\r
19          * 非同期にイメージを構築するためのジョブ定義.<br>\r
20          * リクエストを受け付けたことを示すイベントおよび、リクエストが放棄されたことを示すイベントを受け取ることができる.<br>\r
21          * @author seraphy\r
22          *\r
23          */\r
24         public interface AsyncImageBuildJob extends ImageBuildJob {\r
25                 /**\r
26                  * リクエストを受け付けた場合に呼び出される.<br>\r
27                  * @param ticket このイメージビルダでリクエストを受け付けた通し番号\r
28                  */\r
29                 void onQueueing(long ticket);\r
30                 \r
31                 /**\r
32                  * リクエストを処理するまえに破棄された場合に呼び出される.<br>\r
33                  */\r
34                 void onAbandoned();\r
35         }\r
36         \r
37         /**\r
38          * 同期オブジェクト\r
39          */\r
40         private final Object lock = new Object();\r
41         \r
42         /**\r
43          * チケットのシリアルナンバー.<br>\r
44          * リクエストがあるごとにインクリメントされる.<br>\r
45          */\r
46         private long ticketSerialNum = 0;\r
47         \r
48         /**\r
49          * リクエストされているジョブ、なければnull\r
50          */\r
51         private ImageBuildJob requestJob;\r
52 \r
53         /**\r
54          * 停止フラグ(volatile)\r
55          */\r
56         private volatile boolean stopFlag;\r
57         \r
58         /**\r
59          * スレッド\r
60          */\r
61         private Thread thread;\r
62         \r
63         /**\r
64          * イメージローダを指定して構築する.\r
65          * @param imageLoader イメージローダー\r
66          */\r
67         public AsyncImageBuilder(ColorConvertedImageCachedLoader imageLoader) {\r
68                 super(imageLoader);\r
69                 thread = new Thread(this);\r
70                 thread.setDaemon(true);\r
71         }\r
72         \r
73         /**\r
74          * スレッドの実行部.\r
75          */\r
76         public void run() {\r
77                 logger.log(Level.FINE, "AsyncImageBuilder thread started.");\r
78 \r
79                 // 停止フラグがたてられるまで繰り返す.\r
80                 while (!stopFlag) {\r
81                         try {\r
82                                 ImageBuildJob job;\r
83                                 synchronized (lock) {\r
84                                         while (!stopFlag && requestJob == null) {\r
85                                                 // ジョブリクエストがくるまで待機\r
86                                                 lock.wait(1000);\r
87                                         }\r
88                                         if (stopFlag) {\r
89                                                 break;\r
90                                         }\r
91                                         // ジョブを一旦ローカル変数に保存\r
92                                         job = requestJob;\r
93                                         // ジョブの受け付けを再開.\r
94                                         requestJob = null;\r
95                                         lock.notifyAll();\r
96                                 }\r
97                                 // リクエストを処理する.\r
98                                 AsyncImageBuilder.super.requestJob(job);\r
99                                 \r
100                         } catch (InterruptedException ex) {\r
101                                 logger.log(Level.FINE, "AsyncImageBuilder thead interrupted.");\r
102                                 // 割り込みされた場合、単にループを再開する.\r
103                                 \r
104                         } catch (Exception ex) {\r
105                                 logger.log(Level.SEVERE, "AsyncImageBuilder failed.", ex);\r
106                                 // ジョブ合成中の予期せぬ例外はログに記録するのみで\r
107                                 // スレッドそのものは停止させない.\r
108                                 // (Error系は、たぶんアプリ自身が続行不能な障害なので停止する.)\r
109                         }\r
110                 }\r
111                 logger.log(Level.FINE, "AsyncImageBuilder thread stopped.");\r
112         }\r
113         \r
114         /**\r
115          * イメージ作成ジョブをリクエストする.<br>\r
116          * イメージ作成ジョブは非同期に実行される.<br>\r
117          * 処理がはじまる前に新しいリクエストで上書きされた場合、前のリクエストは単に捨てられる.<br>\r
118          */\r
119         @Override\r
120         public boolean requestJob(ImageBuildJob imageSource) {\r
121                 synchronized (lock) {\r
122                         // 現在処理待ちのリクエストがあれば、新しいリクエストで上書きする.\r
123                         if (this.requestJob != null && this.requestJob instanceof AsyncImageBuildJob) {\r
124                                 ((AsyncImageBuildJob) this.requestJob).onAbandoned();\r
125                         }\r
126                         \r
127                         // リクエストをセットして待機中のスレッドに通知を出す.\r
128                         this.requestJob = imageSource;\r
129                         if (imageSource != null && imageSource instanceof AsyncImageBuildJob) {\r
130                                 ((AsyncImageBuildJob) imageSource).onQueueing(++ticketSerialNum);\r
131                         }\r
132 \r
133                         lock.notifyAll();\r
134                 }\r
135                 return false;\r
136         }\r
137 \r
138         /**\r
139          * スレッドが生きているか?\r
140          * @return 生きていればtrue\r
141          */\r
142         public boolean isAlive() {\r
143                 return thread.isAlive();\r
144         }\r
145         \r
146         /**\r
147          * スレッドを開始する.\r
148          */\r
149         public void start() {\r
150                 if (!thread.isAlive()) {\r
151                         stopFlag = false;\r
152                         thread.start();\r
153                 }\r
154         }\r
155 \r
156         /**\r
157          * スレッドを停止する.\r
158          */\r
159         public void stop() {\r
160                 if (thread.isAlive()) {\r
161                         stopFlag = true;\r
162                         thread.interrupt();\r
163                         try {\r
164                                 // スレッドの停止を待機する.\r
165                                 thread.join();\r
166                         } catch (InterruptedException ex) {\r
167                                 // do nothing.\r
168                         }\r
169                 }\r
170         }\r
171         \r
172 }\r