1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.cache.decorators;
17
18 import java.lang.ref.ReferenceQueue;
19 import java.lang.ref.SoftReference;
20 import java.util.Deque;
21 import java.util.LinkedList;
22 import java.util.concurrent.locks.ReadWriteLock;
23
24 import org.apache.ibatis.cache.Cache;
25
26
27
28
29
30
31
32 public class SoftCache implements Cache {
33 private final Deque<Object> hardLinksToAvoidGarbageCollection;
34 private final ReferenceQueue<Object> queueOfGarbageCollectedEntries;
35 private final Cache delegate;
36 private int numberOfHardLinks;
37
38 public SoftCache(Cache delegate) {
39 this.delegate = delegate;
40 this.numberOfHardLinks = 256;
41 this.hardLinksToAvoidGarbageCollection = new LinkedList<Object>();
42 this.queueOfGarbageCollectedEntries = new ReferenceQueue<Object>();
43 }
44
45 @Override
46 public String getId() {
47 return delegate.getId();
48 }
49
50 @Override
51 public int getSize() {
52 removeGarbageCollectedItems();
53 return delegate.getSize();
54 }
55
56
57 public void setSize(int size) {
58 this.numberOfHardLinks = size;
59 }
60
61 @Override
62 public void putObject(Object key, Object value) {
63 removeGarbageCollectedItems();
64 delegate.putObject(key, new SoftEntry(key, value, queueOfGarbageCollectedEntries));
65 }
66
67 @Override
68 public Object getObject(Object key) {
69 Object result = null;
70 @SuppressWarnings("unchecked")
71 SoftReference<Object> softReference = (SoftReference<Object>) delegate.getObject(key);
72 if (softReference != null) {
73 result = softReference.get();
74 if (result == null) {
75 delegate.removeObject(key);
76 } else {
77
78 synchronized (hardLinksToAvoidGarbageCollection) {
79 hardLinksToAvoidGarbageCollection.addFirst(result);
80 if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) {
81 hardLinksToAvoidGarbageCollection.removeLast();
82 }
83 }
84 }
85 }
86 return result;
87 }
88
89 @Override
90 public Object removeObject(Object key) {
91 removeGarbageCollectedItems();
92 return delegate.removeObject(key);
93 }
94
95 @Override
96 public void clear() {
97 synchronized (hardLinksToAvoidGarbageCollection) {
98 hardLinksToAvoidGarbageCollection.clear();
99 }
100 removeGarbageCollectedItems();
101 delegate.clear();
102 }
103
104 @Override
105 public ReadWriteLock getReadWriteLock() {
106 return null;
107 }
108
109 private void removeGarbageCollectedItems() {
110 SoftEntry sv;
111 while ((sv = (SoftEntry) queueOfGarbageCollectedEntries.poll()) != null) {
112 delegate.removeObject(sv.key);
113 }
114 }
115
116 private static class SoftEntry extends SoftReference<Object> {
117 private final Object key;
118
119 SoftEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) {
120 super(value, garbageCollectionQueue);
121 this.key = key;
122 }
123 }
124
125 }