/* * 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; } }