package xsched.analysis.core;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
//the abstract schedule of a task
public final class TaskSchedule<TV, SM extends TaskScheduleManager<TV>> {
public enum Relation {
singleton,
happensBefore,
happensAfter,
ordered,
unordered;
public Relation inverse() {
switch(this) {
case singleton: return singleton;
case happensBefore: return happensAfter;
case happensAfter: return happensBefore;
case ordered: return ordered;
case unordered: return unordered;
default: assert false; return null;
}
}
}
//an ordering of all nodes; a "task variable" is the integer index of this array. the first n entries are all parameters coming into this task, the others
//are local schedule sites
private final ArrayList<TV> nodes;
//the last parameter task variable is numTaskParameters - 1
private final int numFormalTaskParameters;
private final Relation[][] relations;
//the 'user data' that can be piggy backed to store additional information from a TV object to other data structures, such as the SSA instructions of where a task comes from etc
//it also has some callbacks for the task schedule to get some information about parameters and such
private final SM scheduleManager;
public TaskSchedule(SM scheduleManager) {
this.scheduleManager = scheduleManager;
nodes = new ArrayList<TV>(scheduleManager.formalTaskParameterNodes());
numFormalTaskParameters = nodes.size();
nodes.addAll(scheduleManager.scheduleSiteNodes());
relations = new Relation[nodes.size()][nodes.size()];
scheduleManager.initializeFullSchedule(this);
assert matrixIsFull();
}
private boolean matrixIsFull() {
for(int i = 0; i < relations.length; i++) {
for(int j = 0; j < relations.length; j++) {
if(relations[i][j] == null)
return false;
}
}
return true;
}
public int numberOfAllTaskVariables() {
return nodes.size();
}
public int numberOfFormalParameterTaskVariables() {
return numFormalTaskParameters;
}
public int numberOfNonParameterTaskVariables() {
return numberOfAllTaskVariables() - numberOfFormalParameterTaskVariables();
}
public boolean isFormalParameterTaskVariable(int var) {
return var < numFormalTaskParameters;
}
public int taskVariableForNode(TV node) {
return nodes.indexOf(node);
}
public TV nodeForTaskVariable(int taskVariable) {
return nodes.get(taskVariable);
}
public Iterator<Integer> iterateNonParameterTaskVariables() {
final int len = nodes.size();
return new Iterator<Integer>() {
private int nextIndex = numFormalTaskParameters;
@Override
public boolean hasNext() {
return nextIndex < len;
}
@Override
public Integer next() {
int res = nextIndex++;
return res;
}
@Override
public void remove() {
throw new ConcurrentModificationException();
}
};
}
public Iterator<Integer> iterateFormalParameterTaskVariables() {
return new Iterator<Integer>() {
private int nextIndex = 0;
@Override
public boolean hasNext() {
return nextIndex < numFormalTaskParameters;
}
@Override
public Integer next() {
int res = nextIndex++;
return res;
}
@Override
public void remove() {
throw new ConcurrentModificationException();
}
};
}
public Iterator<Integer> iterateAllTaskVariables() {
final int len = nodes.size();
return new Iterator<Integer>() {
private int nextIndex = 0;
@Override
public boolean hasNext() {
return nextIndex < len;
}
@Override
public Integer next() {
int res = nextIndex++;
return res;
}
@Override
public void remove() {
throw new ConcurrentModificationException();
}
};
}
public int[] actualsForTaskVariable(int taskVariable) {
assert ! isFormalParameterTaskVariable(taskVariable);
List<TV> params = scheduleManager.actualParametersForNode(nodeForTaskVariable(taskVariable));
int[] result = new int[params.size()];
for(int i = 0; i < result.length; i++) {
result[i] = taskVariableForNode(params.get(i));
}
return result;
}
//only use this in the task schedule manager initializeTaskSchedule() method!
public void addRelationForTaskVariables(int lhsIndex, Relation rel, int rhsIndex) {
assert relations[lhsIndex][rhsIndex] == null;
relations[lhsIndex][rhsIndex] = rel;
if(lhsIndex == rhsIndex)
return;
assert relations[rhsIndex][lhsIndex] == null;
relations[rhsIndex][lhsIndex] = rel.inverse();
}
public void addRelationForNodes(TV lhs, Relation rel, TV rhs) {
int lhsIndex = taskVariableForNode(lhs);
int rhsIndex = taskVariableForNode(rhs);
addRelationForTaskVariables(lhsIndex, rel, rhsIndex);
}
public SM taskScheduleManager() {
return scheduleManager;
}
public Relation relationForNodes(TV lhs, TV rhs) {
int lhsIndex = taskVariableForNode(lhs);
int rhsIndex = taskVariableForNode(rhs);
return relations[lhsIndex][rhsIndex];
}
public Relation relationForTaskVariables(int lhs, int rhs) {
return relations[lhs][rhs];
}
public void print(PrintStream out) {
for(int i = 0; i < relations.length; i++) {
for(int j = 0; j < relations.length; j++) {
out.println(i + " " + relations[i][j] + " " + j);
}
}
}
}