static class TimedCache { long timeout; A value; O function; long set; Lock lock = lock(); // stats int stores, fails, hits; *(O function, double timeoutSeconds) { this(timeoutSeconds); this.function = function; } // 0 = no timeout *(double timeoutSeconds) { timeout = toMS(timeoutSeconds); } A set(A a) { lock lock; ++stores; value = a; set = now(); ret a; } bool has() { lock lock; clean(); if (set != 0) { ++hits; true; } ++fails; false; } A get() { lock lock; if (function != null) ret get(function); clean(); if (set != 0) ++hits; else ++fails; ret value; } A get(O makerFunction) { lock lock; if (this.has()) ret getNoClean(); A a = cast callF(makerFunction); ret set(a); } A getNoClean() { lock lock; // lock to wait for potentially running calculation ret value; } // clear if timed out void clean() { lock lock; if (timeout > 0 && now() > set+timeout) clear(); } // clear now void clear() { lock lock; set = 0; value = null; } S stats() { ret "Stores: " + stores + ", hits: " + hits + ", fails: " + fails; } }