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 } |
