/**
* Author: Christoph Hillebold <c.hillebold@student.tugraz.at>
*/
package at.iaik.suraq.util;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.WeakHashMap;
import at.iaik.suraq.sexp.Token;
import at.iaik.suraq.smtlib.formula.AndOrXorFormula;
import at.iaik.suraq.smtlib.formula.DomainTerm;
import at.iaik.suraq.smtlib.formula.DomainVariable;
import at.iaik.suraq.smtlib.formula.EqualityFormula;
import at.iaik.suraq.smtlib.formula.Formula;
import at.iaik.suraq.smtlib.formula.FormulaTerm;
import at.iaik.suraq.smtlib.formula.FunctionMacro;
import at.iaik.suraq.smtlib.formula.ImpliesFormula;
import at.iaik.suraq.smtlib.formula.NotFormula;
import at.iaik.suraq.smtlib.formula.PropositionalConstant;
import at.iaik.suraq.smtlib.formula.PropositionalVariable;
import at.iaik.suraq.smtlib.formula.Term;
import at.iaik.suraq.smtlib.formula.UninterpretedFunction;
public class FormulaCache<T> {
// This static List MUST be on first position in this file!
// Else it would not be initialized before the other static variables
private static ArrayList<FormulaCache<?>> instances = new ArrayList<FormulaCache<?>>();
// do not cache token because token is a sexpression that has recursive
// problems??
public static FormulaCache<Token> token = new FormulaCache<Token>("Token",
true);
public static FormulaCache<NotFormula> notFormula = new FormulaCache<NotFormula>(
"NOT", true);
public static FormulaCache<PropositionalVariable> propVar = new FormulaCache<PropositionalVariable>(
"PropVar", true);
public static FormulaCache<PropositionalConstant> propConst = new FormulaCache<PropositionalConstant>(
"PropConst", true);
public static FormulaCache<DomainVariable> domainVarFormula = new FormulaCache<DomainVariable>(
"DomainVar", true);
public static FormulaCache<ImpliesFormula> impliesFormula = new FormulaCache<ImpliesFormula>(
"implies", true);
public static FormulaCache<AndOrXorFormula> andOrXorFormula = new FormulaCache<AndOrXorFormula>(
"AndOrXor", true);
public static FormulaCache<FormulaTerm> formulaTerm = new FormulaCache<FormulaTerm>(
"FormulaTerm", true);
public static FormulaCache<EqualityFormula> equalityFormula = new FormulaCache<EqualityFormula>(
"EqualityFormula", true);
public static FormulaCache<DomainTerm> domainTerm = new FormulaCache<DomainTerm>(
"DomainTerm:*", true);
public static FormulaCache<Term> term = new FormulaCache<Term>("Term:*",
true);
public static FormulaCache<Formula> formula = new FormulaCache<Formula>(
"Formula:*", true);
public static FormulaCache<UninterpretedFunction> uninterpretedFunction = new FormulaCache<UninterpretedFunction>(
"UF", true);
public static FormulaCache<FunctionMacro> functionMacro = new FormulaCache<FunctionMacro>(
"FunctionMacro", true);
public static boolean _isActive = true;
private boolean _isActiveLocal = true;
// For statistics
private long cachedReads = 0;
private long cachedWrites = 0;
// Sets are not possible, because they don't provide the get() method
// WeakHashMap compares keys with equals(==) instead of .hashCode!!!!
// http://docs.oracle.com/javase/6/docs/api/java/util/WeakHashMap.html
private WeakHashMap<T, WeakReference<T>> cache = new WeakHashMap<T, WeakReference<T>>();
private String name;
private FormulaCache(String name, boolean isActive2) {
this._isActiveLocal = isActive2;
try {
this.name = name;
FormulaCache.instances.add(this);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException("blubb");
}
}
/**
* Clears all caches.
*/
public synchronized static void clearAll() {
for (FormulaCache<?> instance : FormulaCache.instances) {
instance.clear();
}
}
/**
* Clears the cache and resets the statistic.
*/
public synchronized void clear() {
cache.clear();
cachedReads = 0;
}
/**
* This may override an existing object with the same hashCode.
*
* @param object
* @throws ClassCastException
*/
public synchronized void post(T object) throws ClassCastException {
if (!FormulaCache._isActive || !_isActiveLocal)
return;
cache.put(object, new WeakReference<T>(object));
cachedWrites++;
}
/**
* This method returns an Object with the same hashCode if it already
* exists. If not, the given Object is stored in the Map. If you modify the
* given Object later, it will be changed everywhere!!!
*
* @param object
* @return
* @throws ClassCastException
*/
public synchronized T put(T object) throws ClassCastException {
if (!FormulaCache._isActive || !_isActiveLocal)
return object;
if (cache.containsKey(object)) {
WeakReference<T> ref = cache.get(object);
if (ref != null) {
T result = ref.get();
if (result != null) {
if (result != object) {
cachedReads++;
if (cachedReads % 10000000 == 0)
this.printStatisticLine();
}
return result;
}
}
}
cache.put(object, new WeakReference<T>(object));
cachedWrites++;
if (cachedWrites % 100000 == 0)
this.printStatisticLine();
return object;
}
/**
* Gets an already existing instance of the given reference object. If the
* Object does not exist, this method returns null
*
* @param reference
* @return
* @throws ClassCastException
*/
public synchronized T get(T reference) throws ClassCastException {
if (!FormulaCache._isActive || !_isActiveLocal)
return reference;
if (cache.containsKey(reference)) {
T result = cache.get(reference).get();
if (result != reference && result != null)
cachedReads++;
return result;
}
return null;
}
public synchronized long getCachedReads() {
return cachedReads;
}
public synchronized long getCachedWrites() {
return cachedWrites;
}
public synchronized int getCachedElements() {
return cache.size();
}
public synchronized String getName() {
return name;
}
public synchronized void printStatisticLine() {
long reads = getCachedReads();
int elems = getCachedElements();
long writes = getCachedWrites();
String className = getName();
System.err.println("* saved " + reads + " reads on " + elems
+ " elements of max. " + writes + ":" + className);
}
public synchronized static void printStatistic() {
System.out.println("************************************************");
for (FormulaCache<?> instance : FormulaCache.instances) {
long reads = instance.getCachedReads();
int elems = instance.getCachedElements();
long writes = instance.getCachedWrites();
String className = instance.getName();
System.out.println("* saved " + reads + " reads on " + elems
+ " elements of max. " + writes + ":" + className);
}
System.out.println("************************************************");
}
}