summaryrefslogtreecommitdiff
path: root/source/com/c2kernel/utils/SoftCache.java
diff options
context:
space:
mode:
Diffstat (limited to 'source/com/c2kernel/utils/SoftCache.java')
-rwxr-xr-xsource/com/c2kernel/utils/SoftCache.java100
1 files changed, 100 insertions, 0 deletions
diff --git a/source/com/c2kernel/utils/SoftCache.java b/source/com/c2kernel/utils/SoftCache.java
new file mode 100755
index 0000000..ce2b390
--- /dev/null
+++ b/source/com/c2kernel/utils/SoftCache.java
@@ -0,0 +1,100 @@
+package com.c2kernel.utils;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.*;
+
+/*******************************************************************************
+ * SoftReferences are reaped if not strong references are left and the vm is
+ * running out of memory. Most caches in the kernel use this.
+ *
+ * $Revision: 1.5 $ $Date: 2004/10/29 13:29:09 $
+ ******************************************************************************/
+public class SoftCache extends AbstractMap {
+
+ private final Map hash = new HashMap();
+ private final int minSize;
+ private final LinkedList hardCache = new LinkedList();
+ private final ReferenceQueue queue = new ReferenceQueue();
+
+ public SoftCache() {
+ this(0);
+ }
+
+ public SoftCache(int minSize) {
+ this.minSize = minSize;
+ }
+
+ public Object get(Object key) {
+ Object result = null;
+ SoftReference soft_ref = (SoftReference) hash.get(key);
+ if (soft_ref != null) {
+ result = soft_ref.get();
+ if (result == null)
+ hash.remove(key);
+ else
+ if (minSize > 0) { // add to hard cache so it's not reaped for a while
+ hardCache.addFirst(result);
+ if (hardCache.size() > minSize) // trim last one off
+ hardCache.removeLast();
+ }
+ }
+ return result;
+ }
+
+ public Object put(Object key, Object value) {
+ processQueue();
+ if (minSize > 0) {
+ hardCache.addFirst(value);
+ if (hardCache.size() > minSize)
+ hardCache.removeLast();
+ }
+ return hash.put(key, new SoftValue(value, key, queue));
+ }
+
+ public Object remove(Object key) {
+ processQueue();
+ return hash.remove(key);
+ }
+
+ public void clear() {
+ hardCache.clear();
+ while(queue.poll()!=null);
+ hash.clear();
+ }
+
+ public int size() {
+ processQueue();
+ return hash.size();
+ }
+
+ public Set keySet() {
+ processQueue();
+ return hash.keySet();
+ }
+
+ public Set entrySet() {
+ // Would have to create another Map to do this - too expensive
+ // Throwing runtime expensive is dangerous, but better than nulls
+ throw new UnsupportedOperationException();
+ }
+
+ private static class SoftValue extends SoftReference {
+ private final Object key;
+ private SoftValue(Object k, Object key, ReferenceQueue q) {
+ super(k, q);
+ this.key = key;
+ }
+ }
+
+ /**
+ * Look for values that have been reaped, and remove their keys from the cache
+ */
+ private void processQueue() {
+ SoftValue sv;
+ while ((sv = (SoftValue) queue.poll()) != null) {
+ hash.remove(sv.key);
+ }
+ }
+
+}