sclass ConcurrentEvaluator { new L functions; L results = synchroList(); ExecutorService executorService; O onNewResult; // Runnable or voidfunc(int) volatile bool cancelled; L threads = synchroList(); int coresToUse; // if 0, use coresToUse() void add(O f) { functions.add(f); } void addAll(Collection l) { functions.addAll(l); } void start() { executorService = Executors.newFixedThreadPool(coresToUse != 0 ? coresToUse : coresToUse()); while (l(results) < l(functions)) results.add(null); for _i over functions: { final int i = _i; executorService.execute(r { threads.add(currentThread()); try { results.set(i, pcallF(functions.get(i))); ping(); onNewResult(i); } finally { threads.remove(currentThread()); } }); } } void onNewResult(int i) { if (!cancelled) pcallF(onNewResult, i); } L results() { ret cloneList(results); } void cancel { pcall { cancelled = true; executorService.shutdownNow(); cancelThreads(cloneList(threads)); } } void cancelAndWait { long time = sysNow(); cancel(); while (nempty(threads)) sleep(1); sysDone("Cancelling evaluators", time, 10); } bool done() { ret empty(threads); } void startWaitCleanUp { try { start(); while (!done()) sleepSeconds(1); } finally { cancel(); } } }