blob: ce2b390f7804bd8c69937b3a715e05ad713659dd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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);
}
}
}
|