3 import java.util.concurrent.atomic.AtomicBoolean;
4 import java.util.concurrent.atomic.AtomicLong;
6 import era.mi.logic.timeline.Timeline;
8 public class LogicExecuter
10 // TODO replace with LogicModel when it exists
11 private final Timeline timeline;
13 private final AtomicBoolean shouldBeRunningLive;
14 private final AtomicBoolean isRunningLive;
15 private final AtomicLong nextExecSimulTime;
16 private final Thread simulationThread;
18 public LogicExecuter(Timeline timeline)
20 this.timeline = timeline;
22 timeline.setTimeFunction(System::currentTimeMillis);
23 shouldBeRunningLive = new AtomicBoolean();
24 isRunningLive = new AtomicBoolean();
25 nextExecSimulTime = new AtomicLong();
26 simulationThread = new Thread(() ->
28 isRunningLive.set(true);
29 while (shouldBeRunningLive.get())
31 // always execute to keep timeline from "hanging behind" for too long
32 long current = System.currentTimeMillis();
33 timeline.executeUntil(timeline.laterThan(current), current + 10);
35 if (timeline.hasNext())
36 sleepTime = timeline.nextEventTime() - current;
41 nextExecSimulTime.set(current + sleepTime);
43 Thread.sleep(sleepTime);
45 catch (InterruptedException e)
46 {// do nothing; it is normal execution flow to be interrupted
49 isRunningLive.set(false);
51 timeline.addEventAddedListener(event ->
53 if (isRunningLive.get())
54 if (Timeline.timeCmp(event.getTiming(), nextExecSimulTime.get()) < 0)
55 simulationThread.interrupt();
59 public void executeNextStep()
61 timeline.executeNext();
64 public synchronized void startLiveExecution()
66 if (shouldBeRunningLive.get())
68 shouldBeRunningLive.set(true);
69 simulationThread.start();
70 while (!isRunningLive.get())
74 public synchronized void stopLiveExecution()
76 if (!shouldBeRunningLive.get())
78 shouldBeRunningLive.set(false);
79 simulationThread.interrupt();
80 while (isRunningLive.get())