package hdgl.db.task;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
*
* @author elm
*
* @param <T>
*/
public class CallableAsyncResult<T> implements Runnable, Callable<T>, AsyncResult<T> {
Callable<T> callable;
Vector<AsyncCallback<T>> listeners = new Vector<AsyncCallback<T>>();
boolean cancelled;
boolean done;
boolean started;
Throwable exception;
T result;
Thread runningThread;
public CallableAsyncResult(){
this.started = false;
this.cancelled = false;
this.done = false;
}
public CallableAsyncResult(Callable<T> callable){
this.callable = callable;
this.started = false;
this.cancelled = false;
this.done = false;
}
@Override
public void run() {
try{
call();
}catch(ExecutionException ex){
//该异常已被处理,此处忽略即可
}
}
@Override
public T call() throws ExecutionException {
boolean succ;
synchronized(this){
started = true;
}
for(AsyncCallback<T> callback:listeners){
callback.started();
callback.progress(0);
}
try{
if(callable!=null){
setValue(callable.call());
}
succ = true;
}catch(Throwable ex){
setException(ex);
succ = false;
}
synchronized(this){
this.done = true;
this.notifyAll();
}
if(succ){
for(AsyncCallback<T> callback:listeners){
callback.progress(1);
callback.completed(result);
}
return result;
}else{
for(AsyncCallback<T> callback:listeners){
callback.exception(exception);
}
throw new ExecutionException(exception);
}
}
@Override
public boolean supportCancel() {
return true;
}
@Override
public void addCallback(AsyncCallback<T> callback) {
listeners.add(callback);
}
@Override
public void removeCallback(AsyncCallback<T> callback) {
listeners.remove(callback);
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean result;
synchronized(this){
if(cancelled){
result = false;
}else if(!this.started){
this.started = true;
this.cancelled = true;
this.done = true;
result = true;
}else{
if(mayInterruptIfRunning){
if(runningThread!=null){
runningThread.interrupt();
}
this.cancelled = true;
this.done = true;
result = true;
}else{
result = false;
}
}
}
if(result){
for(AsyncCallback<T> callback:listeners){
callback.cancelled();
}
synchronized(this){
this.notifyAll();
}
}
return cancelled||result;
}
@Override
public T get() throws InterruptedException, ExecutionException {
boolean starting = false;
synchronized(this){
if(!started){
starting = true;
}
if(cancelled){
throw new CancellationException();
}else if(exception!=null){
throw new ExecutionException(exception);
}else if(done){
return result;
}
}
if(starting){
start();
}
synchronized(this){
this.wait();
if(cancelled){
throw new CancellationException();
}else if(exception!=null){
throw new ExecutionException(exception);
}else if(done){
return result;
}else{
throw new InterruptedException();
}
}
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
boolean starting = false;
synchronized(this){
if(!started){
starting = true;
}
if(cancelled){
throw new CancellationException();
}else if(exception!=null){
throw new ExecutionException(exception);
}else if(done){
return result;
}
}
if(starting){
start();
}
synchronized(this){
unit.timedWait(this, timeout);
if(cancelled){
throw new CancellationException();
}else if(exception!=null){
throw new ExecutionException(exception);
}else if(done){
return result;
}else{
throw new TimeoutException();
}
}
}
@Override
public boolean isCancelled() {
return cancelled;
}
public void setValue(T val){
synchronized(this){
this.done = true;
this.result = val;
this.notifyAll();
}
}
public void setException(Throwable ex){
synchronized(this){
this.exception = ex;
this.notifyAll();
}
}
@Override
public boolean isDone() {
return done;
}
@Override
public void start() {
boolean starting = !started;
synchronized(this){
starting =! started;
if(!started){
started = true;
}
}
if(starting){
runningThread = new Thread(this);
runningThread.setDaemon(false);
runningThread.start();
}
}
}