sclass MultiThreadStepper implements AutoCloseable { Runnable onDone; Lock lock = lock(); L threads = synchroList(); L steppables = synchroList(); L stepping = synchroList(); int cores = coresToUse(); int idleDelay = 10; volatile bool cancelled; new AtomicLong steps; long startTime; volatile long elapsedTime; *() {} *(Steppable... steppables) { addAll(this.steppables, steppables); } *(Collection steppables) { addAll(this.steppables, steppables); } void start { print("Using " + n2(cores, "core")); startTime = sysNow(); repeat cores { thread "Multi Thread Stepper" { final Thread me = currentThread(); threads.add(me); afterwards { bool done; { lock lock; threads.remove(me); done = empty(threads); } if (done) { elapsedTime = sysNow()-startTime; callF(onDone); } } //int i = 0; while licensed { Steppable s; { lock lock; if (done()) ret; //s = get(steppables, mod(i++, l(steppables))); s = random(steppables); if (s != null) { steppables.remove(s); stepping.add(s); } } if (s == null) continue with sleep(idleDelay); bool done = false; try { incAtomicLong(steps); done = !s.step(); } catch e { _handleException(e); done = true; } finally { lock lock; stepping.remove(s); if (!done) steppables.add(s); } } } } } bool done() { ret empty(steppables) || cancelled; } void stop { cancelled = true; cancelThreads(threads); } void cleanMeUp { stop(); } public void close() { stop(); } MultiThreadStepper onDone(Runnable r) { onDone = r; this; } void add(Steppable s) { steppables.add(s); } long steps() { ret steps!; } }