/** * **************************************************************************** * 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; import java.util.BitSet; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; /** * Round robin scheduler. * * @author Min Cai * @param <ResourceT> the type of the resource */ public class RoundRobinScheduler<ResourceT> { private final List<ResourceT> resources; private final Predicate<ResourceT> predicate; private final Function<ResourceT, Boolean> consumeAction; private final int quant; private int resourceId; private BitSet stalled; /** * Create a round robin scheduler. * * @param resources the list of resources * @param predicate the predicate * @param consumeAction the consume action * @param quant the quant */ public RoundRobinScheduler(List<ResourceT> resources, Predicate<ResourceT> predicate, Function<ResourceT, Boolean> consumeAction, int quant) { this.resources = resources; this.predicate = predicate; this.consumeAction = consumeAction; this.quant = quant; this.resourceId = 0; this.stalled = new BitSet(this.resources.size()); } /** * Consume next. */ public void consumeNext() { this.resourceId = consumeNext(this.resourceId); } private int findNext(BitSet except) { for (int i = 0; i < this.resources.size(); i++) { if (this.predicate.test(this.resources.get(i)) && !except.get(i)) { return i; } } return -1; } private int consumeNext(int resourceId) { this.stalled.clear(); resourceId = (resourceId + 1) % this.resources.size(); for (int numConsumed = 0; numConsumed < this.quant; numConsumed++) { if (this.stalled.get(resourceId) || !this.predicate.test(this.resources.get(resourceId))) { resourceId = findNext(this.stalled); } if (resourceId == -1) { break; } if (!this.consumeAction.apply(this.resources.get(resourceId))) { this.stalled.set(resourceId); } } return resourceId; } }