1 30 31 32 package org.hsqldb.lib; 33 34 import java.util.Date ; 35 36 47 public class HsqlTimer implements ObjectComparator { 48 49 50 protected final TaskQueue taskQueue = new TaskQueue(16, 51 (ObjectComparator) this); 52 53 54 protected final TaskRunner taskRunner = new TaskRunner(); 55 56 57 protected Thread taskRunnerThread; 58 59 60 protected ThreadFactory threadFactory; 61 62 66 public HsqlTimer() { 67 this(null); 68 } 69 70 78 public HsqlTimer(ThreadFactory tf) { 79 threadFactory = new HsqlThreadFactory(tf); 80 } 81 82 90 public int compare(Object a, Object b) { 91 92 long awhen; 93 long bwhen; 94 95 awhen = ((Task) (a)).getNextScheduled(); 96 bwhen = ((Task) (b)).getNextScheduled(); 97 98 return (int) (awhen - bwhen); 104 } 105 106 112 public synchronized Thread getThread() { 113 return taskRunnerThread; 114 } 115 116 119 public synchronized void restart() { 120 121 if (taskRunnerThread == null) { 122 taskRunnerThread = threadFactory.newThread(taskRunner); 123 124 taskRunnerThread.setName("HSQLDB Timer @" 125 + Integer.toHexString(this.hashCode())); 126 taskRunnerThread.setDaemon(true); 127 taskRunnerThread.start(); 128 } else { 129 notify(); 130 } 131 } 132 133 141 public Object scheduleAfter(long delay, Runnable r) { 142 return addTask(now() + delay, r, 0, false); 143 } 144 145 153 public Object scheduleAt(Date date, Runnable r) { 154 return addTask(date.getTime(), r, -1, false); 155 } 156 157 167 public Object schedulePeriodicallyAt(Date date, long p, Runnable r, 168 boolean relative) { 169 170 if (p <= 0) { 171 throw new IllegalArgumentException (); 172 } 173 174 return addTask(date.getTime(), r, p, relative); 175 } 176 177 187 public Object schedulePeriodicallyAfter(long delay, long p, Runnable r, 188 boolean relative) { 189 190 if (p <= 0) { 191 throw new IllegalArgumentException (); 192 } 193 194 return addTask(now() + delay, r, p, relative); 195 } 196 197 201 public synchronized void shutDown() { 202 203 taskQueue.clear(); 204 205 if (taskRunnerThread != null) { 206 taskRunnerThread.interrupt(); 207 } 208 209 taskRunnerThread = null; 210 } 211 212 222 public static void cancel(Object task) throws ClassCastException { 223 224 if (task != null) { 225 ((Task) task).cancel(); 226 227 } 229 } 230 231 240 public static boolean isCancelled(Object task) throws ClassCastException { 241 return task == null ? true 242 : ((Task) task).isCancelled(); 243 } 244 245 255 public static boolean isFixedRate(Object task) throws ClassCastException { 256 257 return task == null ? false 258 : ((Task) task).relative 259 && ((Task) task).period > 0; 260 } 261 262 272 public static boolean isFixedDelay(Object task) 273 throws ClassCastException { 274 275 return task == null ? false 276 : !((Task) task).relative 277 && ((Task) task).period > 0; 278 } 279 280 290 public static boolean isPeriodic(Object task) throws ClassCastException { 291 return task == null ? false 292 : ((Task) task).period != 0; 293 } 294 295 305 public static Date getLastScheduled(Object task) 306 throws ClassCastException { 307 308 long last; 309 310 last = task == null ? 0 311 : ((Task) task).getLastScheduled(); 312 313 return last == 0 ? null 314 : new Date (last); 315 } 316 317 326 public static void setPeriod(Object task, 327 long period) throws ClassCastException { 328 329 if (task == null) { 330 return; 331 } 332 333 ((Task) task).setPeriod(period); 334 } 335 336 346 public static Date getNextScheduled(Object task) 347 throws ClassCastException { 348 return isCancelled(task) ? null 349 : new Date (((Task) task).getNextScheduled()); 350 } 351 352 362 protected Task addTask(long n, Runnable r, long p, boolean b) { 363 364 Task task; 365 366 task = new Task(n, r, p, b); 367 368 taskQueue.add(task); 370 371 restart(); 373 374 return task; 375 } 376 377 378 protected synchronized void clearThread() { 379 taskRunnerThread = null; 380 } 381 382 388 protected synchronized Task nextTask() { 389 390 Task task; 391 long now; 392 long last; 393 long next; 394 long late; 395 long period; 396 boolean relative; 397 398 try { 399 while (!Thread.interrupted()) { 400 task = (Task) (taskQueue.peek()); 401 402 if (task == null) { 403 wait(); 404 } else { 405 now = now(); 406 next = task.getNextScheduled(); 407 408 if (next > now) { 409 wait(next - now); 410 } else { 411 task = (Task) taskQueue.remove(); 412 413 if (task != null &&!task.isCancelled()) { 414 period = task.period; 415 416 if (period > 0) { 417 now = now(); 418 419 if (task.relative) { 420 late = now - next; 421 422 if (late > 0) { 423 period -= late; 424 } 425 } 426 427 next = now + period; 428 429 task.setNextScheduled(next); 430 taskQueue.add(task); 431 } 432 433 return task; 434 } 435 } 436 } 437 } 438 } catch (InterruptedException e) { 439 440 } 442 443 return null; 445 } 446 447 static int nowCount = 0; 448 449 455 private static long now() { 456 457 nowCount++; 458 459 return System.currentTimeMillis(); 460 } 461 462 470 protected class TaskRunner implements Runnable { 471 472 public void run() { 473 474 Task task; 475 476 try { 477 do { 478 task = HsqlTimer.this.nextTask(); 479 480 if (task == null) { 481 break; 482 } 483 484 task.setLastScheduled(now()); 485 task.runnable.run(); 486 } while (true); 487 } finally { 488 HsqlTimer.this.clearThread(); 489 } 490 } 491 } 492 493 498 protected class Task { 499 500 501 final Runnable runnable; 502 503 504 long period; 505 506 507 private long last; 508 509 510 private long next; 511 512 517 private boolean cancelled = false; 518 519 520 private Object cancel_mutex = new Object (); 521 522 533 final boolean relative; 534 535 544 Task(long n, Runnable r, long p, boolean b) { 545 546 last = 0; 547 next = n; 548 runnable = r; 549 period = p; 550 relative = b; 551 } 552 553 554 void cancel() { 555 556 synchronized (cancel_mutex) { 557 cancelled = true; 558 } 559 } 560 561 566 boolean isCancelled() { 567 568 synchronized (cancel_mutex) { 569 return cancelled; 570 } 571 } 572 573 580 synchronized long getLastScheduled() { 581 return last; 582 } 583 584 589 synchronized void setLastScheduled(long l) { 590 last = l; 591 } 592 593 600 synchronized long getNextScheduled() { 601 return next; 602 } 603 604 611 synchronized void setNextScheduled(long n) { 612 next = n; 613 } 614 615 620 synchronized void setPeriod(long n) { 621 period = n; 622 } 623 } 624 625 631 protected class TaskQueue extends HsqlArrayHeap { 632 633 641 TaskQueue(int capacity, ObjectComparator oc) { 642 super(capacity, oc); 643 } 644 645 646 public synchronized void clear() { 647 648 for (int i = 0; i < count; i++) { 649 ((Task) heap[i]).cancel(); 650 651 heap[i] = null; 652 } 653 654 count = 0; 655 } 656 } 657 658 } 765 | Popular Tags |