001: /*
002: * Copyright (c) 1998-2002 Carnegie Mellon University. All rights
003: * reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * 2. Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: *
017: * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
018: * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
019: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
020: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
021: * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: */
030:
031: package rcm.util;
032:
033: import java.util.Vector;
034:
035: public class Timer {
036:
037: int interval;
038: boolean periodic;
039: boolean isExpired = false;
040:
041: static TimerManager manager = new TimerManager();
042: long deadline;
043: Timer next, prev;
044:
045: public Timer() {
046: }
047:
048: public void set(int msecDelay, boolean periodic) {
049: interval = msecDelay;
050: this .periodic = periodic;
051: isExpired = false;
052: if (!manager.isAlive()) {
053: System.err.println("TimerManager: restarting");
054: manager = new TimerManager();
055: }
056: manager.register(this , System.currentTimeMillis() + msecDelay);
057: }
058:
059: public int getInterval() {
060: return interval;
061: }
062:
063: public boolean getPeriodic() {
064: return periodic;
065: }
066:
067: public void cancel() {
068: manager.delete(this );
069: }
070:
071: protected void alarm() {
072: }
073:
074: public boolean expired() {
075: return isExpired;
076: }
077:
078: /*
079: public static void main (String[] args) {
080: for (int i=0; i<args.length; ++i) {
081: boolean periodic = (args[i].charAt (0) == 'p');
082: if (periodic) args[i] = args[i].substring (1);
083: new TestTimer (args[i], Integer.parseInt (args[i]), periodic);
084: }
085: while (true) Thread.yield ();
086: }
087: */
088: }
089:
090: class TimerManager extends Thread {
091: Timer first, last;
092:
093: /*
094: static ThreadGroup rootThreadGroup;
095: static {
096: rootThreadGroup = Thread.currentThread().getThreadGroup();
097: while (rootThreadGroup.getParent() != null)
098: rootThreadGroup = rootThreadGroup.getParent();
099: }
100: */
101:
102: public TimerManager() {
103: super (/* rootThreadGroup, */"Timer Manager");
104: setDaemon(true);
105: start();
106: }
107:
108: public synchronized void register(Timer t, long deadline) {
109: t.deadline = deadline;
110: delete(t); // just in case it's already registered
111:
112: //System.err.println ("TimerManager: set " + t + " to go off at " + deadline);
113: insertion: {
114: for (Timer u = first; u != null; u = u.next) {
115: if (t.deadline < u.deadline) {
116: if (u.prev != null)
117: u.prev.next = t;
118: else
119: first = t;
120: t.prev = u.prev;
121: t.next = u;
122: u.prev = t;
123: break insertion;
124: }
125: }
126: if (last != null) {
127: last.next = t;
128: t.prev = last;
129: t.next = null;
130: last = t;
131: } else {
132: first = last = t;
133: }
134: }
135:
136: //System.err.println ("TimerManager: waking up background thread");
137: notifyAll();
138: }
139:
140: public synchronized void delete(Timer t) {
141: if (t.next != null)
142: t.next.prev = t.prev;
143: if (t.prev != null)
144: t.prev.next = t.next;
145: if (t == last)
146: last = t.prev;
147: if (t == first)
148: first = t.next;
149: t.next = null;
150: t.prev = null;
151: }
152:
153: static final int FOREVER = 60000; // wake up at least every 60 seconds
154:
155: public synchronized void run() {
156: while (true) {
157: try {
158: //System.err.println ("TimerManager: awake");
159: if (first == null) {
160: //System.err.println ("TimerManager: waiting forever");
161: wait(FOREVER);
162: //System.err.println ("TimerManager: woke up");
163: } else {
164: Timer t = first;
165: long now = System.currentTimeMillis();
166: if (t.deadline <= now) {
167: // System.err.println ("TimerManager: timer " + t + " just went off at " + now);
168: try {
169: t.isExpired = true;
170: t.alarm();
171: } catch (Throwable e) {
172: if (e instanceof ThreadDeath)
173: throw (ThreadDeath) e;
174: else
175: e.printStackTrace();
176: }
177: if (t.periodic) {
178: register(t, now + t.interval);
179: } else {
180: delete(t);
181: }
182: } else {
183: //System.err.println ("TimerManager: waiting for " + (t.deadline - now) + " msec");
184: wait(t.deadline - now);
185: //System.err.println ("TimerManager: woke up");
186: }
187: }
188: } catch (InterruptedException e) {
189: }
190: }
191: }
192: }
193:
194: /*
195: class TestTimer extends Timer {
196: String message;
197:
198: public TestTimer (String message, int millisec, boolean periodic) {
199: this.message = message;
200: set (millisec, periodic);
201: }
202:
203: public void alarm () {
204: System.out.println (message);
205: }
206: }
207: */
|