/*
* JBossMQ, the OpenSource JMS implementation
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.mq.server;
import EDU.oswego.cs.dl.util.concurrent.Heap;
/**
* Much like the java.util.Timer class, except a separate
* thread is launched only when a new task appears.
* Another useful feature is that all pending tasks may be canceled without
* invalidating the whole timer.
*/
final class SimpleTimer
extends Thread
{
// Count of created instances, for setting default thread name
private static int creationCount = 0;
// Basic heap
private Heap heap = new Heap(16);
// Flag indicating timer is canceled
private boolean canceled = false;
/**
* Constructs a new SimpleTimer with a thread default name and
* by default as a daemon.
*/
public SimpleTimer() {
setName("SimpleTimer-" + creationCount++);
setDaemon(true);
}
/**
* Returns the number of tasks.
*/
public int size()
{
return heap.size();
}
/**
* Clears all currently scheduled tasks.
*/
public void clear()
{
heap.clear();
}
/**
* Terminates all timer tasks, ends this thread.
*/
public synchronized void cancel()
{
clear();
canceled = true;
interrupt();
}
private SimpleTimerTask peekNextTask()
{
return (SimpleTimerTask)heap.peek();
}
/**
* Schedules a task on the specified heap, at a specific time.
* The heap must have been previously registered using the method {@link #add}.
*/
public void schedule(SimpleTimerTask task, long at)
{
task.scheduled = at;
synchronized (this)
{
if (!isAlive())
start();
heap.insert(task);
if (task == peekNextTask())
notify();
}
}
public void run()
{
while (true)
{
try
{
SimpleTimerTask task;
boolean execute = false;
synchronized (this)
{
// No tasks, so wait for one...
while ((task = peekNextTask()) == null && !canceled)
wait();
if (canceled)
break;
// Check if we're ready for this task
long now = System.currentTimeMillis();
long duration = task.scheduled - now;
if (duration > 0)
{
wait(duration);
}
else
{
execute = true;
heap.extract();
}
}
// Do not lock when running
if (execute)
task.run();
}
catch (InterruptedException e) {}
}
}
/**
* Calls cancel on this object.
*/
protected void finalize() {
cancel();
}
}