Fixed execution freezing when the next queued event has a long delta
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Thu, 26 Sep 2019 12:56:22 +0000 (14:56 +0200)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Thu, 26 Sep 2019 12:56:22 +0000 (14:56 +0200)
plugins/net.mograsim.logic.core/src/net/mograsim/logic/core/timeline/PauseableTimeFunction.java
plugins/net.mograsim.logic.model/src/net/mograsim/logic/model/LogicExecuter.java

index ed95ec0..fc4aa13 100644 (file)
@@ -1,5 +1,8 @@
 package net.mograsim.logic.core.timeline;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
 import java.util.function.LongSupplier;
 
 public class PauseableTimeFunction implements LongSupplier
@@ -8,6 +11,8 @@ public class PauseableTimeFunction implements LongSupplier
        private long unpausedSysTime = 0, lastPausedInternalTime = 0;
        private double speedFactor = 1;
 
+       private final List<Consumer<Double>> simulTimeToRealTimeFactorChangedListeners = new ArrayList<>();
+
        public void pause()
        {
                if (!paused)
@@ -33,9 +38,9 @@ public class PauseableTimeFunction implements LongSupplier
                                : lastPausedInternalTime + (System.nanoTime() / 1000 - unpausedSysTime) * speedFactor);
        }
 
-       public long simulTimeDeltaToRealTimeMillis(long simulTime)
+       public double getSimulTimeToRealTimeFactor()
        {
-               return paused ? -1 : (long) (simulTime / speedFactor / 1000);
+               return 1 / 1000 / speedFactor;
        }
 
        public void setSpeedFactor(double factor)
@@ -48,8 +53,18 @@ public class PauseableTimeFunction implements LongSupplier
                        unpause();
                }
                this.speedFactor = factor;
+               callSimulTimeToRealTimeFactorChangedListeners(getSimulTimeToRealTimeFactor());
        }
 
+       //@formatter:off
+       public void    addSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
+               {simulTimeToRealTimeFactorChangedListeners.add   (listener);}
+       public void removeSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
+               {simulTimeToRealTimeFactorChangedListeners.remove(listener);}
+       private void  callSimulTimeToRealTimeFactorChangedListeners(double f)
+               {simulTimeToRealTimeFactorChangedListeners.forEach(l -> l.accept(f));}
+       //@formatter:on
+
        public boolean isPaused()
        {
                return paused;
index 77a0935..c106121 100644 (file)
@@ -41,13 +41,12 @@ public class LogicExecuter
                        {
                                while (shouldBeRunningLive.get())
                                {
-                                       // always execute to keep timeline from "hanging behind" for too long
                                        long current = tf.getAsLong();
                                        timeline.executeUntil(timeline.laterThan(current), System.currentTimeMillis() + 10);
                                        long nextEventTime = timeline.nextEventTime();
                                        long sleepTime;
                                        if (timeline.hasNext())
-                                               sleepTime = tf.simulTimeDeltaToRealTimeMillis(nextEventTime - current);
+                                               sleepTime = (long) ((nextEventTime - current) * tf.getSimulTimeToRealTimeFactor());
                                        else
                                                sleepTime = 10000;
                                        try
@@ -82,6 +81,8 @@ public class LogicExecuter
                                if (Timeline.timeCmp(event.getTiming(), nextExecSimulTime.get()) < 0)
                                        simulationThread.interrupt();
                });
+               // not optimal; but we don't expect this to happen very often
+               tf.addSimulTimeToRealTimeFactorChangedListener(d -> simulationThread.interrupt());
        }
 
        public void executeNextStep()