App

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

RenderingTask.java
Go to the documentation of this file.
1 package mhr.appcore.tasks;
2
3 import mhr.appcore.AppCore;
4 import mhr.appcore.bitmap.NBitmap;
5 import mhr.appcore.image.Image;
6 import mhr.appcore.interfaces.PDBitmap;
7 import mhr.appcore.interfaces.PDDisplayer;
8 import mhr.appcore.utils.Rect;
9
14 public class RenderingTask implements Runnable {
15
16 //===== INTERFACES, CLASSES, ENUMS ==========================================================================================================//
17 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
22 @Deprecated
23 private enum RenderScope {
24 NONE, INCREMENTAL, MERGED, HEURISTIC, ALL;
25 }
29 private class Lock {
30 public volatile boolean EXIT_FLAG = false;
31 public RenderScope scope = RenderScope.NONE;
32 public volatile boolean RENDER_FLAG = false;
33 public volatile boolean SUSPEND_FLAG = false;
34 public volatile Object suspendedOn = null;
35 }
36 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
37
38 //===== FIELDS ==============================================================================================================================//
39 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
40 protected Image image = null;
41 protected NBitmap wrOutput = null;
42 protected NBitmap wrTmp = null;
43 protected PDDisplayer disp = null;
44 protected Thread thread = null;
45 protected Lock lock = new Lock();
46 protected Thread.UncaughtExceptionHandler handler = null;
47
48 protected AppCore app;
49 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
50
51 //===== CONSTRUCTORS, DESTRUCTORS, RELATED METHODS ==========================================================================================//
52 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
53 @Override
54 protected void finalize() throws Throwable {
55 dispose();
56 }
57 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
62 public RenderingTask(AppCore app) {
63 if (app == null) {
64 throw new IllegalArgumentException("app should not be null");
65 }
66 this.app = app;
67 }
68
73 public void init() throws IllegalStateException {
74 if (thread != null) {
75 throw new IllegalStateException("Instance is already in use");
76 }
77 this.image = app.getImg();
78 this.wrOutput = app.getWrOutput();
79 this.disp = app.getDisp();
80 if (wrTmp != null) {
81 wrTmp.dispose();
82 }
83 this.wrTmp = new NBitmap(wrOutput);
84 }
85
86 public synchronized void dispose() {
87 stop();
88 if (wrTmp != null) {
89 wrTmp.dispose();
90 wrTmp = null;
91 }
92 }
93
94 //===== METHODS =============================================================================================================================//
95 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
96 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
97
98 public void setThreadEH(Thread.UncaughtExceptionHandler handler) {
99 synchronized (lock) {
100 this.handler = handler;
101 if (thread != null) {
102 thread.setUncaughtExceptionHandler(handler);
103 }
104 }
105 }
106
107
111 public synchronized void start(){
112 if (thread != null) {
113 return;
114 }
115 thread = new Thread(this);
116 if (handler != null) {
117 thread.setUncaughtExceptionHandler(handler);
118 }
119 synchronized (lock) {
120 lock.EXIT_FLAG = false;
121 }
122 thread.start();
123 }
124
128 public synchronized void stop(){
129 if (thread == null) {
130 return;
131 }
132 synchronized (lock) {
133 lock.EXIT_FLAG = true;
134 lock.notifyAll();
135 }
136 try {
137 thread.join();
138 } catch (InterruptedException exc) {
139 }
140 thread = null;
141 }
142
152 public void susepnd(Object o) throws NullPointerException, IllegalStateException {
153 if (o == null) {
154 throw new NullPointerException("o cannot be null");
155 }
156 synchronized (lock) {
157 if (lock.suspendedOn != null) {
158 throw new IllegalStateException("Thread is already suspended by someone else");
159 }
160 lock.SUSPEND_FLAG = true;
161 lock.suspendedOn = o;
162 lock.notifyAll();
163 }
164 }
165
173 public void wake(Object o) throws NullPointerException, IllegalStateException {
174 if (o == null) {
175 throw new NullPointerException("o cannot be null");
176 }
177 synchronized (lock) {
178 if (lock.suspendedOn != o) {
179 throw new IllegalArgumentException("Bad object supplied");
180 }
181 lock.suspendedOn = null;
182 lock.SUSPEND_FLAG = false;
183 lock.notifyAll();
184 }
185
186 }
187
192 public boolean isSuspended() {
193 synchronized (lock) {
194 return lock.SUSPEND_FLAG;
195 }
196 }
197
201 public void renderOnThisThread() {
202 while (image.exportChangedToHeuristic(wrOutput) != null) {
203 disp.redraw();
204 }
205 disp.redraw(); // Zbytečný redraw(), ale redraw je dost rychlý...
206 }
207
211 public void render() {
212 renderHeuristic();
213 }
214
218 @Deprecated
219 public void renderAll() {
220 synchronized (lock) {
221 lock.RENDER_FLAG = true;
222 lock.scope = RenderScope.ALL;
223 lock.notifyAll();
224 }
225 }
226
230 public void renderHeuristic() {
231 synchronized (lock) {
232 lock.RENDER_FLAG = true;
233 lock.scope = RenderScope.HEURISTIC;
234 lock.notifyAll();
235 }
236 }
237
238 //===== CALLBACKS ===========================================================================================================================//
239
240 @Override
241 public void run() {
242 RenderScope scope = RenderScope.NONE;
243 while (true) { // bezi stale
244 synchronized (lock) {
245 while (true) {
246 if (lock.EXIT_FLAG) {
247 return;
248 }
249 while (lock.SUSPEND_FLAG) { // Dokud uspani trva
250 synchronized (lock.suspendedOn) {
251 lock.suspendedOn.notifyAll(); // Oznamit tomu kdo ceka na uspani
252 /*
253 * Zde byl deadlock - Bude lepsi neustale davat vedet uspanemu kdykoliv probehne smycka...
254 *
255 * Deadlock spocival v tom, ze nez se thread dostal do uspane smycky, byl probuzen a znovu uspan, ale uz nedal vedet tomu,
256 * kdo na druhe uspani cekal...
257 * Takto se to stat nemuze - pokazde kdyz bude vlakno probuzeno, pokud bude platit SUSPEND_FLAG, da vedet zadateli, at uz bude tento jakykoliv...
258 */
259 }
260 try {
261 this.lock.wait(); // Porad cekat
262 } catch (InterruptedException e) {
263 return;
264 }
265 if (lock.EXIT_FLAG) { // I pokud je uspany muze byt potreba jej ukoncit
266 return;
267 }
268 }
269 if (lock.RENDER_FLAG) {
270 lock.RENDER_FLAG = false;
271 scope = lock.scope;
272 break;
273 }
274 try {
275 this.lock.wait();
276 } catch (InterruptedException e) {
277 return;
278 }
279 }
280 }
281 switch (scope) {
282 case HEURISTIC:
283 Rect r = null;
284 while ((r = image.exportChangedToHeuristic(wrTmp)) != null) {
285 wrTmp.copyTo(wrOutput, r, r.tlx, r.tly);
286 disp.redraw();
287 }
288 disp.redraw(); // Zbytečný redraw(), ale redraw je dost rychlý...
289 break;
290 default:
291 break;
292 }
293
294 }
295 }
296
297
298 }