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