package org.simantics.graphviz.continuation; import java.util.ArrayList; import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; public abstract class Computation { T result; Exception exception; ArrayList> continuations = new ArrayList>(); CountDownLatch doneGate = new CountDownLatch(1); public void addContinuation(Continuation continuation) { synchronized(doneGate) { if(doneGate.getCount() == 0) { if(exception == null) continuation.succeeded(result); else continuation.failed(exception); } else continuations.add(continuation); } } public boolean isDone() { return doneGate.getCount() == 0; } protected void failWith(Exception exception) { this.exception = exception; ArrayList> cs; synchronized (doneGate) { cs = this.continuations; this.continuations = null; doneGate.countDown(); } if(cs != null) for(Continuation continuation : cs) continuation.failed(exception); } protected void doneWith(T result) { this.result = result; ArrayList> cs; synchronized (doneGate) { cs = this.continuations; this.continuations = null; doneGate.countDown(); } if(cs != null) for(Continuation continuation : cs) continuation.succeeded(result); } public void cancel() { failWith(new CancellationException()); } public T get() throws Exception { doneGate.await(); if(exception != null) throw exception; return result; } }