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 removeCompletedPrograms(List programStates) { return programStates.stream().filter(p -> p.isNotCompleted()).collect(Collectors.toList()); } public void oneStepForAllProgramStates(List programStates) { programStates.forEach(programState -> { try{ repository.logProgramStateExecution(programState); } catch(BaseException e){ System.out.println(e.getMessage()); } }); List> callList = programStates.stream().map((ProgramState p) -> (Callable)(() -> { try{ return p.oneStep(); } catch(BaseException e){ System.out.println(e.getMessage()); } return null; })).filter(c -> c != null).collect(Collectors.toList()); List newProgramStates = new ArrayList(); 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 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 garbageCollector(Set symbolTable, Hashtable 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 getAddressesFromSymbolTable(List> symbolTablesValues, Hashtable 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()); } }