package io.hummer.prefetch.context; import io.hummer.util.log.LogUtil; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicReference; import org.apache.log4j.Logger; /** * Used to handle different notions of time, * e.g., real system time, simulation time, ... * * All times are in seconds with type Double (e.g., 10.25 seconds). * * @author Waldemar Hummer */ public abstract class TimeClock { public static final AtomicReference<TimeClock> instance = new AtomicReference<>((TimeClock)new TimeClockSystem()); public static double now() { return instance.get().getTime(); } public static void setTime(double time) { if(!(instance.get() instanceof TimeClockManual)) { instance.set(new TimeClockManual(time)); } TimeClockManual t = (TimeClockManual)instance.get(); t.setTheTime(time); t.runTasks(); } abstract double getTime(); abstract void scheduleTask(TimerTask task, double delaySecs); public static class TimeClockSystem extends TimeClock { final Timer timer = new Timer(); @Override public double getTime() { return ((double)System.currentTimeMillis()) / 1000.0; } @Override void scheduleTask(TimerTask task, double delaySecs) { timer.schedule(task, (long)(delaySecs * 1000.0)); } } public static class TimeClockManual extends TimeClock { static final Logger LOG = LogUtil.getLogger(); double time; final Map<TimerTask,Double> tasks = new HashMap<TimerTask,Double>(); public TimeClockManual(double time) { this.time = time; } @Override public double getTime() { return time; } public void setTheTime(double time) { this.time = time; } @Override void scheduleTask(TimerTask task, double delaySecs) { LOG.debug("Scheduling task (delay " + delaySecs + ", tasks: " + tasks.size() + "): " + task); tasks.put(task, now() + delaySecs); } private void runTasks() { double now = now(); for(Entry<TimerTask,Double> e : new HashSet<>(tasks.entrySet())) { if(now >= e.getValue()) { tasks.remove(e.getKey()); //GlobalThreadPool.execute(e.getKey()); LOG.debug("Running scheduled task (time: " + e.getValue() + ", now: " + now + "): " + e.getKey()); e.getKey().run(); } } } } /** * Filter by timestamp range. * @param timestamps * @param timeFrom from, inclusive * @param timeTo to, exclusive * @return */ public static <T> List<T> filterTimestampedValues( Map<Double,T> timestamps, double timeFrom, double timeTo) { List<T> result = new LinkedList<T>(); for(double d : timestamps.keySet()) { if(d >= timeFrom && d < timeTo) { result.add(timestamps.get(d)); } } return result; } public static void schedule(TimerTask task, double delaySecs) { instance.get().scheduleTask(task, delaySecs); } }