// (c) Tuomas J. Lukka package org.fenfire.util; import java.util.*; import org.nongnu.libvob.util.CachingMap; import org.nongnu.libvob.util.Background; import org.fenfire.*; import org.fenfire.util.*; /** A super-lazy node function: caches values from another function, * and for uncached values returns a placeholder value and initializes * a background computation. *

* This function only caches pure functions but is not a pure * node function itself as it returns the placeholder value. */ public class SuperLazyPureFunction implements Function { CachingMap cache; PureFunction f; Object placeHolder; Background background; ObjObs recalcObs; /** Create a new SuperLazyPureNodeFunction. * @param n The number of cache entries to use * @param g The constgraph to cache using * @param f The pure node function whose values we are caching * @param placeHolder The value to return when no function value * has been precalculated. * @param background The object to use for the background calculations. * @param recalcObs The observer to call whenever a new value * has been calculated */ public SuperLazyPureFunction(int n, PureFunction f, Object placeHolder, Background background, ObjObs recalcObs ) { cache = new CachingMap(n); this.f = f; this.placeHolder = placeHolder; this.background = background; this.recalcObs = recalcObs; } private class SuperLazyFunctionCacheEntry extends FunctionCacheEntry implements Runnable { public SuperLazyFunctionCacheEntry(Object input) { super(input); } public void schedule() { background.addTask(this, 0); } public void run() { synchronized(this) { this.value = f.f(this.input); } if(recalcObs != null) recalcObs.chg(this.input); } } public Object f(Object node) { SuperLazyFunctionCacheEntry cac = (SuperLazyFunctionCacheEntry)cache.get(node); if(cac == null) { cac = new SuperLazyFunctionCacheEntry(node); cache.put(node, cac); } synchronized(cac) { if(cac.value == cac.DIRTY) { cac.schedule(); return placeHolder; } return cac.value; } } }