1 16 package com.google.gwt.user.client; 17 18 import com.google.gwt.core.client.GWT; 19 import com.google.gwt.core.client.GWT.UncaughtExceptionHandler; 20 21 import java.util.ArrayList ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 25 46 class CommandExecutor { 47 48 52 private class CircularIterator implements Iterator { 53 57 private int end; 58 59 62 private int last = -1; 63 64 67 private int next = 0; 68 69 74 public boolean hasNext() { 75 return next < end; 76 } 77 78 84 public Object next() { 85 last = next; 86 Object command = commands.get(next++); 87 if (next >= end) { 88 next = 0; 89 } 90 91 return command; 92 } 93 94 99 public void remove() { 100 assert (last >= 0); 101 102 commands.remove(last); 103 --end; 104 105 if (last <= next) { 106 if (--next < 0) { 107 next = 0; 108 } 109 } 110 111 last = -1; 112 } 113 114 119 private Object getLast() { 120 assert (last >= 0); 121 return commands.get(last); 122 } 123 124 private void setEnd(int end) { 125 assert (end >= next); 126 127 this.end = end; 128 } 129 130 private void setLast(int last) { 131 this.last = last; 132 } 133 134 private boolean wasRemoved() { 135 return last == -1; 136 } 137 } 138 139 145 private static final long DEFAULT_CANCELLATION_TIMEOUT_MILLIS = 10000; 146 147 151 private static final long DEFAULT_TIME_SLICE_MILLIS = 100; 152 153 160 private static boolean hasTimeSliceExpired(long currentTimeMillis, 161 long startTimeMillis) { 162 return Math.abs(currentTimeMillis - startTimeMillis) >= DEFAULT_TIME_SLICE_MILLIS; 163 } 164 165 169 private final Timer cancellationTimer = new Timer() { 170 public void run() { 171 if (!isExecuting()) { 172 177 return; 178 } 179 180 doCommandCanceled(); 181 } 182 }; 183 184 187 private final List commands = new ArrayList (); 188 189 192 private boolean executing = false; 193 194 197 private final Timer executionTimer = new Timer() { 198 public void run() { 199 assert (!isExecuting()); 200 201 setExecutionTimerPending(false); 202 203 doExecuteCommands(System.currentTimeMillis()); 204 } 205 }; 206 207 211 private boolean executionTimerPending = false; 212 213 217 private final CircularIterator iterator = new CircularIterator(); 218 219 224 public void submit(Command command) { 225 commands.add(command); 226 227 maybeStartExecutionTimer(); 228 } 229 230 235 public void submit(IncrementalCommand command) { 236 commands.add(command); 237 238 maybeStartExecutionTimer(); 239 } 240 241 246 protected void doCommandCanceled() { 247 Object cmd = iterator.getLast(); 248 iterator.remove(); 249 assert (cmd != null); 250 251 RuntimeException ex = null; 252 if (cmd instanceof Command) { 253 ex = new CommandCanceledException((Command) cmd); 254 } else if (cmd instanceof IncrementalCommand) { 255 ex = new IncrementalCommandCanceledException((IncrementalCommand) cmd); 256 } 257 258 if (ex != null) { 259 UncaughtExceptionHandler ueh = GWT.getUncaughtExceptionHandler(); 260 if (ueh != null) { 261 ueh.onUncaughtException(ex); 262 } 263 } 264 265 setExecuting(false); 266 267 maybeStartExecutionTimer(); 268 } 269 270 284 protected void doExecuteCommands(long startTimeMillis) { 285 assert (!isExecutionTimerPending()); 286 287 boolean wasCanceled = false; 288 try { 289 setExecuting(true); 290 291 iterator.setEnd(commands.size()); 292 293 cancellationTimer.schedule((int) DEFAULT_CANCELLATION_TIMEOUT_MILLIS); 294 295 while (iterator.hasNext()) { 296 Object element = iterator.next(); 297 298 boolean removeCommand = true; 299 try { 300 if (element == null) { 301 return; 303 } 304 305 if (element instanceof Command) { 306 Command command = (Command) element; 307 command.execute(); 308 } else if (element instanceof IncrementalCommand) { 309 IncrementalCommand incrementalCommand = (IncrementalCommand) element; 310 removeCommand = !incrementalCommand.execute(); 311 } 312 313 } finally { 314 wasCanceled = iterator.wasRemoved(); 315 if (wasCanceled) { 316 320 return; 321 } 322 323 if (removeCommand) { 324 iterator.remove(); 325 } 326 } 327 328 if (hasTimeSliceExpired(System.currentTimeMillis(), startTimeMillis)) { 329 return; 331 } 332 } 333 } finally { 334 if (!wasCanceled) { 335 cancellationTimer.cancel(); 336 337 setExecuting(false); 338 339 maybeStartExecutionTimer(); 340 } 341 } 342 } 343 344 348 protected void maybeStartExecutionTimer() { 349 if (!commands.isEmpty() && !isExecutionTimerPending() && !isExecuting()) { 350 setExecutionTimerPending(true); 351 executionTimer.schedule(1); 352 } 353 } 354 355 358 List getPendingCommands() { 359 return commands; 360 } 361 362 365 void setExecuting(boolean executing) { 366 this.executing = executing; 367 } 368 369 372 void setLast(int last) { 373 iterator.setLast(last); 374 } 375 376 383 private boolean isExecuting() { 384 return executing; 385 } 386 387 394 private boolean isExecutionTimerPending() { 395 return executionTimerPending; 396 } 397 398 private void setExecutionTimerPending(boolean pending) { 399 executionTimerPending = pending; 400 } 401 } | Popular Tags |