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