The final restructured version for automatic build using maven tycho
[Mograsim.git] / plugins / net.mograsim.logic.model / src / net / mograsim / logic / model / LogicExecuter.java
1 package net.mograsim.logic.model;
2
3 import java.util.concurrent.atomic.AtomicBoolean;
4 import java.util.concurrent.atomic.AtomicLong;
5
6 import net.mograsim.logic.core.timeline.Timeline;
7
8 //TODO maybe move to logic core?
9 public class LogicExecuter
10 {
11         // TODO replace with CoreModel when it exists
12         private final Timeline timeline;
13
14         private final AtomicBoolean shouldBeRunningLive;
15         private final AtomicBoolean isRunningLive;
16         private final AtomicLong nextExecSimulTime;
17         private final Thread simulationThread;
18
19         public LogicExecuter(Timeline timeline)
20         {
21                 this.timeline = timeline;
22
23                 timeline.setTimeFunction(System::currentTimeMillis);
24                 shouldBeRunningLive = new AtomicBoolean();
25                 isRunningLive = new AtomicBoolean();
26                 nextExecSimulTime = new AtomicLong();
27                 simulationThread = new Thread(() ->
28                 {
29                         isRunningLive.set(true);
30                         synchronized (isRunningLive)
31                         {
32                                 isRunningLive.notify();
33                         }
34                         try
35                         {
36                                 while (shouldBeRunningLive.get())
37                                 {
38                                         // always execute to keep timeline from "hanging behind" for too long
39                                         long current = System.currentTimeMillis();
40                                         timeline.executeUntil(timeline.laterThan(current), current + 10);
41                                         long sleepTime;
42                                         if (timeline.hasNext())
43                                                 sleepTime = timeline.nextEventTime() - current;
44                                         else
45                                                 sleepTime = 10000;
46                                         try
47                                         {
48                                                 nextExecSimulTime.set(current + sleepTime);
49                                                 if (sleepTime > 0)
50                                                         Thread.sleep(sleepTime);
51                                         }
52                                         catch (@SuppressWarnings("unused") InterruptedException e)
53                                         {// do nothing; it is normal execution flow to be interrupted
54                                         }
55                                 }
56                         }
57                         finally
58                         {
59                                 isRunningLive.set(false);
60                                 synchronized (isRunningLive)
61                                 {
62                                         isRunningLive.notify();
63                                 }
64                         }
65                 });
66                 timeline.addEventAddedListener(event ->
67                 {
68                         if (isRunningLive.get())
69                                 if (Timeline.timeCmp(event.getTiming(), nextExecSimulTime.get()) < 0)
70                                         simulationThread.interrupt();
71                 });
72         }
73
74         public void executeNextStep()
75         {
76                 timeline.executeNext();
77         }
78
79         public synchronized void startLiveExecution()
80         {
81                 if (shouldBeRunningLive.get())
82                         return;
83                 shouldBeRunningLive.set(true);
84                 simulationThread.start();
85                 waitForIsRunning(true);
86         }
87
88         public synchronized void stopLiveExecution()
89         {
90                 if (!shouldBeRunningLive.get())
91                         return;
92                 shouldBeRunningLive.set(false);
93                 simulationThread.interrupt();
94                 waitForIsRunning(false);
95         }
96
97         private void waitForIsRunning(boolean expectedState)
98         {
99                 while (isRunningLive.get() ^ expectedState)
100                         try
101                         {
102                                 synchronized (isRunningLive)
103                                 {
104                                         isRunningLive.wait();
105                                 }
106                         }
107                         catch (@SuppressWarnings("unused") InterruptedException e)
108                         {// no need to do anything
109                         }
110         }
111 }