1 32 package net.sf.retrotranslator.runtime.impl; 33 34 import java.lang.ref.*; 35 import java.util.concurrent.*; 36 37 40 public class WeakIdentityTable<K, V> { 41 42 private final ConcurrentMap<IdentityKey<K>, V> map = new ConcurrentHashMap<IdentityKey<K>, V>(); 43 private final ReferenceQueue<K> queue = new ReferenceQueue<K>(); 44 45 public WeakIdentityTable() { 46 } 47 48 public V lookup(K key) { 49 return map.get(new StrongKey<K>(key)); 50 } 51 52 public V obtain(K key) { 53 V currentValue = map.get(new StrongKey<K>(key)); 54 if (currentValue != null) { 55 return currentValue; 56 } 57 cleanup(); 58 V newValue = initialValue(); 59 V previousValue = map.putIfAbsent(new WeakKey<K>(key, queue), newValue); 60 return previousValue != null ? previousValue : newValue; 61 } 62 63 public void putIfAbsent(K key, V value) { 64 cleanup(); 65 map.putIfAbsent(new WeakKey<K>(key, queue), value); 66 } 67 68 public int size() { 69 cleanup(); 70 return map.size(); 71 } 72 73 protected V initialValue() { 74 return null; 75 } 76 77 private void cleanup() { 78 Reference reference; 79 while ((reference = queue.poll()) != null) { 80 map.remove(reference); 81 } 82 } 83 84 private interface IdentityKey<T> { 85 T get(); 86 } 87 88 private static class StrongKey<T> implements IdentityKey<T> { 89 90 private T referent; 91 92 public StrongKey(T referent) { 93 if (referent == null) { 94 throw new NullPointerException (); 95 } 96 this.referent = referent; 97 } 98 99 public T get() { 100 return referent; 101 } 102 103 public int hashCode() { 104 return System.identityHashCode(referent); 105 } 106 107 public boolean equals(Object obj) { 108 return obj instanceof IdentityKey && ((IdentityKey) obj).get() == referent; 109 } 110 } 111 112 private static class WeakKey<T> extends WeakReference<T> implements IdentityKey<T> { 113 114 private int hashCode; 115 116 public WeakKey(T referent, ReferenceQueue<T> queue) { 117 super(referent, queue); 118 if (referent == null) { 119 throw new NullPointerException (); 120 } 121 hashCode = System.identityHashCode(referent); 122 } 123 124 public int hashCode() { 125 return hashCode; 126 } 127 128 public boolean equals(Object obj) { 129 return obj == this || (obj instanceof IdentityKey && ((IdentityKey) obj).get() == get()); 130 } 131 132 } 133 134 } 135 | Popular Tags |