package com.framsticks.test; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import com.framsticks.experiment.Experiment; import com.framsticks.experiment.WorkPackageLogic; import com.framsticks.params.EventListener; import com.framsticks.params.EventListeners; import com.framsticks.params.annotations.FramsClassAnnotation; import com.framsticks.params.annotations.ParamAnnotation; import com.framsticks.params.types.ProcedureParam; import com.framsticks.structure.messages.ValueChange; import com.framsticks.test.prime.ExpParams; import com.framsticks.test.prime.PrimePackage; import com.framsticks.util.FramsticksException; import com.framsticks.util.dispatching.FutureHandler; @FramsClassAnnotation public class PrimeExperiment extends Experiment { private static final Logger log = LogManager.getLogger(PrimeExperiment.class); @ParamAnnotation public final WorkPackageLogic workPackageLogic; final PrimePackage task = new PrimePackage(); protected int step = 500; protected int nextWaitNumber = 1; protected List waitingPackages = new LinkedList<>(); // protected List primes = new LinkedList<>(); protected final EventListeners primesListeners = new EventListeners<>(); /** * */ public PrimeExperiment() { setExpdef("prime"); // task.params.from_number = 1; task.params.to_number = 10000; task.state.current_number = 1; workPackageLogic = new WorkPackageLogic(this, PrimePackage.class) { @Override protected void generateNextPackage(FutureHandler future) { assert isActive(); if (task.state.current_number > task.params.to_number) { log.debug("no more packages in range left"); future.pass(null); return; } PrimePackage wp = PrimePackage.compose(task.state.current_number, Math.min(task.params.to_number, task.state.current_number + step - 1)); task.state.current_number += step; log.debug("generated package: {}", wp.getShortDescription()); future.pass(wp); } @Override protected void returnPackage(PrimePackage result) { log.debug("returned package: {}", result); if (tryAddResult(result)) { while (tryMergeWaitingPackages()) { } } else if (result.params.from_number > nextWaitNumber) { waitingPackages.add(result); } try { isComplete(); } catch (FramsticksException e) { log.debug("experiment is not done yet: {}", e.getShortMessage(new StringBuilder())); return; } log.info("experiment is done, {} primes found", getPrimes().size()); log.debug("primes: {}", getPrimes()); interruptJoinable(); } }; } public List getPrimes() { return task.state.getResultList(); } protected boolean tryAddResult(PrimePackage result) { if (result.params.from_number > nextWaitNumber) { return false; } if (result.params.from_number < nextWaitNumber) { throw new FramsticksException().msg("duplicate result").arg("result", result); } getPrimes().addAll(result.state.getResultList()); nextWaitNumber = result.params.to_number + 1; primesListeners.actionForAll(new ValueChange(getDescription())); return true; } protected boolean tryMergeWaitingPackages() { Iterator i = waitingPackages.iterator(); while (i.hasNext()) { if (tryAddResult(i.next())) { i.remove(); return true; } } return false; } protected void isComplete() { if (nextWaitNumber - 1 != task.params.to_number) { throw new FramsticksException().msg("not ready yet").arg("done to", nextWaitNumber - 1); } } /** * @return the maxNumber */ @ParamAnnotation public int getMaxNumber() { return task.params.to_number; } /** * @param maxNumber the maxNumber to set */ @ParamAnnotation public void setMaxNumber(int maxNumber) { task.params.to_number = maxNumber; } @ParamAnnotation public String getDescription() { return getPrimes().size() + " found in range " + new ExpParams(task.params.from_number, nextWaitNumber - 1); } @ParamAnnotation(id = "description_changed") public void addPrimesListener(EventListener listener) { primesListeners.add(listener); } @ParamAnnotation(id = "description_changed") public void removePrimesListener(EventListener listener) { primesListeners.remove(listener); } @ParamAnnotation(paramType = ProcedureParam.class) public PrimePackage experimentNetsave() { return task; } }