/* CachedNodeFunction.java * * Copyright (c) 2003, Tuomas J. Lukka * This file is part of Fenfire. * * Fenfire is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Fenfire is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with Fenfire; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * */ /* * Written by Tuomas J. Lukka */ package org.fenfire.functional; import java.util.*; import org.nongnu.libvob.util.CachingMap; import org.fenfire.*; import org.fenfire.swamp.*; import org.fenfire.util.*; /** A function which caches its values. * This is a less restricted class than CachedPureNodeFunction, * allowing impure node functions and flushing. *

* This class is, of course, far more dangerous and may introduce * subtle caching bugs - using it is slightly deprecated, * PureNodeFunctions * and CachedPureNodeFunction should be used whenever possible. *

*/ public class CachedNodeFunction implements NodeFunction { NodeFunction f; ConstGraph ourGraph; CachingMap cache; /** Constructor for default set. */ public CachedNodeFunction(int n, ConstGraph graph, NodeFunction f) { this(n,graph,f, DEFAULT); } /** Constructor for different sets. * @param set The set to be flushed when flushing. */ public CachedNodeFunction(int n, ConstGraph graph, NodeFunction f, Object set) { cache = new CachingMap(n); this.ourGraph = graph; this.f = f; this.n = n; this.add(set, this); } public Object f(ConstGraph g, Object node) { Obs o = null; if(g != ourGraph) { o = g.getObserver(); g = g.getOriginalConstGraph(); if(g != ourGraph) throw new IllegalArgumentException("Called with wrong graph"); } FunctionCacheEntry cac = (FunctionCacheEntry)cache.get(node); if(cac == null) { cac = new FunctionCacheEntry(node); cache.put(node, cac); } if(cac.value == cac.DIRTY) { ConstGraph og = (ourGraph == null ? null : ourGraph.getObservedConstGraph(cac)); cac.value = f.f(og, node); if(og != null) og.close(); } if(o != null) cac.addObs(o); return cac.value; } static private HashMap funcsMap = new HashMap(); static private void add(Object set, Object func) { if (funcsMap.get(set) == null) funcsMap.put(set, new ArrayList()); List l = (List)funcsMap.get(set); l.add(func); } /** Flush all information related to node. * This function is needed because we cache impure functions. */ public void flush(Object node) { FunctionCacheEntry entry = (FunctionCacheEntry)cache.get(node); if(entry == null) return; entry.value = entry.DIRTY; } /** Flush all different sets. */ static public void flushAllSets() { for (Iterator it = funcsMap.keySet().iterator(); it.hasNext(); ) { Object set = it.next(); flushSet(set); } } /** Flush the default set. */ static public void flushDefaultSet() { flushSet(DEFAULT); } /** Flush the set which is given. * Throws an error if set doesn't exist. */ static public void flushSet(Object set) { if (funcsMap.get(set) == null) throw new Error("No flush set found: '"+set+"'"); List l = (List)funcsMap.get(set); for (int i=0; i