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; } }