import java.util.PriorityQueue;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
-import java.util.function.LongSupplier;
/**
* Orders Events by the time they are due to be executed. Can execute Events individually.
public class Timeline
{
private PriorityQueue<InnerEvent> events;
- private LongSupplier time;
- private long lastTimeUpdated = 0;
+ private TimeFunction time;
+ private long processedUntil = 0;
private long eventCounter = 0;
private final List<Consumer<TimelineEvent>> eventAddedListener;
- public final LongSupplier stepByStepExec = () -> lastTimeUpdated;
- public final LongSupplier realTimeExec = () -> System.currentTimeMillis();
+ public final TimeFunction stepByStepExec = new TimeFunction()
+ {
+
+ @Override
+ public void setTime(long time)
+ {
+ processedUntil = time;
+ }
+
+ @Override
+ public long getTime()
+ {
+ return processedUntil;
+ }
+ };
+ public final TimeFunction realTimeExec = new TimeFunction()
+ {
+ private long offset = 0;
+
+ @Override
+ public void setTime(long time)
+ {
+ offset = time;
+ }
+
+ @Override
+ public long getTime()
+ {
+ return System.currentTimeMillis() - offset;
+ }
+ };
+ private boolean isWorking;
/**
* Constructs a Timeline object. Per default the time function is set to step by step execution.
{
if (events.isEmpty())
{
- lastTimeUpdated = getSimulationTime();
+ processedUntil = getSimulationTime();
return ExecutionResult.NOTHING_DONE;
}
+ working();
int checkStop = 0;
while (hasNext() && !condition.getAsBoolean())
{
{
event = events.remove();
}
- lastTimeUpdated = event.getTiming();
+ processedUntil = event.getTiming();
event.run();
// Don't check after every run
checkStop = (checkStop + 1) % 10;
if (checkStop == 0 && System.currentTimeMillis() >= stopMillis)
+ {
+ notWorking();
return ExecutionResult.EXEC_OUT_OF_TIME;
+ }
}
- lastTimeUpdated = getSimulationTime();
+ notWorking();
+ processedUntil = getSimulationTime();
return hasNext() ? ExecutionResult.EXEC_UNTIL_EMPTY : ExecutionResult.EXEC_UNTIL_CONDITION;
}
*
* @param time The return value of calling this function is the current simulation time.
*/
- public void setTimeFunction(LongSupplier time)
+ public void setTimeFunction(TimeFunction time)
{
+ time.setTime(this.time.getTime());
this.time = time;
}
*/
public long getSimulationTime()
{
- return time.getAsLong();
+ return isWorking() ? processedUntil : time.getTime();
}
/**
{
events.clear();
}
- lastTimeUpdated = 0;
+ processedUntil = time.getTime();
}
/**
eventAddedListener.forEach(l -> l.accept(event));
}
+ //@formatter:off
+ private void working() { isWorking = true; }
+ private void notWorking() { isWorking = false; }
+ private boolean isWorking() { return isWorking; }
+ //@formatter:on
+
private class InnerEvent implements Runnable, Comparable<InnerEvent>
{
private final TimelineEventHandler function;
{
eventsString = events.toString();
}
- return String.format("Simulation time: %s, Last update: %d, Events: %s", getSimulationTime(), lastTimeUpdated, eventsString);
+ return String.format("Simulation time: %s, Last update: %d, Events: %s", getSimulationTime(), processedUntil, eventsString);
}
- public enum ExecutionResult
+ public static enum ExecutionResult
{
NOTHING_DONE, EXEC_UNTIL_EMPTY, EXEC_UNTIL_CONDITION, EXEC_OUT_OF_TIME
}
+
+ public static interface TimeFunction
+ {
+ long getTime();
+
+ void setTime(long time);
+ }
+
+ /**
+ * Sets the time of the {@link TimeFunction} to the timestamp of the latest processed event
+ */
+ public void synchTime()
+ {
+ time.setTime(processedUntil);
+ }
}
\ No newline at end of file