001: /*
002: * TimerHandler.java --
003: *
004: * The API for defining timer event handler.
005: *
006: * Copyright (c) 1997 Cornell University.
007: * Copyright (c) 1997 Sun Microsystems, Inc.
008: *
009: * See the file "license.terms" for information on usage and
010: * redistribution of this file, and for a DISCLAIMER OF ALL
011: * WARRANTIES.
012: *
013: * RCS: @(#) $Id: TimerHandler.java,v 1.3 2006/04/27 02:16:13 mdejong Exp $
014: *
015: */
016:
017: package tcl.lang;
018:
019: /*
020: * This abstract class is used to define timer handlers.
021: */
022:
023: abstract public class TimerHandler {
024:
025: /*
026: * Back pointer to the notifier that will fire this timer.
027: */
028:
029: Notifier notifier;
030:
031: /*
032: * System time at (of after) which the timer should be fired.
033: */
034:
035: long atTime;
036:
037: /*
038: * True if the cancel() method has been called.
039: */
040:
041: boolean isCancelled;
042:
043: /*
044: * Used to distinguish older idle handlers from recently-created ones.
045: */
046:
047: int generation;
048:
049: /*
050: *----------------------------------------------------------------------
051: *
052: * TimerHandler --
053: *
054: * Create a timer handler to be fired after the given time lapse.
055: *
056: * Results:
057: * None.
058: *
059: * Side effects:
060: * The timer is registered in the list of timers in the given
061: * notifier. After milliseconds have elapsed, the
062: * processTimerEvent() method will be invoked exactly once inside
063: * the primary thread of the notifier.
064: *
065: *----------------------------------------------------------------------
066: */
067:
068: public TimerHandler(Notifier n, // The notifier to fire the event.
069: int milliseconds) // How many milliseconds to wait
070: // before invoking processTimerEvent().
071: {
072: int i;
073:
074: atTime = System.currentTimeMillis() + milliseconds;
075: notifier = n;
076: isCancelled = false;
077:
078: /*
079: * Add timer event to the pending timer list in the correct
080: * position (ordered by event firing time).
081: *
082: * NOTE: it's very important that if two timer handlers have the
083: * same atTime, the newer timer handler always goes after the
084: * older handler in the list. See comments in
085: * Notifier.TimerEvent.processEvent() for details.
086: */
087:
088: synchronized (notifier) {
089: generation = notifier.timerGeneration;
090:
091: for (i = 0; i < notifier.timerList.size(); i++) {
092: TimerHandler q = (TimerHandler) notifier.timerList
093: .get(i);
094: if (atTime < q.atTime) {
095: break;
096: }
097: }
098: notifier.timerList.add(i, this );
099:
100: if (Thread.currentThread() != notifier.primaryThread) {
101: notifier.notifyAll();
102: }
103: }
104: }
105:
106: /*
107: *----------------------------------------------------------------------
108: *
109: * cancel --
110: *
111: * Mark this timer handler as cancelled so that it won't be
112: * invoked.
113: *
114: * Results:
115: * None.
116: *
117: * Side effects:
118: * The timer handler is marked as cancelled so that its
119: * processTimerEvent() method will not be called. If the timer
120: * has already fired, then nothing this call has no effect.
121: *
122: *----------------------------------------------------------------------
123: */
124:
125: public synchronized void cancel() {
126: if (isCancelled) {
127: return;
128: }
129:
130: isCancelled = true;
131:
132: synchronized (notifier) {
133: for (int i = 0; i < notifier.timerList.size(); i++) {
134: if (notifier.timerList.get(i) == this ) {
135: notifier.timerList.remove(i);
136:
137: /*
138: * We can return now because the same timer can be
139: * registered only once in the list of timers.
140: */
141:
142: return;
143: }
144: }
145: }
146: }
147:
148: /*
149: *----------------------------------------------------------------------
150: *
151: * invoke --
152: *
153: * Execute the timer handler if it has not been cancelled. This
154: * method should be called by the notifier only.
155: *
156: * Because the timer handler may be being cancelled by another
157: * thread, both this method and cancel() must be synchronized to
158: * ensure correctness.
159: *
160: * Results:
161: * 0 if the handler was not executed because it was already
162: * cancelled, 1 otherwise.
163: *
164: * Side effects:
165: * The timer handler may have arbitrary side effects.
166: *
167: *----------------------------------------------------------------------
168: */
169:
170: synchronized final int invoke() {
171: /*
172: * The timer may be cancelled after it was put on the
173: * event queue. Check its isCancelled field to make sure it's
174: * not cancelled.
175: */
176:
177: if (!isCancelled) {
178: processTimerEvent();
179: return 1;
180: } else {
181: return 0;
182: }
183: }
184:
185: /*
186: *----------------------------------------------------------------------
187: *
188: * processTimerEvent --
189: *
190: * This method is called when the timer is expired. Override
191: * This method to implement your own timer handlers.
192: *
193: * Results:
194: * None.
195: *
196: * Side effects:
197: * It can do anything.
198: *
199: *----------------------------------------------------------------------
200: */
201:
202: abstract public void processTimerEvent();
203:
204: } // end TimerHandler
|