blob: b545f24c784df965da9f34bcbaf9b6bb146adab1 [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2019 Dortmund University of Applied Sciences and Arts and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dortmund University of Applied Sciences and Arts - initial API and implementation
********************************************************************************
*/
package org.eclipse.app4mc.multicore.execution.logic.systemproxy.scheduler.core;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.eclipse.app4mc.multicore.execution.logic.systemproxy.scheduler.ISchedulerAlgorithm;
import org.eclipse.app4mc.multicore.execution.logic.systemproxy.scheduler.ISchedulerEventListener;
public abstract class AbstractScheduler implements ISchedulerBase {
/** Simulation time. */
protected long simTime = 0;
/** Map of tasks accessible by their names */
private final Map<String, SchedulerTask> tasks = new HashMap<>();
/**
* Listners or observers that gets informed about scheduling information
* like task state changes.
**/
private final List<ISchedulerEventListener> osHookListeners = new LinkedList<>();
/**
* Algorithm to choose high prio task and determine if is cooperative or
* preemptive scheduling.
**/
private final ISchedulerAlgorithm schedulingAlgo;
/** Current task in execution **/
protected SchedulerTask currentTask = null;
public AbstractScheduler(final ISchedulerAlgorithm m) {
this.schedulingAlgo = m;
}
protected void notifyObserver(final Consumer<? super ISchedulerEventListener> action) {
this.osHookListeners.forEach(action);
}
protected Map<String, SchedulerTask> getTasks() {
return this.tasks;
}
protected List<ISchedulerEventListener> getOsHookListeners() {
return this.osHookListeners;
}
/**
* Search for the task with the highest priority, which is in ready state.
* Uses {@link #compare(SchedulerTask, SchedulerTask)} to determine higher/
* lower prio.
*
* @return Task with highest prio or null if no ready task is available.
*/
protected SchedulerTask getReadyPriorityTask() {
SchedulerTask highTask = null;
for (final SchedulerTask t : this.tasks.values()) {
if (t.isReady()) {
if (highTask == null || compare(t, highTask) < 0) {
highTask = t;
}
}
}
return highTask;
}
/**
* Get simulation time.
*/
@Override
public long getSimTime() {
return this.simTime;
}
/**
* Increment simulation time by one.
*/
protected void timeStep() {
this.simTime++;
}
protected boolean isPreemptiveScheduling() {
return this.schedulingAlgo.isPreemptiveScheduling();
}
/**
* Compare two tasks regarding its priority. Therefore the provided
* scheduling algorithm is used. If the algorithm determines the same
* priority the earliest added task wins.
*
* @param t1
* @param t2
* @return
* <ul>
* <li>t1 has highest priority: < 0 (-1)</li>
* <li>t2 has highest priority: > 0 (1)</li>
* <ul>
*/
protected int compare(final SchedulerTask t1, final SchedulerTask t2) {
int tmp = this.schedulingAlgo.compare(t1, t2);
if (tmp == 0) {
// same prio => lowest id wins (earliest added task)
tmp = Integer.compare(t1.getId(), t2.getId());
}
return tmp;
}
@Override
public SchedulerTask getTask(final String name) {
return getTasks().get(name);
}
@Override
public void addTask(final String name, final long wcet, final long period) {
final SchedulerTask t = new SchedulerTask(name, wcet, period);
t.setId(getTasks().size());
getTasks().put(t.getName(), t);
}
@Override
public void addSchedulerEventListener(final ISchedulerEventListener l) {
getOsHookListeners().add(l);
}
}