aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/scopedpool/SoftValueHashMap.java
diff options
context:
space:
mode:
authornickl- <github@jigsoft.co.za>2017-10-29 23:42:49 +0200
committernickl- <github@jigsoft.co.za>2017-11-12 23:52:01 +0200
commit53325f5637042322f1b810ad32c8ee3bad2915f4 (patch)
treed5153092d9a968d3f6e7c9ae912c0df036959c03 /src/main/javassist/scopedpool/SoftValueHashMap.java
parente1f0bba5de4dc03a9debfab333683f07cfbcb594 (diff)
downloadjavassist-53325f5637042322f1b810ad32c8ee3bad2915f4.tar.gz
javassist-53325f5637042322f1b810ad32c8ee3bad2915f4.zip
Fixes to javassist.scopepool
Applied parameters and squashed all compiler warnings. Changed loops to enhanced for where appropriate. Fixed SoftValueHashMap: Made it a raw type. Overwritten implementation of the `get` method correctly unwrapped the reference but the methods `containsValue` and `entrySet` needed to be fixed. Implemented the remaining outstanding methods from the `java.util.Map` contract `values`, `putAll` and `keySet`. Dropped `AbstractMap` inheritance as we were not inheriting anything anymore. Changed internal map to `ConcurrentHashMap' to be atomic and parallel safe. Found original unit tests from jboss retro which are now updated to reflect the javassist versions of the scoped pool classes. Added tests for the SoftValueHashMap including test which overloads the heap to ensure the cache cleans itself appropriately.
Diffstat (limited to 'src/main/javassist/scopedpool/SoftValueHashMap.java')
-rw-r--r--src/main/javassist/scopedpool/SoftValueHashMap.java132
1 files changed, 96 insertions, 36 deletions
diff --git a/src/main/javassist/scopedpool/SoftValueHashMap.java b/src/main/javassist/scopedpool/SoftValueHashMap.java
index df6ae599..1154e62e 100644
--- a/src/main/javassist/scopedpool/SoftValueHashMap.java
+++ b/src/main/javassist/scopedpool/SoftValueHashMap.java
@@ -18,10 +18,14 @@ package javassist.scopedpool;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
-import java.util.AbstractMap;
-import java.util.HashMap;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* This Map will remove entries when the value in the map has been cleaned from
@@ -30,21 +34,21 @@ import java.util.Set;
* @version <tt>$Revision: 1.4 $</tt>
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
*/
-public class SoftValueHashMap extends AbstractMap implements Map {
- private static class SoftValueRef extends SoftReference {
- public Object key;
+public class SoftValueHashMap<K,V> implements Map<K,V> {
+ private static class SoftValueRef<K,V> extends SoftReference<V> {
+ public K key;
- private SoftValueRef(Object key, Object val, ReferenceQueue q) {
+ private SoftValueRef(K key, V val, ReferenceQueue<V> q) {
super(val, q);
this.key = key;
}
- private static SoftValueRef create(Object key, Object val,
- ReferenceQueue q) {
+ private static <K,V> SoftValueRef<K,V> create(
+ K key, V val, ReferenceQueue<V> q) {
if (val == null)
return null;
else
- return new SoftValueRef(key, val, q);
+ return new SoftValueRef<K,V>(key, val, q);
}
}
@@ -52,30 +56,37 @@ public class SoftValueHashMap extends AbstractMap implements Map {
/**
* Returns a set of the mappings contained in this hash table.
*/
- public Set entrySet() {
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
processQueue();
- return hash.entrySet();
+ Set<Entry<K,V>> ret = new HashSet<Entry<K,V>>();
+ for (Entry<K,SoftValueRef<K,V>> e:hash.entrySet())
+ ret.add(new SimpleImmutableEntry<K,V> (
+ e.getKey(), e.getValue().get()));
+ return ret;
}
/* Hash table mapping WeakKeys to values */
- private Map hash;
+ private Map<K,SoftValueRef<K,V>> hash;
/* Reference queue for cleared WeakKeys */
- private ReferenceQueue queue = new ReferenceQueue();
+ private ReferenceQueue<V> queue = new ReferenceQueue<V>();
/*
* Remove all invalidated entries from the map, that is, remove all entries
* whose values have been discarded.
*/
private void processQueue() {
- SoftValueRef ref;
- while ((ref = (SoftValueRef)queue.poll()) != null) {
- if (ref == (SoftValueRef)hash.get(ref.key)) {
- // only remove if it is the *exact* same WeakValueRef
- //
- hash.remove(ref.key);
+ Object ref;
+ if (!hash.isEmpty())
+ while ((ref = queue.poll()) != null)
+ if (ref instanceof SoftValueRef) {
+ @SuppressWarnings("rawtypes")
+ SoftValueRef que =(SoftValueRef) ref;
+ if (ref == hash.get(que.key))
+ // only remove if it is the *exact* same SoftValueRef
+ hash.remove(que.key);
}
- }
}
/* -- Constructors -- */
@@ -95,7 +106,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* factor is nonpositive
*/
public SoftValueHashMap(int initialCapacity, float loadFactor) {
- hash = new HashMap(initialCapacity, loadFactor);
+ hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity, loadFactor);
}
/**
@@ -109,7 +120,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* If the initial capacity is less than zero
*/
public SoftValueHashMap(int initialCapacity) {
- hash = new HashMap(initialCapacity);
+ hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity);
}
/**
@@ -117,7 +128,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* initial capacity and the default load factor, which is <code>0.75</code>.
*/
public SoftValueHashMap() {
- hash = new HashMap();
+ hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>();
}
/**
@@ -129,7 +140,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
*
* @param t the map whose mappings are to be placed in this map.
*/
- public SoftValueHashMap(Map t) {
+ public SoftValueHashMap(Map<K,V> t) {
this(Math.max(2 * t.size(), 11), 0.75f);
putAll(t);
}
@@ -142,6 +153,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* <code>Map</code> interface, the time required by this operation is
* linear in the size of the map.</em>
*/
+ @Override
public int size() {
processQueue();
return hash.size();
@@ -150,6 +162,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
/**
* Returns <code>true</code> if this map contains no key-value mappings.
*/
+ @Override
public boolean isEmpty() {
processQueue();
return hash.isEmpty();
@@ -162,6 +175,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @param key
* The key whose presence in this map is to be tested.
*/
+ @Override
public boolean containsKey(Object key) {
processQueue();
return hash.containsKey(key);
@@ -177,12 +191,10 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @param key
* The key whose associated value, if any, is to be returned.
*/
- public Object get(Object key) {
+ @Override
+ public V get(Object key) {
processQueue();
- SoftReference ref = (SoftReference)hash.get(key);
- if (ref != null)
- return ref.get();
- return null;
+ return valueOrNull(hash.get(key));
}
/**
@@ -200,12 +212,10 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @return The previous value to which this key was mapped, or
* <code>null</code> if if there was no mapping for the key
*/
- public Object put(Object key, Object value) {
+ @Override
+ public V put(K key, V value) {
processQueue();
- Object rtn = hash.put(key, SoftValueRef.create(key, value, queue));
- if (rtn != null)
- rtn = ((SoftReference)rtn).get();
- return rtn;
+ return valueOrNull(hash.put(key, SoftValueRef.create(key, value, queue)));
}
/**
@@ -218,16 +228,66 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @return The value to which this key was mapped, or <code>null</code> if
* there was no mapping for the key.
*/
- public Object remove(Object key) {
+ @Override
+ public V remove(Object key) {
processQueue();
- return hash.remove(key);
+ return valueOrNull(hash.remove(key));
}
/**
* Removes all mappings from this map.
*/
+ @Override
public void clear() {
processQueue();
hash.clear();
}
+
+ /*
+ * Check whether the supplied value exists.
+ * @param Object the value to compare.
+ * @return true if it was found or null.
+ */
+ @Override
+ public boolean containsValue(Object arg0) {
+ processQueue();
+ if (null == arg0)
+ return false;
+
+ for (SoftValueRef<K,V> e:hash.values())
+ if (null != e && arg0.equals(e.get()))
+ return true;
+ return false;
+ }
+
+ /* {@inheritDoc} */
+ @Override
+ public Set<K> keySet() {
+ processQueue();
+ return hash.keySet();
+ }
+
+ /* {@inheritDoc} */
+ @Override
+ public void putAll(Map<? extends K,? extends V> arg0) {
+ processQueue();
+ for (K key:arg0.keySet())
+ put(key, arg0.get(key));
+ }
+
+ /* {@inheritDoc} */
+ @Override
+ public Collection<V> values() {
+ processQueue();
+ List<V> ret = new ArrayList<V>();
+ for (SoftValueRef<K,V> e:hash.values())
+ ret.add(e.get());
+ return ret;
+ }
+
+ private V valueOrNull(SoftValueRef<K,V> rtn) {
+ if (null == rtn)
+ return null;
+ return rtn.get();
+ }
}