/*
* Copyright 2014-2015 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wplatform.ddal.util;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A method call that is executed in a separate thread. If the method throws an
* exception, it is wrapped in a RuntimeException.
*/
public abstract class Task implements Runnable {
private static AtomicInteger counter = new AtomicInteger();
/**
* A flag indicating the get() method has been called.
*/
protected volatile boolean stop;
/**
* The result, if any.
*/
protected Object result;
private volatile boolean finished;
private Thread thread;
private Exception ex;
/**
* The method to be implemented.
*
* @throws Exception any exception is wrapped in a RuntimeException
*/
public abstract void call() throws Exception;
@Override
public void run() {
try {
call();
} catch (Exception e) {
this.ex = e;
}
finished = true;
}
/**
* Start the thread.
*
* @return this
*/
public Task execute() {
return execute(getClass().getName() + ":" + counter.getAndIncrement());
}
/**
* Start the thread.
*
* @param threadName the name of the thread
* @return this
*/
public Task execute(String threadName) {
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start();
return this;
}
/**
* Calling this method will set the stop flag and wait until the thread is
* stopped.
*
* @return the result, or null
* @throws RuntimeException if an exception in the method call occurs
*/
public Object get() {
Exception e = getException();
if (e != null) {
throw new RuntimeException(e);
}
return result;
}
/**
* Whether the call method has returned (with or without exception).
*
* @return true if yes
*/
public boolean isFinished() {
return finished;
}
/**
* Get the exception that was thrown in the call (if any).
*
* @return the exception or null
*/
public Exception getException() {
stop = true;
if (thread == null) {
throw new IllegalStateException("Thread not started");
}
try {
thread.join();
} catch (InterruptedException e) {
// ignore
}
if (ex != null) {
return ex;
}
return null;
}
}