/* * TimerHandler.java -- * * The API for defining timer event handler. * * Copyright (c) 1997 Cornell University. * Copyright (c) 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and * redistribution of this file, and for a DISCLAIMER OF ALL * WARRANTIES. * * RCS: @(#) $Id: TimerHandler.java,v 1.1.1.1 1998/10/14 21:09:21 cvsadmin Exp $ * */ package tcl.lang; import java.util.Hashtable; import java.util.Vector; /* * This abstract class is used to define timer handlers. */ abstract public class TimerHandler { /* * Back pointer to the notifier that will fire this timer. */ Notifier notifier; /* * System time at (of after) which the timer should be fired. */ long atTime; /* * True if the cancel() method has been called. */ boolean isCancelled; /* * Used to distinguish older idle handlers from recently-created ones. */ int generation; /* *---------------------------------------------------------------------- * * TimerHandler -- * * Create a timer handler to be fired after the given time lapse. * * Results: * None. * * Side effects: * The timer is registered in the list of timers in the given * notifier. After milliseconds have elapsed, the * processTimerEvent() method will be invoked exactly once inside * the primary thread of the notifier. * *---------------------------------------------------------------------- */ public TimerHandler( Notifier n, // The notifier to fire the event. int milliseconds) // How many milliseconds to wait // before invoking processTimerEvent(). { int i; atTime = System.currentTimeMillis() + milliseconds; notifier = (Notifier)n; isCancelled = false; /* * Add the event to the queue in the correct position (ordered by * event firing time). * * NOTE: it's very important that if two timer handlers have the * same atTime, the newer timer handler always goes after the * older handler in the list. See comments in * Notifier.TimerEvent.processEvent() for details. */ synchronized(notifier) { generation = notifier.timerGeneration; for (i = 0; i < notifier.timerList.size(); i++) { TimerHandler q = (TimerHandler)notifier.timerList.elementAt(i); if (atTime < q.atTime) { break; } } notifier.timerList.insertElementAt(this, i); if (Thread.currentThread() != notifier.primaryThread) { notifier.notifyAll(); } } } /* *---------------------------------------------------------------------- * * cancel -- * * Mark this timer handler as cancelled so that it won't be * invoked. * * Results: * None. * * Side effects: * The timer handler is marked as cancelled so that its * processTimerEvent() method will not be called. If the timer * has already fired, then nothing this call has no effect. * *---------------------------------------------------------------------- */ public synchronized void cancel() { if (isCancelled) { return; } isCancelled = true; synchronized(notifier) { for (int i = 0; i < notifier.timerList.size(); i++) { if (notifier.timerList.elementAt(i) == this) { notifier.timerList.removeElementAt(i); /* * We can return now because the same timer can be * registered only once in the list of timers. */ return; } } } } /* *---------------------------------------------------------------------- * * invoke -- * * Execute the timer handler if it has not been cancelled. This * method should be called by the notifier only. * * Because the timer handler may be being cancelled by another * thread, both this method and cancel() must be synchronized to * ensure correctness. * * Results: * 0 if the handler was not executed because it was already * cancelled, 1 otherwise. * * Side effects: * The timer handler may have arbitrary side effects. * *---------------------------------------------------------------------- */ synchronized final int invoke() { /* * The timer may be cancelled after it was put on the * event queue. Check its isCancelled field to make sure it's * not cancelled. */ if (!isCancelled) { processTimerEvent(); return 1; } else { return 0; } } /* *---------------------------------------------------------------------- * * processTimerEvent -- * * This method is called when the timer is expired. Override * This method to implement your own timer handlers. * * Results: * None. * * Side effects: * It can do anything. * *---------------------------------------------------------------------- */ abstract public void processTimerEvent(); } // end TimerHandler