/*
* TaskThread.java
* Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
* @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package tr.gov.ulakbim.jDenetX.tasks;
import tr.gov.ulakbim.jDenetX.core.ObjectRepository;
import tr.gov.ulakbim.jDenetX.core.TimingUtils;
import java.util.concurrent.CopyOnWriteArraySet;
public class TaskThread extends Thread {
public static enum Status {
NOT_STARTED, RUNNING, PAUSED, CANCELLING, CANCELLED, COMPLETED, FAILED
}
protected Task runningTask;
protected volatile Status currentStatus;
protected TaskMonitor taskMonitor;
protected ObjectRepository repository;
protected Object finalResult;
protected long taskStartTime;
protected long taskEndTime;
protected double latestPreviewGrabTime = 0.0;
CopyOnWriteArraySet<TaskCompletionListener> completionListeners = new CopyOnWriteArraySet<TaskCompletionListener>();
public TaskThread(Task toRun) {
this(toRun, null);
}
public TaskThread(Task toRun, ObjectRepository repository) {
this.runningTask = toRun;
this.repository = repository;
this.currentStatus = Status.NOT_STARTED;
this.taskMonitor = new StandardTaskMonitor();
this.taskMonitor.setCurrentActivityDescription("Running task " + toRun);
}
@Override
public void run() {
TimingUtils.enablePreciseTiming();
this.taskStartTime = TimingUtils.getNanoCPUTimeOfThread(getId());
try {
this.currentStatus = Status.RUNNING;
this.finalResult = this.runningTask.doTask(this.taskMonitor,
this.repository);
this.currentStatus = this.taskMonitor.isCancelled() ? Status.CANCELLED
: Status.COMPLETED;
} catch (Throwable ex) {
this.currentStatus = Status.FAILED;
this.finalResult = new FailedTaskReport(ex);
}
this.taskEndTime = TimingUtils.getNanoCPUTimeOfThread(getId());
fireTaskCompleted();
this.taskMonitor.setLatestResultPreview(null); // free preview memory
}
public synchronized void pauseTask() {
if (this.currentStatus == Status.RUNNING) {
this.taskMonitor.requestPause();
this.currentStatus = Status.PAUSED;
}
}
public synchronized void resumeTask() {
if (this.currentStatus == Status.PAUSED) {
this.taskMonitor.requestResume();
this.currentStatus = Status.RUNNING;
}
}
public synchronized void cancelTask() {
if ((this.currentStatus == Status.RUNNING)
|| (this.currentStatus == Status.PAUSED)) {
this.taskMonitor.requestCancel();
this.currentStatus = Status.CANCELLING;
}
}
public double getCPUSecondsElapsed() {
double secondsElapsed = 0.0;
if (this.currentStatus == Status.NOT_STARTED) {
secondsElapsed = 0.0;
} else if (isComplete()) {
secondsElapsed = TimingUtils.nanoTimeToSeconds(this.taskEndTime
- this.taskStartTime);
} else {
secondsElapsed = TimingUtils.nanoTimeToSeconds(TimingUtils
.getNanoCPUTimeOfThread(getId())
- this.taskStartTime);
}
return secondsElapsed > 0.0 ? secondsElapsed : 0.0;
}
public Task getTask() {
return this.runningTask;
}
public String getCurrentStatusString() {
switch (this.currentStatus) {
case NOT_STARTED:
return "not started";
case RUNNING:
return "running";
case PAUSED:
return "paused";
case CANCELLING:
return "cancelling";
case CANCELLED:
return "cancelled";
case COMPLETED:
return "completed";
case FAILED:
return "failed";
}
return "unknown";
}
public String getCurrentActivityString() {
return (isComplete() || (this.currentStatus == Status.NOT_STARTED)) ? ""
: this.taskMonitor.getCurrentActivityDescription();
}
public double getCurrentActivityFracComplete() {
switch (this.currentStatus) {
case NOT_STARTED:
return 0.0;
case RUNNING:
case PAUSED:
case CANCELLING:
return this.taskMonitor.getCurrentActivityFractionComplete();
case CANCELLED:
case COMPLETED:
case FAILED:
return 1.0;
}
return 0.0;
}
public boolean isComplete() {
return ((this.currentStatus == Status.CANCELLED)
|| (this.currentStatus == Status.COMPLETED) || (this.currentStatus == Status.FAILED));
}
public Object getFinalResult() {
return this.finalResult;
}
public void addTaskCompletionListener(TaskCompletionListener tcl) {
this.completionListeners.add(tcl);
}
public void removeTaskCompletionListener(TaskCompletionListener tcl) {
this.completionListeners.remove(tcl);
}
protected void fireTaskCompleted() {
for (TaskCompletionListener listener : this.completionListeners) {
listener.taskCompleted(this);
}
}
public void getPreview(ResultPreviewListener previewer) {
this.taskMonitor.requestResultPreview(previewer);
this.latestPreviewGrabTime = getCPUSecondsElapsed();
}
public Object getLatestResultPreview() {
return this.taskMonitor.getLatestResultPreview();
}
public double getLatestPreviewGrabTimeSeconds() {
return this.latestPreviewGrabTime;
}
}