-package org.simantics.simulation.sequences.action;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.List;\r
-import java.util.PriorityQueue;\r
-\r
-import org.simantics.scl.runtime.SCLContext;\r
-import org.simantics.scl.runtime.function.Function1;\r
-import org.simantics.scl.runtime.tuple.Tuple0;\r
-\r
-public abstract class AbstractActionContext implements ActionContext {\r
- public static final double TIME_TOLERANCE = 1e-6;\r
- \r
- double currentTime;\r
- volatile boolean stopped;\r
- ArrayList<Function1<Tuple0, Object>> scheduledNow = new ArrayList<Function1<Tuple0, Object>>();\r
- ArrayList<Function1<Tuple0, Object>> scheduledNextStep = new ArrayList<Function1<Tuple0, Object>>();\r
- PriorityQueue<Task> scheduledAt = new PriorityQueue<Task>();\r
-\r
- public List<Exception> exceptions; \r
- \r
- private static class Task implements Comparable<Task> {\r
- final double time;\r
- final Function1<Tuple0, Object> continuation;\r
- \r
- public Task(double time, Function1<Tuple0, Object> continuation) {\r
- this.time = time;\r
- this.continuation = continuation;\r
- }\r
-\r
- @Override\r
- public int compareTo(Task o) {\r
- return Double.compare(time, o.time);\r
- }\r
- }\r
- \r
- @Override\r
- public double time() {\r
- return currentTime;\r
- }\r
- \r
- @Override\r
- public void scheduleNow(Function1<Tuple0, Object> continuation) {\r
- scheduledNow.add(continuation);\r
- }\r
- \r
- @Override\r
- public void scheduleNextStep(Function1<Tuple0, Object> continuation) {\r
- scheduledNextStep.add(continuation);\r
- }\r
- \r
- @Override\r
- public void scheduleAt(double time, Function1<Tuple0, Object> continuation) {\r
- if(time <= currentTime)\r
- scheduleNow(continuation);\r
- else\r
- scheduledAt.add(new Task(time, continuation));\r
- }\r
- \r
- @Override\r
- public void stop() {\r
- stopped = true;\r
- }\r
- \r
- public boolean isStopped() {\r
- synchronized (this) {\r
- return stopped || (scheduledNextStep.isEmpty() && scheduledAt.isEmpty());\r
- }\r
- }\r
- \r
- public double handleStep(double currentTime) {\r
- synchronized (this) {\r
- this.currentTime = currentTime;\r
- {\r
- ArrayList<Function1<Tuple0, Object>> temp = scheduledNow;\r
- scheduledNow = scheduledNextStep;\r
- scheduledNextStep = temp;\r
- Collections.reverse(scheduledNow);\r
- }\r
- \r
- SCLContext context = SCLContext.getCurrent();\r
- Object oldActionContext = context.put("sequenceAction", this);\r
- try {\r
- Task firstTask = scheduledAt.peek();\r
- while(true) {\r
- while(!scheduledNow.isEmpty()) {\r
- try {\r
- Function1<Tuple0, Object> currentContinuation = scheduledNow.remove(scheduledNow.size()-1);\r
- currentContinuation.apply(Tuple0.INSTANCE);\r
- currentContinuation = null;\r
- } catch (Exception e) {\r
- if (this.exceptions == null)\r
- this.exceptions = new ArrayList<Exception>();\r
- this.exceptions.add(new RuntimeException("Action failure at " + currentTime + ": " + e.getMessage(), e));\r
- }\r
- }\r
- if(firstTask == null)\r
- return Double.POSITIVE_INFINITY;\r
- else if(firstTask.time > currentTime+TIME_TOLERANCE)\r
- return firstTask.time;\r
- else {\r
- firstTask.continuation.apply(Tuple0.INSTANCE);\r
- synchronized (this) {\r
- scheduledAt.remove();\r
- }\r
- firstTask = scheduledAt.peek();\r
- }\r
- }\r
- } finally {\r
- context.put("sequenceAction", oldActionContext);\r
- }\r
- }\r
- }\r
-}\r
+package org.simantics.simulation.sequences.action;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.PriorityQueue;
+
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.tuple.Tuple0;
+
+public abstract class AbstractActionContext implements ActionContext {
+ public static final double TIME_TOLERANCE = 1e-6;
+
+ double currentTime;
+ volatile boolean stopped;
+ ArrayList<Function1<Tuple0, Object>> scheduledNow = new ArrayList<Function1<Tuple0, Object>>();
+ ArrayList<Function1<Tuple0, Object>> scheduledNextStep = new ArrayList<Function1<Tuple0, Object>>();
+ PriorityQueue<Task> scheduledAt = new PriorityQueue<Task>();
+
+ public List<Exception> exceptions;
+
+ private static class Task implements Comparable<Task> {
+ final double time;
+ final Function1<Tuple0, Object> continuation;
+
+ public Task(double time, Function1<Tuple0, Object> continuation) {
+ this.time = time;
+ this.continuation = continuation;
+ }
+
+ @Override
+ public int compareTo(Task o) {
+ return Double.compare(time, o.time);
+ }
+ }
+
+ @Override
+ public double time() {
+ return currentTime;
+ }
+
+ @Override
+ public void scheduleNow(Function1<Tuple0, Object> continuation) {
+ scheduledNow.add(continuation);
+ }
+
+ @Override
+ public void scheduleNextStep(Function1<Tuple0, Object> continuation) {
+ scheduledNextStep.add(continuation);
+ }
+
+ @Override
+ public void scheduleAt(double time, Function1<Tuple0, Object> continuation) {
+ if(time <= currentTime)
+ scheduleNow(continuation);
+ else
+ scheduledAt.add(new Task(time, continuation));
+ }
+
+ @Override
+ public void stop() {
+ stopped = true;
+ }
+
+ public boolean isStopped() {
+ synchronized (this) {
+ return stopped || (scheduledNextStep.isEmpty() && scheduledAt.isEmpty());
+ }
+ }
+
+ public double handleStep(double currentTime) {
+ synchronized (this) {
+ this.currentTime = currentTime;
+ {
+ ArrayList<Function1<Tuple0, Object>> temp = scheduledNow;
+ scheduledNow = scheduledNextStep;
+ scheduledNextStep = temp;
+ Collections.reverse(scheduledNow);
+ }
+
+ SCLContext context = SCLContext.getCurrent();
+ Object oldActionContext = context.put("sequenceAction", this);
+ try {
+ Task firstTask = scheduledAt.peek();
+ while(true) {
+ while(!scheduledNow.isEmpty()) {
+ try {
+ Function1<Tuple0, Object> currentContinuation = scheduledNow.remove(scheduledNow.size()-1);
+ currentContinuation.apply(Tuple0.INSTANCE);
+ currentContinuation = null;
+ } catch (Exception e) {
+ if (this.exceptions == null)
+ this.exceptions = new ArrayList<Exception>();
+ this.exceptions.add(new RuntimeException("Action failure at " + currentTime + ": " + e.getMessage(), e));
+ }
+ }
+ if(firstTask == null)
+ return Double.POSITIVE_INFINITY;
+ else if(firstTask.time > currentTime+TIME_TOLERANCE)
+ return firstTask.time;
+ else {
+ firstTask.continuation.apply(Tuple0.INSTANCE);
+ synchronized (this) {
+ scheduledAt.remove();
+ }
+ firstTask = scheduledAt.peek();
+ }
+ }
+ } finally {
+ context.put("sequenceAction", oldActionContext);
+ }
+ }
+ }
+}