package deadlock.analyser.detection;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Set;
import java.util.TreeSet;
import deadlock.analyser.factory.GroupName;
public class Lam {
//The collection of states for a Lam
LinkedList<State> states;
// Constructor
public Lam(){
this.states = new LinkedList<State>();
}
// Constructor copy
public Lam(Lam l){
this.states = new LinkedList<State>(l.getStates());
}
// Constructor copy2
public Lam(LinkedList<State> s){
this.states = s;
}
// getter and setter for the states
public LinkedList<State> getStates(){
return this.states;
}
public void setStates(LinkedList<State> s){
this.states = s;
}
//add state to lamp
public void addState(State s){
for(State sthis : this.states){
if(sthis.containState(s))
return;
}
this.states.add(s);
}
//TODO ABEL: check correctness
//minimize a lamp
public Lam minimize(){
Lam l = new Lam();
for(int i = 0; i< this.states.size(); i++){
boolean contained = false;
for(int j = 0; j < l.states.size(); j++){
if(i==j) continue;
if(l.states.get(j).containState(this.states.get(i))) contained = true;
}
if(!contained)
l.addState(this.states.get(i));
}
return l;
}
// add couple of dependencies (get) on a Lamp, it means to add that couple to all the states in the lamp
public void addCouple(GroupName a, GroupName b){
if(states.isEmpty()){
states.add(new State());
}
for(State s : states){
s.addCouple(a, b);
}
}
// add couple of dependencies (await) on a Lamp, it means to add that couple to all the states in the lamp
public void addCoupleAwait(GroupName a, GroupName b){
if(states.isEmpty()){
states.add(new State());
}
for(State s : states){
s.addCoupleAwait(a, b);
}
}
// add a Lamp l to this lam, this is the + lam operator
public void addLamp(Lam l){
//check all l states and add those that are not present in the current states
for(State s : l.states){
Boolean contained = false;
for(State s1 : this.states){
//if any current state contains s there is no need to continue searching
if(contained = s1.containState(s))
break;
}
//if s is not contained then add the state
if(!contained){
State sNew = new State();
sNew.addState(s);
sNew.setDebugInfo(s.getDebugInfo());
this.states.add(sNew);
}
}
}
//TODO ABEL: Check correctness
// parallel between this Lam and Lam l, this is the || lam operator
public void parallel(Lam l){
// if Lamp l is empty, the result of parallel is this
if(l.states.isEmpty()) return;
// if Lamp this is empty, the result of parallel is l
if(this.states.isEmpty()){
this.addLamp(l);
return;
}
//now we can work assuming that both l and this have at least one state
//we need to calculate the cartesian product
LinkedList<State> cartesianState = new LinkedList<State>();
for(State s1 : this.states){
for(State s2 : l.states){
State s3 = new State();
s3.addState(s1);
s3.addState(s2);
cartesianState.add(s3);
}
}
this.states = cartesianState;
}
//TODO ABEL: Check correctness
// get the FreeVariable of a Lamp
public Set<GroupName> fv(){
Set<GroupName> fv = new TreeSet<GroupName>();
for(State s : states){
fv.addAll(s.fv());
}
return fv;
}
// realize the name substitution defined in s
public void apply(VarSubstitution s){
for(State st : states){
st.apply(s);
}
}
// calculates the current number of dependencies, used in the fix point iteration to determine
// if there are new changes
public Integer numberOfDep(){
Integer i = 0;
for(State st : states)
i+=st.numberOfDep();
return i;
}
//check for Cycle that might be composed by any kind of dependencies
//if there is a cycle and there is at least one get dependency then this is a deadlock
//otherwise this is a livelock and the result will be the same of hasAwaitCycle
public Boolean hasCycle(){
//it has cycle if there is any cyclic state
for(State st : states)
if(st.hasCycle())
return true;
return false;
}
//check for a pure get dependencies cycle
public Boolean hasCycleGet(){
//it has cycle if there is any cyclic state
for(State st : states)
if(st.hasCycleGet())
return true;
return false;
}
//check just for Await Cycle, this check for what is called livelock
public Boolean hasCycleAwait(){
//it has cycle if there is any cyclic state
for(State st : states)
if(st.hasCycleAwait())
return true;
return false;
}
public String toString(){
String res = "";
for(State s : states){
res += s.toString() + "\n";
}
return res;
}
//According to version2 of the fix point algorithm this method adds the missing dependencies from the transitive closure
//of the dependencies of not new names and removes all dependencies with new names
public void expandAndClean() {
for(State s: states)
s.expandAndClean();
}
public boolean hasReflexiveState() {
// TODO Auto-generated method stub
for(State s: states)
if(s.hasReflexiveState())
return true;
return false;
}
public void updateStackTrace(String method) {
for(State s: states) {
LinkedList<String> callStack = s.getDebugInfo().callStack;
if(!callStack.contains(method))
callStack.add(method);
}
}
public LinkedList<State> getReflexiveStates() {
LinkedList<State> res = new LinkedList<>();
for(State s: states)
if(s.hasReflexiveState())
res.add(s);
return res;
}
}