/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*/
package com.sun.sgs.impl.kernel.schedule;
import com.sun.sgs.kernel.schedule.ScheduledTask;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* Package-private utility class that handles timers for tasks that are
* scheduled to run in the future.
*/
class TimedTaskHandler {
/**
* The milliseconds in the future that a task must be to be accepted
* by the handler.
*/
static final int FUTURE_THRESHOLD = 15;
// the listener that will consume ready tasks
private final TimedTaskListener listener;
// the timer used for future execution
private Timer timer;
/**
* Creates an instance of <code>TimedTaskHandler</code>. This has the
* effect of creating a new <code>Timer</code> which involves creating
* at least one new thread.
*
* @param listener the <code>TimedTaskListener</code> that will consume
* the task when its time comes, causing it to be executed
*/
TimedTaskHandler(TimedTaskListener listener) {
if (listener == null) {
throw new NullPointerException("Listener cannot be null");
}
this.listener = listener;
timer = new Timer();
}
/**
* Tries to pass off a task to be run at some point in the future. If
* the task should be run directly instead of delayed, then it is
* rejected and the method returns <code>false</code>.
*
* @param task the <code>ScheduledTask</code> to run in the future
*
* @return <code>true</code> if the task is accepted to run delayed,
* <code>false</code> otherwise
*/
boolean runDelayed(ScheduledTask task) {
// see if this is far enough in the future that it's worth handling
if (task.getStartTime() < (System.currentTimeMillis() +
FUTURE_THRESHOLD)) {
return false;
}
TimerTask tt = new TimerTaskImpl(task);
// if this task is recurring, set the timer task if it's still active
if (task.isRecurring()) {
RecurringTaskHandleImpl handle =
(RecurringTaskHandleImpl) (task.getRecurringTaskHandle());
synchronized (handle) {
// if the recurring task is cancelled, then say that we're
// handling it, which has the effect of the task being dropped
if (handle.isCancelled()) {
return true;
}
handle.setTimerTask(tt);
}
}
timer.schedule(tt, new Date(task.getStartTime()));
return true;
}
/**
* Shuts down this handler, cancelling the associated timer.
*/
void shutdown() {
timer.cancel();
}
/**
* Private inner class implementation of <code>TimerTask</code>. This is
* used to schedule all delayed tasks.
*/
private class TimerTaskImpl extends TimerTask {
private final ScheduledTask task;
private boolean cancelled = false;
TimerTaskImpl(ScheduledTask task) {
this.task = task;
}
/** {@inheritDoc} */
public synchronized boolean cancel() {
if (!cancelled) {
cancelled = true;
return true;
}
return false;
}
/** {@inheritDoc} */
public long scheduledExecutionTime() {
return task.getStartTime();
}
/** {@inheritDoc} */
public synchronized void run() {
if (!cancelled) {
listener.timedTaskReady(task);
}
cancelled = true;
}
}
}