105 lines
4.2 KiB
Java
105 lines
4.2 KiB
Java
package Controllers;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashSet;
|
|
import java.util.Hashtable;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
|
|
import Exceptions.BaseException;
|
|
import Models.Program.ProgramState;
|
|
import Models.Values.IValue;
|
|
import Models.Values.ReferenceValue;
|
|
import Repositories.IRepository;
|
|
|
|
public class Controller {
|
|
private IRepository repository;
|
|
private boolean displayFlag;
|
|
private ExecutorService executor;
|
|
|
|
public Controller(IRepository repository, boolean displayFlag) {
|
|
this.repository = repository;
|
|
this.displayFlag = displayFlag;
|
|
}
|
|
|
|
public List<ProgramState> removeCompletedPrograms(List<ProgramState> programStates) {
|
|
return programStates.stream().filter(p -> p.isNotCompleted()).collect(Collectors.toList());
|
|
}
|
|
|
|
public void oneStepForAllProgramStates(List<ProgramState> programStates) {
|
|
programStates.forEach(programState -> {
|
|
try{
|
|
repository.logProgramStateExecution(programState);
|
|
}
|
|
catch(BaseException e){
|
|
System.out.println(e.getMessage());
|
|
}
|
|
});
|
|
List<Callable<ProgramState>> callList = programStates.stream().map((ProgramState p) -> (Callable<ProgramState>)(() -> {
|
|
try{
|
|
return p.oneStep();
|
|
}
|
|
catch(BaseException e){
|
|
System.out.println(e.getMessage());
|
|
}
|
|
return null;
|
|
})).filter(c -> c != null).collect(Collectors.toList());
|
|
List<ProgramState> newProgramStates = new ArrayList<ProgramState>();
|
|
try{
|
|
newProgramStates = executor.invokeAll(callList).stream().map(future -> {
|
|
try {
|
|
return future.get();
|
|
} catch (Exception e) {
|
|
System.out.println(e.getMessage());
|
|
}
|
|
return null;
|
|
}).filter(p -> p != null).collect(Collectors.toList());
|
|
}
|
|
catch(InterruptedException e){
|
|
System.out.println(e.getMessage());
|
|
}
|
|
programStates.addAll(newProgramStates);
|
|
programStates.forEach(programState -> {
|
|
try{
|
|
repository.logProgramStateExecution(programState);
|
|
}
|
|
catch(BaseException e){
|
|
System.out.println(e.getMessage());
|
|
}
|
|
});
|
|
repository.setProgramStates(programStates);
|
|
}
|
|
|
|
public void allSteps() {
|
|
executor = Executors.newFixedThreadPool(2);
|
|
List<ProgramState> programStates = removeCompletedPrograms(repository.getProgramStates());
|
|
while(programStates.size() > 0){
|
|
programStates.get(0).getHeap().setContent(this.garbageCollector(this.getAddressesFromSymbolTable(programStates.stream().map(programState -> programState.getSymbolTable().getContent()).collect(Collectors.toList()), programStates.get(0).getHeap().getContent()), programStates.get(0).getHeap().getContent()));
|
|
oneStepForAllProgramStates(programStates);
|
|
programStates = removeCompletedPrograms(repository.getProgramStates());
|
|
}
|
|
executor.shutdownNow();
|
|
repository.setProgramStates(programStates);
|
|
}
|
|
|
|
public Hashtable<Integer, IValue> garbageCollector(Set<Integer> symbolTable, Hashtable<Integer, IValue> heap) {
|
|
return heap.entrySet().stream().filter(e -> symbolTable.contains(e.getKey()))
|
|
.collect(Hashtable::new, (m, e) -> m.put(e.getKey(), e.getValue()), Hashtable::putAll);
|
|
}
|
|
|
|
public Set<Integer> getAddressesFromSymbolTable(List<Collection<IValue>> symbolTablesValues, Hashtable<Integer, IValue> heap) {
|
|
return symbolTablesValues.stream().flatMap(Collection::stream).filter(v -> v instanceof ReferenceValue)
|
|
.flatMap(v -> Stream.iterate(((ReferenceValue) v).getAddress(), Objects::nonNull, addr -> {
|
|
var value = heap.get(addr);
|
|
return value instanceof ReferenceValue ? ((ReferenceValue) value).getAddress() : null;
|
|
})).distinct().collect(Collectors.toSet());
|
|
}
|
|
}
|