package ilarkesto.concurrent;
import ilarkesto.core.logging.Log;
public abstract class ATask {
private static final Log LOG = Log.get(ATask.class);
private volatile boolean finished;
private long finishTime = -1;
private volatile boolean started;
private long startTime = -1;
private volatile boolean abortRequested;
private Thread thread;
// --- dependencies ---
private long maxSleepAtOnce = 1000;
public final void setMaxSleepAtOnce(long maxSleepAtOnce) {
this.maxSleepAtOnce = maxSleepAtOnce;
}
protected abstract void perform() throws InterruptedException;
public float getProgress() {
return isFinished() ? 1 : 0;
}
public String getProgressMessage() {
return null;
}
// --- ---
public final boolean isFinished() {
return finished;
}
public final long getFinishTime() {
return finishTime;
}
public final boolean isStarted() {
return started;
}
public final long getStartTime() {
return startTime;
}
public final boolean isAbortRequested() {
return abortRequested;
}
public void abort() {
this.abortRequested = true;
}
public final boolean isRunning() {
return started && !finished;
}
public final long getRunTime() {
if (startTime < 0) return -1;
long endTime = finishTime < 0 ? System.currentTimeMillis() : finishTime;
return endTime - startTime;
}
public void reset() {
if (isRunning()) {
abort();
try {
waitForFinish();
} catch (InterruptedException ex) {
// nop
}
}
started = false;
finished = false;
abortRequested = false;
}
public final void run() {
this.thread = Thread.currentThread();
if (started) throw new RuntimeException("Task already started: " + this);
started = true;
startTime = System.currentTimeMillis();
try {
perform();
} catch (InterruptedException ex) {
// all right
} catch (Throwable ex) {
LOG.error("Task execution failed:", this, ex);
throw new RuntimeException(ex);
} finally {
finished = true;
finishTime = System.currentTimeMillis();
synchronized (this) {
this.notifyAll();
}
thread = null;
}
}
public final void waitForFinish() throws InterruptedException {
while (!isFinished()) {
synchronized (this) {
this.wait(1000);
}
}
}
public final void sleep(long millis) throws InterruptedException {
while (!abortRequested && millis > 0) {
long sleep = millis > maxSleepAtOnce ? maxSleepAtOnce : millis;
Thread.sleep(sleep);
millis -= sleep;
}
}
public final Thread getThread() {
return thread;
}
public final String getThreadName() {
if (thread == null) return null;
return thread.getName();
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}