Mercurial Hosting > nabble
comparison src/fschmidt/db/util/CacheMap.java @ 68:00520880ad02
add fschmidt source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 05 Oct 2025 17:24:15 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
67:9d0fefce6985 | 68:00520880ad02 |
---|---|
1 /* | |
2 Copyright (c) 2008 Franklin Schmidt <fschmidt@gmail.com> | |
3 | |
4 Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 of this software and associated documentation files (the "Software"), to deal | |
6 in the Software without restriction, including without limitation the rights | |
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 copies of the Software, and to permit persons to whom the Software is | |
9 furnished to do so, subject to the following conditions: | |
10 | |
11 The above copyright notice and this permission notice shall be included in | |
12 all copies or substantial portions of the Software. | |
13 | |
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 THE SOFTWARE. | |
21 */ | |
22 | |
23 package fschmidt.db.util; | |
24 | |
25 import java.lang.ref.ReferenceQueue; | |
26 import java.util.Map; | |
27 import java.util.AbstractMap; | |
28 import java.util.HashMap; | |
29 import java.util.Set; | |
30 import java.util.AbstractSet; | |
31 import java.util.Iterator; | |
32 | |
33 | |
34 public abstract class CacheMap<K,V> extends AbstractMap<K,V> { | |
35 | |
36 protected static interface MyReference<K,V> { | |
37 public K key(); | |
38 public V get(); | |
39 public void clear(); | |
40 } | |
41 | |
42 protected abstract MyReference<K,V> newReference(K key,V value,ReferenceQueue<V> q); | |
43 | |
44 private final Map<K,MyReference<K,V>> cache = new HashMap<K,MyReference<K,V>>(); | |
45 private final ReferenceQueue<V> queue = new ReferenceQueue<V>(); | |
46 | |
47 private void sweep() { | |
48 while(true) { | |
49 @SuppressWarnings("unchecked") | |
50 MyReference<K,V> ref = (MyReference<K,V>)queue.poll(); | |
51 if( ref == null ) | |
52 return; | |
53 MyReference<K,V> mappedRef = cache.remove(ref.key()); | |
54 if( mappedRef != ref && mappedRef != null ) | |
55 cache.put( mappedRef.key(), mappedRef ); // put it back | |
56 } | |
57 } | |
58 | |
59 public int size() { | |
60 return cache.size(); | |
61 } | |
62 | |
63 public boolean isEmpty() { | |
64 return cache.isEmpty(); | |
65 } | |
66 | |
67 public boolean containsKey(Object key) { | |
68 return cache.containsKey(key); | |
69 } | |
70 | |
71 public V get(Object key) { | |
72 MyReference<K,V> ref = cache.get(key); | |
73 return ref==null ? null : ref.get(); | |
74 } | |
75 | |
76 public V put(K key,V value) { | |
77 sweep(); | |
78 MyReference<K,V> ref = cache.put( key, newReference(key,value,queue) ); | |
79 return ref==null ? null : ref.get(); | |
80 } | |
81 | |
82 public V remove(Object key) { | |
83 sweep(); | |
84 MyReference<K,V> ref = cache.remove(key); | |
85 return ref==null ? null : ref.get(); | |
86 } | |
87 | |
88 public void clear() { | |
89 sweep(); | |
90 cache.clear(); | |
91 } | |
92 | |
93 /* | |
94 public Object clone() { | |
95 GCCacheMap map = new GCCacheMap(); | |
96 map.cache = (HashMap)cache.clone(); | |
97 return map; | |
98 } | |
99 */ | |
100 public Set<K> keySet() { | |
101 return cache.keySet(); | |
102 } | |
103 | |
104 public Set<Map.Entry<K,V>> entrySet() { | |
105 return new MySet(); | |
106 } | |
107 | |
108 | |
109 private class MySet extends AbstractSet<Map.Entry<K,V>> { | |
110 | |
111 public int size() { | |
112 return CacheMap.this.size(); | |
113 } | |
114 | |
115 public Iterator<Map.Entry<K,V>> iterator() { | |
116 return new MyIterator(cache.entrySet().iterator()); | |
117 } | |
118 | |
119 } | |
120 | |
121 private class MyIterator implements Iterator<Map.Entry<K,V>> { | |
122 Iterator<Map.Entry<K,MyReference<K,V>>> iter; | |
123 | |
124 MyIterator(Iterator<Map.Entry<K,MyReference<K,V>>> iter) { | |
125 this.iter = iter; | |
126 } | |
127 | |
128 public boolean hasNext() { | |
129 return iter.hasNext(); | |
130 } | |
131 | |
132 public void remove() { | |
133 iter.remove(); | |
134 } | |
135 | |
136 public Map.Entry<K,V> next() { | |
137 return new MyEntry( iter.next() ); | |
138 } | |
139 } | |
140 | |
141 private class MyEntry implements Map.Entry<K,V> { | |
142 Map.Entry<K,MyReference<K,V>> entry; | |
143 | |
144 MyEntry(Map.Entry<K,MyReference<K,V>> entry) { | |
145 this.entry = entry; | |
146 } | |
147 | |
148 public K getKey() { | |
149 return entry.getKey(); | |
150 } | |
151 | |
152 public V getValue() { | |
153 MyReference<K,V> ref = entry.getValue(); | |
154 return ref.get(); | |
155 } | |
156 | |
157 public V setValue(V value) { | |
158 MyReference<K,V> ref = entry.setValue( newReference(getKey(),value,queue) ); | |
159 return ref.get(); | |
160 } | |
161 | |
162 public boolean equals(Object o) { | |
163 if( o==null || !(o instanceof CacheMap.MyEntry) ) | |
164 return false; | |
165 MyEntry m = (MyEntry)o; | |
166 return entry.equals(m.entry); | |
167 } | |
168 | |
169 public int hashCode() { | |
170 K key = getKey(); | |
171 V value = getValue(); | |
172 return (key==null ? 0 : key.hashCode()) ^ | |
173 (value==null ? 0 : value.hashCode()); | |
174 } | |
175 } | |
176 | |
177 } |