/*
* FreeMarker: a tool that allows Java programs to generate HTML
* output using templates.
* Copyright (C) 1998-2004 Benjamin Geer
* Email: beroul@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package freemarker.template.cache;
/**
* <p>
* A timer for objects that implement <tt>Updateable</tt>. Creates a new thread,
* in which it periodically calls the <tt>Updateable</tt>'s <tt>update()</tt>
* method.
* </p>
*
* <p>
* Uses techniques from the document "Why Are <code>Thread.stop</code>,
* <code>Thread.suspend</code>, <code>Thread.resume</code> and
* <code>Runtime.runFinalizersOnExit</code> Deprecated?", from the Java API
* documentation.
* </p>
*
* @version $Id: UpdateTimer.java 987 2004-10-05 10:13:24Z run2000 $
*/
public final class UpdateTimer implements Runnable {
private final Updateable target;
private final Long delay;
private volatile Thread timerThread;
/**
* Constructs the timer with the update target and update interval.
*
* @param target
* the object to be updated.
* @param delay
* the number of milliseconds between updates.
*/
public UpdateTimer(Updateable target, long delay) {
this.target = target;
this.delay = new Long(delay);
}
/**
* Begins periodic automatic updates of the target. Since it can't be
* determined if an existing thread is Runnable or not, create and start a
* new thread
*
* @param niceness
* How much to decrease the priority of the timer thread by. The
* value is applied against the default priority of the new
* thread. The value may be negative, to indicate that the thread
* should have a greater priority than the default.
*/
public void startTiming(int niceness) {
int priority;
timerThread = new Thread(this);
priority = timerThread.getPriority();
// "Nice" the new thread, to run it at a lower priority than
// the threads actually servicing requests. Note that we don't
// want to set the thread to minimum priority, since this would
// result in the thread only being able to run when no other threads
// are active. Similarly, maximum priority would also be bad.
if ((niceness != 0) && (priority - niceness > Thread.MIN_PRIORITY) && (priority - niceness < Thread.MAX_PRIORITY)) {
timerThread.setPriority(priority - niceness);
}
timerThread.start();
}
/**
* Stops (immediately) automatically updating the target.
*/
public void stopTiming() {
Thread oldThread = timerThread;
timerThread = null;
if (oldThread != null) {
oldThread.interrupt();
}
}
/**
* Waits for the given period, then calls <code>update()</code>, if
* required. If someone decides to kill this thread, exit immediately.
*/
public void run() {
while (timerThread != null) {
try {
Thread.sleep(delay.longValue());
if (timerThread != null) {
target.update();
}
} catch (InterruptedException e) {
// Do nothing. If the thread needs to be killed, then the
// outer while loop will return false.
}
}
}
}