import java.util.HashMap;
import java.lang.ref.*;
/**
* Ein einfacher Cache basierend
auf SoftReferences. Es obliegt der vollen
* Kontrolle des Garbage Collectors
wann welche Einträge aus dem Cache
* entfernt werden.
* @author Sven Buergel
* @version 0.1
*/
public class Cache {
/**
*
CacheReferences halten als Referent das zu speichernde Objekt.
*
Zusätzlich zum Referent wird noch ein Schlüsselobjekt gespeichert,
*
um später verwaiste Einträge aus dem Cache zu entfernen.
*/
protected class CacheReference
extends SoftReference {
/**
* der zusätzliche Schlüssel
*/
private Object key;
/**
* Erzeugt eine neue CacheReference
* @param key der Schlüssel des
Eintrages
* @param value das zu cachende Objekt
* @param q eine ReferenceQueue
*/
public CacheReference(Object key, Object value, ReferenceQueue q) {
super(value,q);
this.key=key;
}
/**
* Liefert den Schlüssel des Eintrages.
*/
public Object getKey() {
return key;
}
public boolean equals(Object o) {
return (o!=null) &&
(o instanceof CacheReference) &&
(key.equals(((CacheReference)o).getKey()));
}
public int hashCode() {
return key.hashCode();
}
}
/**
*
der eigentliche Speicher
*/
private HashMap hash;
/**
*
ReferenceQueue zum Auffangen von freigegebenen CacheReferences
*/
private ReferenceQueue
queue;
/**
*
Erzeugt einen neuen Cache. Die Cachegröße variiert und kann
*
maximal den gesamten Heap einnehmen.
*/
public Cache() {
hash=new HashMap();
queue=new ReferenceQueue();
}
/**
*
Fügt hinzu oder ersetzt einen Cacheeintrag.
*
@param key der Key des Eintrages
*
@param value der Wert des Eintrages
*
@return ein evtl. schon vorhandener Wert unter diesem Key
*/
public Object put(Object
key, Object value) {
processQueue();
Object tmp=null;
if ((key!=null) && (value!=null)) {
tmp=hash.put(key,new CacheReference(key,value,queue));
}
return tmp;
}
/**
*
Liefert den zugehörigen Cacheeintrag oder <code>null</code>,
falls
*
kein passender Eintrag mehr existiert.
*
@param key der Schlüssel des Eintrages
*
@return den Wert des Eintrages
*/
public Object get(Object
key) {
Reference ref=(Reference)hash.get(key);
return (ref==null) ? null : ref.get();
}
/**
*
Pollt die ReferenceQueue nach freigegebenen CacheReferences.
*
Sobald ein Cacheobjekt vom Garbage Collector gelöscht wurde,
*
wird auch der verwaiste Cacheeintrag entfernt.
*/
protected void processQueue()
{
CacheReference ref;
while ((ref=(CacheReference)queue.poll())!=null) {
hash.remove(ref.getKey());
}
}
} |