sclass ProbabilisticScheduler implements Steppable { TreeSetWithDuplicates entries = new(byProbability()); bool verbose; double cutoffProbabilityOnAdd = .5; double cutoffProbabilityOnExecute = .5; Comparator byProbability() { ret (a, b) -> cmp(b.probability, a.probability); } new ThreadLocal threadProbability; persistable sclass Entry { double probability; Runnable action; *(double *probability, Runnable *action) {} run { action.run(); } toString { ret str(WithProbability(probability, action)); } } void add(double probability, Runnable action) { if (action == null) ret; if (probability < cutoffProbabilityOnAdd) ret; entries.add(new Entry(probability, action)); } public bool step() { ret stepFirstUnstepped(); } Entry nextSteppable() { Entry s = first(entries); if (s != null && s.probability < cutoffProbabilityOnExecute) null; ret s; } // returns false when done stepping bool stepFirstUnstepped() { Entry s = nextSteppable(), ret false if null; entries.remove(s); temp tempSetTL(threadProbability, s.probability); s.run(); true; } void reset { entries.clear(); } run { stepAll(this); } void printStats() { Entry first = entries.first(), last = entries.last(); print("ProbabilisticScheduler. " + nEntries(entries) + ", highest probability in queue: " + (first == null ? "-" : first.probability) + ", lowest probability in queue: " + (last == null ? "-" : last.probability) + ", cutoff probability: " + cutoffProbabilityOnAdd + "/" + cutoffProbabilityOnExecute + ", done: " + yesNoShort(nextSteppable() == null)); } S stats(TreeSetWithDuplicates ts) { ret l(ts) + (empty(ts) ? "" : " (best: " + iround(first(ts).probability) + ")"); } }