001 /* 002 * LAPIS lightweight structured text processing system 003 * 004 * Copyright (C) 1998-2002 Carnegie Mellon University, 005 * Copyright (C) 2003 Massachusetts Institute of Technology. 006 * All rights reserved. 007 * 008 * This library is free software; you can redistribute it 009 * and/or modify it under the terms of the GNU General 010 * Public License as published by the Free Software 011 * Foundation, version 2. 012 * 013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/ 014 */ 015 016 017 package lapisx.util; 018 019 //import java.util.Vector; 020 021 public class Timer { 022 023 int interval; 024 boolean periodic; 025 boolean isExpired = false; 026 027 static TimerManager manager = new TimerManager (); 028 long deadline; 029 Timer next, prev; 030 031 public Timer () { 032 } 033 034 public void set (int msecDelay, boolean periodic) { 035 interval = msecDelay; 036 this.periodic = periodic; 037 isExpired = false; 038 if (!manager.isAlive ()) { 039 System.err.println ("TimerManager: restarting"); 040 manager = new TimerManager (); 041 } 042 manager.register (this, System.currentTimeMillis () + msecDelay); 043 } 044 045 public int getInterval () { 046 return interval; 047 } 048 049 public boolean getPeriodic () { 050 return periodic; 051 } 052 053 public void cancel () { 054 manager.delete (this); 055 } 056 057 protected void alarm () { 058 } 059 060 public boolean expired () { 061 return isExpired; 062 } 063 064 /* 065 public static void main (String[] args) { 066 for (int i=0; i<args.length; ++i) { 067 boolean periodic = (args[i].charAt (0) == 'p'); 068 if (periodic) args[i] = args[i].substring (1); 069 new TestTimer (args[i], Integer.parseInt (args[i]), periodic); 070 } 071 while (true) Thread.yield (); 072 } 073 */ 074 } 075 076 class TimerManager extends Thread { 077 Timer first, last; 078 079 /* 080 static ThreadGroup rootThreadGroup; 081 static { 082 rootThreadGroup = Thread.currentThread().getThreadGroup(); 083 while (rootThreadGroup.getParent() != null) 084 rootThreadGroup = rootThreadGroup.getParent(); 085 } 086 */ 087 088 public TimerManager () { 089 super (/* rootThreadGroup, */ "Timer Manager"); 090 setDaemon (true); 091 start (); 092 } 093 094 public synchronized void register (Timer t, long deadline) { 095 t.deadline = deadline; 096 delete (t); // just in case it's already registered 097 098 //System.err.println ("TimerManager: set " + t + " to go off at " + deadline); 099 insertion: 100 { 101 for (Timer u = first; u != null; u = u.next) { 102 if (t.deadline < u.deadline) { 103 if (u.prev != null) 104 u.prev.next = t; 105 else 106 first = t; 107 t.prev = u.prev; 108 t.next = u; 109 u.prev = t; 110 break insertion; 111 } 112 } 113 if (last != null) { 114 last.next = t; 115 t.prev = last; 116 t.next = null; 117 last = t; 118 } else { 119 first = last = t; 120 } 121 } 122 123 //System.err.println ("TimerManager: waking up background thread"); 124 notifyAll (); 125 } 126 127 public synchronized void delete (Timer t) { 128 if (t.next != null) 129 t.next.prev = t.prev; 130 if (t.prev != null) 131 t.prev.next = t.next; 132 if (t == last) 133 last = t.prev; 134 if (t == first) 135 first = t.next; 136 t.next = null; 137 t.prev = null; 138 } 139 140 static final int FOREVER = 60000; // wake up at least every 60 seconds 141 142 public synchronized void run () { 143 while (true) { 144 try { 145 //System.err.println ("TimerManager: awake"); 146 if (first == null) { 147 //System.err.println ("TimerManager: waiting forever"); 148 wait (FOREVER); 149 //System.err.println ("TimerManager: woke up"); 150 } 151 else { 152 Timer t = first; 153 long now = System.currentTimeMillis (); 154 if (t.deadline <= now) { 155 // System.err.println ("TimerManager: timer " + t + " just went off at " + now); 156 try { 157 t.isExpired = true; 158 t.alarm (); 159 } catch (Throwable e) { 160 if (e instanceof ThreadDeath) 161 throw (ThreadDeath)e; 162 else 163 e.printStackTrace (); 164 } 165 if (t.periodic) { 166 register (t, now + t.interval); 167 } 168 else { 169 delete (t); 170 } 171 } 172 else { 173 //System.err.println ("TimerManager: waiting for " + (t.deadline - now) + " msec"); 174 wait (t.deadline - now); 175 //System.err.println ("TimerManager: woke up"); 176 } 177 } 178 } catch (InterruptedException e) {} 179 } 180 } 181 } 182 183 /* 184 class TestTimer extends Timer { 185 String message; 186 187 public TestTimer (String message, int millisec, boolean periodic) { 188 this.message = message; 189 set (millisec, periodic); 190 } 191 192 public void alarm () { 193 System.out.println (message); 194 } 195 } 196 */