+package org.simantics.simulator.toolkit;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.simulator.IDynamicExperimentLocal;
+
+/**
+ * @author Antti Villberg
+ * @since 1.34.0
+ */
+public class DynamicExperimentThreadSequenceRunner {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static DynamicExperimentActionContext runAction(IDynamicExperimentLocal experiment, DynamicExperimentThread thread, Function action, final boolean simulateAndWaitCompletion) {
+ final DynamicExperimentActionContext context = new DynamicExperimentActionContext(experiment);
+ context.scheduleNextStep(action);
+ final Object sync = new Object();
+ final SCLContext sclContext = SCLContext.getCurrent();
+
+ thread.addListener(new DynamicExperimentThreadListener() {
+
+ @Override
+ public void beforeStep() {
+ if(!context.isStopped()) {
+ SCLContext.push(sclContext);
+ context.handleStep(experiment.getSimulationTime());
+ SCLContext.pop();
+ }
+ removeIfStopped();
+ }
+
+ public void removeIfStopped() {
+ if(context.isStopped()) {
+ thread.removeListener(this);
+ if(simulateAndWaitCompletion) {
+ experiment.simulate(false);
+ synchronized(sync) {
+ sync.notify();
+ }
+ }
+ experiment.shutdown(new NullProgressMonitor());
+ }
+ }
+
+ });
+
+ if(simulateAndWaitCompletion) {
+ experiment.simulate(true);
+
+ try {
+ synchronized(sync) {
+ while(!context.isStopped())
+ sync.wait(1000L);
+ }
+ } catch(InterruptedException e) {
+ context.stop();
+ }
+
+ if (context.exceptions != null && !context.exceptions.isEmpty()) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Action failures:");
+ for (Exception e : context.exceptions) {
+ builder.append("\n");
+ builder.append(e.getMessage());
+ }
+
+ throw new RuntimeException(builder.toString());
+ }
+ }
+ return context;
+ }
+}