/**
* ****************************************************************************
* 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;
}