001: /***
002: * Retrotranslator: a Java bytecode transformer that translates Java classes
003: * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
004: *
005: * Copyright (c) 2005 - 2008 Taras Puchko
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * 3. Neither the name of the copyright holders nor the names of its
017: * contributors may be used to endorse or promote products derived from
018: * this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
024: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
025: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
026: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
027: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
028: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
029: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
030: * THE POSSIBILITY OF SUCH DAMAGE.
031: */package net.sf.retrotranslator.runtime.impl;
032:
033: import java.lang.ref.*;
034: import java.util.concurrent.*;
035:
036: /**
037: * @author Taras Puchko
038: */
039: public class WeakIdentityTable<K, V> {
040:
041: private final ConcurrentMap<IdentityKey<K>, V> map = new ConcurrentHashMap<IdentityKey<K>, V>();
042: private final ReferenceQueue<K> queue = new ReferenceQueue<K>();
043:
044: public WeakIdentityTable() {
045: }
046:
047: public V lookup(K key) {
048: return map.get(new StrongKey<K>(key));
049: }
050:
051: public V obtain(K key) {
052: V currentValue = map.get(new StrongKey<K>(key));
053: if (currentValue != null) {
054: return currentValue;
055: }
056: cleanup();
057: V newValue = initialValue();
058: V previousValue = map.putIfAbsent(new WeakKey<K>(key, queue),
059: newValue);
060: return previousValue != null ? previousValue : newValue;
061: }
062:
063: public void putIfAbsent(K key, V value) {
064: cleanup();
065: map.putIfAbsent(new WeakKey<K>(key, queue), value);
066: }
067:
068: public int size() {
069: cleanup();
070: return map.size();
071: }
072:
073: protected V initialValue() {
074: return null;
075: }
076:
077: private void cleanup() {
078: Reference reference;
079: while ((reference = queue.poll()) != null) {
080: map.remove(reference);
081: }
082: }
083:
084: private interface IdentityKey<T> {
085: T get();
086: }
087:
088: private static class StrongKey<T> implements IdentityKey<T> {
089:
090: private T referent;
091:
092: public StrongKey(T referent) {
093: if (referent == null) {
094: throw new NullPointerException();
095: }
096: this .referent = referent;
097: }
098:
099: 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
109: && ((IdentityKey) obj).get() == referent;
110: }
111: }
112:
113: private static class WeakKey<T> extends WeakReference<T> implements
114: IdentityKey<T> {
115:
116: private int hashCode;
117:
118: public WeakKey(T referent, ReferenceQueue<T> queue) {
119: super (referent, queue);
120: if (referent == null) {
121: throw new NullPointerException();
122: }
123: hashCode = System.identityHashCode(referent);
124: }
125:
126: public int hashCode() {
127: return hashCode;
128: }
129:
130: public boolean equals(Object obj) {
131: return obj == this
132: || (obj instanceof IdentityKey && ((IdentityKey) obj)
133: .get() == get());
134: }
135:
136: }
137:
138: }
|