/** * **************************************************************************** * Copyright (c) 2010-2016 by Min Cai (min.cai.china@gmail.com). * <p> * This file is part of the PickaPack library. * <p> * PickaPack is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * <p> * PickaPack is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * <p> * You should have received a copy of the GNU General Public License * along with PickaPack. If not, see <http://www.gnu.org/licenses/>. * **************************************************************************** */ package archimulator.util.event; import java.util.ArrayList; import java.util.List; import java.util.concurrent.PriorityBlockingQueue; /** * Cycle accurate event queue. * * @author Min Cai */ public class CycleAccurateEventQueue { private long currentCycle; private PriorityBlockingQueue<CycleAccurateEvent> events; private List<Runnable> perCycleEvents; /** * Create a cycle accurate event queue. */ public CycleAccurateEventQueue() { this.events = new PriorityBlockingQueue<>(); this.perCycleEvents = new ArrayList<>(); } /** * Advance for one cycle. */ public void advanceOneCycle() { while (!this.events.isEmpty()) { CycleAccurateEvent event = this.events.peek(); if (event.getWhen() > this.currentCycle) { break; } event.getAction().run(); this.events.remove(event); } this.perCycleEvents.forEach(Runnable::run); this.currentCycle++; } /** * Schedule the specified action to be performed after the specified delay in cycles. * * @param sender the event sender * @param action the action that is to be performed when the specified event takes place * @param delay the delay in cycles after which the the specified event takes place * @return the newly created cycle accurate event */ public CycleAccurateEventQueue schedule(Object sender, Runnable action, int delay) { this.schedule(new CycleAccurateEvent(this, sender, action, this.currentCycle + delay)); return this; } /** * Schedule the specified cycle accurate event. * * @param event the cycle accurate event that is to be scheduled */ private void schedule(CycleAccurateEvent event) { event.setScheduledTime(this.getCurrentCycle()); this.events.add(event); } /** * Reset the current cycle to 0. */ public void resetCurrentCycle() { for (CycleAccurateEvent event : this.events) { event.setWhen(event.getWhen() - this.currentCycle); } this.currentCycle = 0; } /** * Get the current cycle. * * @return the current cycle */ public long getCurrentCycle() { return this.currentCycle; } /** * Get the list of actions that is to be performed at each cycle. * * @return the list of actions that is to be performed at each cycle */ public List<Runnable> getPerCycleEvents() { return perCycleEvents; } @Override public String toString() { return String.format("CycleAccurateEventQueue{currentCycle=%d, events=%s}", currentCycle, events); } /** * Current maximum ID of the cycle accurate event. */ public long currentId = 0; }