App
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;
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 ------------------------------------------------------------------------------------------------------------------------------//
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;
223  lock.notifyAll();
224  }
225  }
226 
230  public void renderHeuristic() {
231  synchronized (lock) {
232  lock.RENDER_FLAG = true;
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 }