/* * Copyright: Almende B.V. (2014), Rotterdam, The Netherlands * License: The Apache Software License, Version 2.0 */ package com.almende.eve.algorithms.simulation; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.joda.time.DateTime; import com.almende.eve.scheduling.clock.ClockEntry; import com.almende.eve.scheduling.clock.RunnableClock; /** * The Class SimulationClock. */ public class SimulationClock extends RunnableClock { private DateTime now = null; private Set<String> activeTriggers = new HashSet<String>(); private boolean paused = false; /** * Instantiates a new simulation clock. * * @param initMillis * the init millis */ public SimulationClock(final long initMillis) { super(); this.now = new DateTime(initMillis); } @Override public DateTime nowDateTime() { return this.now; } @Override public long now() { return this.now.getMillis(); } @Override public void start() { paused = false; startNextTriggers(); } @Override public void stop() { paused = true; } @Override public void done(final String triggerId) { if (triggerId != null) { synchronized (activeTriggers) { activeTriggers.remove(triggerId); } startNextTriggers(); } } @Override public void run() { final List<Runnable> toRun = new ArrayList<Runnable>(); synchronized (TIMELINE) { while (!TIMELINE.isEmpty() && !paused) { final ClockEntry ce = TIMELINE.firstEntry().getValue(); if (ce.getDue().isEqual(now) || ce.getDue().isBefore(now)) { TIMELINE.remove(ce); toRun.add(ce.getCallback()); synchronized (activeTriggers) { activeTriggers.add(ce.getTriggerId()); } continue; } else { break; } } } if (!toRun.isEmpty()) { for (Runnable run : toRun) { RUNNER.execute(run); } } } private void startNextTriggers() { run(); synchronized (TIMELINE) { if (!TIMELINE.isEmpty() && !paused) { synchronized (activeTriggers) { if (activeTriggers.isEmpty()) { final ClockEntry ce = TIMELINE.firstEntry().getValue(); now = ce.getDue(); run(); } } } } } }