Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2013-02-21 07:57:11 +0000
committerEike Stepper2013-02-21 07:57:11 +0000
commitccc143cdbf937af334cb50a69582bb3f8899758e (patch)
tree978fb585501a9a86d4e98e03030bea7b3536eacc /plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref
parentcf49b7c79567c2428ecfca6d42867eda592cefca (diff)
downloadcdo-ccc143cdbf937af334cb50a69582bb3f8899758e.tar.gz
cdo-ccc143cdbf937af334cb50a69582bb3f8899758e.tar.xz
cdo-ccc143cdbf937af334cb50a69582bb3f8899758e.zip
[400892] Intern all CDOIDs
https://bugs.eclipse.org/bugs/show_bug.cgi?id=400892
Diffstat (limited to 'plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref')
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java361
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java452
2 files changed, 460 insertions, 353 deletions
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java
index 75bff38f4b..0ea271d86a 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java
@@ -4,21 +4,13 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
+ *
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.net4j.util.ref;
-import org.eclipse.net4j.util.collection.MapEntry;
-
import java.lang.ref.ReferenceQueue;
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -31,17 +23,11 @@ import java.util.concurrent.ConcurrentMap;
* <p>
* <b>Note:</b> This map is not synchronized. If it is to be used by multiple threads concurrently the user is
* responsible for applying proper external synchronization!
- *
+ *
* @author Eike Stepper
*/
-public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
+public abstract class ReferenceValueMap<K, V> extends ReferenceValueMap2<K, V> implements ConcurrentMap<K, V>
{
- private ConcurrentMap<K, KeyedReference<K, V>> map;
-
- private ReferenceQueue<V> queue;
-
- private EntrySet entrySet;
-
public ReferenceValueMap()
{
this(new ConcurrentHashMap<K, KeyedReference<K, V>>());
@@ -49,93 +35,7 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen
public ReferenceValueMap(ConcurrentMap<K, KeyedReference<K, V>> map)
{
- if (!map.isEmpty())
- {
- throw new IllegalArgumentException("!map.isEmpty()"); //$NON-NLS-1$
- }
-
- this.map = map;
- queue = createQueue();
- }
-
- @Override
- public int size()
- {
- purgeQueue();
- return map.size();
- }
-
- @Override
- public boolean isEmpty()
- {
- purgeQueue();
- return map.isEmpty();
- }
-
- @Override
- public boolean containsKey(Object key)
- {
- KeyedReference<K, V> ref = map.get(key);
- if (ref != null)
- {
- if (ref.get() == null)
- {
- // ref.enqueue();
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- @Override
- public boolean containsValue(Object value)
- {
- if (value == null)
- {
- throw new IllegalArgumentException("value == null"); //$NON-NLS-1$
- }
-
- for (KeyedReference<K, V> ref : map.values())
- {
- V v = ref.get();
- if (v == null)
- {
- // ref.enqueue();
- return false;
- }
-
- if (value.equals(v))
- {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public V get(Object key)
- {
- KeyedReference<K, V> ref = map.get(key);
- return dereference(ref);
- }
-
- @Override
- public V put(K key, V value)
- {
- try
- {
- KeyedReference<K, V> ref = createReference(key, value, queue);
- KeyedReference<K, V> oldRef = map.put(key, ref);
- return dereference(oldRef);
- }
- finally
- {
- purgeQueue();
- }
+ super(map);
}
public V putIfAbsent(K key, V value)
@@ -143,7 +43,7 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen
try
{
KeyedReference<K, V> ref = createReference(key, value, queue);
- KeyedReference<K, V> oldRef = map.putIfAbsent(key, ref);
+ KeyedReference<K, V> oldRef = ((ConcurrentMap<K, KeyedReference<K, V>>)map).putIfAbsent(key, ref);
return dereference(oldRef);
}
finally
@@ -157,7 +57,7 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen
try
{
KeyedReference<K, V> ref = createReference(key, value, queue);
- KeyedReference<K, V> oldRef = map.replace(key, ref);
+ KeyedReference<K, V> oldRef = ((ConcurrentMap<K, KeyedReference<K, V>>)map).replace(key, ref);
return dereference(oldRef);
}
finally
@@ -173,7 +73,7 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen
// TODO Consider a dummy KeyedReference class for oldRef
KeyedReference<K, V> oldRef = createReference(key, oldValue, queue);
KeyedReference<K, V> newRef = createReference(key, newValue, queue);
- return map.replace(key, oldRef, newRef);
+ return ((ConcurrentMap<K, KeyedReference<K, V>>)map).replace(key, oldRef, newRef);
}
finally
{
@@ -181,75 +81,12 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen
}
}
- @Override
- public V remove(Object key)
- {
- KeyedReference<K, V> ref = map.remove(key);
- return dereference(ref);
- }
-
public boolean remove(Object key, Object value)
{
// TODO Consider a dummy KeyedReference class for value
- return map.remove(key, value);
- }
-
- @Override
- public void clear()
- {
- purgeQueue();
- map.clear();
- }
-
- @Override
- public Set<Map.Entry<K, V>> entrySet()
- {
- if (entrySet == null)
- {
- purgeQueue();
- entrySet = new EntrySet();
- }
-
- return entrySet;
- }
-
- protected ReferenceQueue<V> createQueue()
- {
- return new ReferenceQueue<V>();
- }
-
- @SuppressWarnings("unchecked")
- protected void purgeQueue()
- {
- if (queue != null)
- {
- KeyedReference<K, V> ref;
- while ((ref = (KeyedReference<K, V>)queue.poll()) != null)
- {
- // Slightly faster than map.get() + map.remove()
- K key = ref.getKey();
- map.remove(key, ref);
- purged(key);
- }
- }
- }
-
- protected void purged(K key)
- {
- }
-
- protected V dereference(KeyedReference<K, V> ref)
- {
- if (ref == null)
- {
- return null;
- }
-
- return ref.get();
+ return ((ConcurrentMap<K, KeyedReference<K, V>>)map).remove(key, value);
}
- protected abstract KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue);
-
/**
* @author Eike Stepper
*/
@@ -318,186 +155,4 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen
return new KeyedWeakReference<K, V>(key, value, queue);
}
}
-
- /**
- * @author Eike Stepper
- */
- private class EntrySet extends AbstractSet<Map.Entry<K, V>>
- {
- public EntrySet()
- {
- }
-
- @Override
- public int size()
- {
- return map.size();
- }
-
- @Override
- public boolean isEmpty()
- {
- return map.isEmpty();
- }
-
- @Override
- public boolean contains(Object object)
- {
- if (object == null)
- {
- throw new IllegalArgumentException("object == null"); //$NON-NLS-1$
- }
-
- if (object instanceof Map.Entry<?, ?>)
- {
- Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
- Object key = entry.getKey();
- Object value = entry.getValue();
- return key != null && value != null && value.equals(get(key));
- }
-
- return false;
- }
-
- @Override
- public Iterator<Map.Entry<K, V>> iterator()
- {
- return new EntrySetIterator();
- }
-
- @Override
- public Object[] toArray()
- {
- Object[] a = new Object[size()];
- int i = 0;
- for (Map.Entry<K, V> entry : this)
- {
- a[i++] = entry;
- }
-
- return a;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> T[] toArray(T[] a)
- {
- if (a == null)
- {
- throw new IllegalArgumentException("array == null"); //$NON-NLS-1$
- }
-
- int size = size();
- if (a.length < size)
- {
- a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
- }
-
- int i = 0;
- for (Map.Entry<K, V> entry : this)
- {
- a[i++] = (T)entry;
- }
-
- if (a.length > size)
- {
- a[size] = null;
- }
-
- return a;
- }
-
- @Override
- public boolean remove(Object object)
- {
- if (object == null)
- {
- throw new IllegalArgumentException("object == null"); //$NON-NLS-1$
- }
-
- if (object instanceof Map.Entry<?, ?>)
- {
- Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
- return map.remove(entry.getKey(), entry.getValue());
- }
-
- return false;
- }
-
- @Override
- public void clear()
- {
- map.clear();
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private class EntrySetIterator implements Iterator<Map.Entry<K, V>>
- {
- private Iterator<Entry<K, KeyedReference<K, V>>> it = map.entrySet().iterator();
-
- private MapEntry<K, V> nextEntry;
-
- private K lastKey;
-
- public EntrySetIterator()
- {
- }
-
- public boolean hasNext()
- {
- if (nextEntry != null)
- {
- return true;
- }
-
- while (it.hasNext())
- {
- Entry<K, KeyedReference<K, V>> entry = it.next();
- lastKey = entry.getKey();
- V value = dereference(entry.getValue());
- if (value != null)
- {
- nextEntry = new MapEntry<K, V>(lastKey, value);
- return true;
- }
- }
-
- return false;
- }
-
- public Entry<K, V> next()
- {
- if (nextEntry == null)
- {
- if (!hasNext())
- {
- throw new NoSuchElementException();
- }
- }
-
- try
- {
- return nextEntry;
- }
- finally
- {
- nextEntry = null;
- }
- }
-
- public void remove()
- {
- if (lastKey == null)
- {
- throw new IllegalStateException("lastKey == null"); //$NON-NLS-1$
- }
-
- map.remove(lastKey);
- lastKey = null;
- nextEntry = null;
- }
- }
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java
new file mode 100644
index 0000000000..e759e47d93
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.util.ref;
+
+import org.eclipse.net4j.util.collection.MapEntry;
+
+import java.lang.ref.ReferenceQueue;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A {@link Map} implementation that uses {@link KeyedReference} instances ({@link KeyedStrongReference},
+ * {@link KeyedSoftReference}, {@link KeyedWeakReference} or {@link KeyedPhantomReference}) as its values.
+ * <p>
+ * A <code>ReferenceValueMap</code> can be used to cache mappings until the <em>value</em> of the mapping is no longer
+ * reachable from outside of the map
+ * <p>
+ * <b>Note:</b> This map is not synchronized. If it is to be used by multiple threads concurrently the user is
+ * responsible for applying proper external synchronization!
+ *
+ * @author Eike Stepper
+ */
+public abstract class ReferenceValueMap2<K, V> extends AbstractMap<K, V>
+{
+ Map<K, KeyedReference<K, V>> map;
+
+ ReferenceQueue<V> queue;
+
+ private EntrySet entrySet;
+
+ public ReferenceValueMap2()
+ {
+ this(new HashMap<K, KeyedReference<K, V>>());
+ }
+
+ public ReferenceValueMap2(Map<K, KeyedReference<K, V>> map)
+ {
+ if (!map.isEmpty())
+ {
+ throw new IllegalArgumentException("!map.isEmpty()"); //$NON-NLS-1$
+ }
+
+ this.map = map;
+ queue = createQueue();
+ }
+
+ @Override
+ public int size()
+ {
+ purgeQueue();
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ purgeQueue();
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key)
+ {
+ KeyedReference<K, V> ref = map.get(key);
+ if (ref != null)
+ {
+ if (ref.get() == null)
+ {
+ // ref.enqueue();
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean containsValue(Object value)
+ {
+ if (value == null)
+ {
+ throw new IllegalArgumentException("value == null"); //$NON-NLS-1$
+ }
+
+ for (KeyedReference<K, V> ref : map.values())
+ {
+ V v = ref.get();
+ if (v == null)
+ {
+ // ref.enqueue();
+ return false;
+ }
+
+ if (value.equals(v))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public V get(Object key)
+ {
+ KeyedReference<K, V> ref = map.get(key);
+ return dereference(ref);
+ }
+
+ @Override
+ public V put(K key, V value)
+ {
+ try
+ {
+ KeyedReference<K, V> ref = createReference(key, value, queue);
+ KeyedReference<K, V> oldRef = map.put(key, ref);
+ return dereference(oldRef);
+ }
+ finally
+ {
+ purgeQueue();
+ }
+ }
+
+ @Override
+ public V remove(Object key)
+ {
+ KeyedReference<K, V> ref = map.remove(key);
+ return dereference(ref);
+ }
+
+ @Override
+ public void clear()
+ {
+ purgeQueue();
+ map.clear();
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet()
+ {
+ if (entrySet == null)
+ {
+ purgeQueue();
+ entrySet = new EntrySet();
+ }
+
+ return entrySet;
+ }
+
+ protected ReferenceQueue<V> createQueue()
+ {
+ return new ReferenceQueue<V>();
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void purgeQueue()
+ {
+ if (queue != null)
+ {
+ KeyedReference<K, V> ref;
+ while ((ref = (KeyedReference<K, V>)queue.poll()) != null)
+ {
+ K key = ref.getKey();
+ map.remove(key);
+ purged(key);
+ }
+ }
+ }
+
+ protected void purged(K key)
+ {
+ }
+
+ protected V dereference(KeyedReference<K, V> ref)
+ {
+ if (ref == null)
+ {
+ return null;
+ }
+
+ return ref.get();
+ }
+
+ protected abstract KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue);
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class Strong<K, V> extends ReferenceValueMap2<K, V>
+ {
+ public Strong()
+ {
+ }
+
+ public Strong(Map<K, KeyedReference<K, V>> map)
+ {
+ super(map);
+ }
+
+ @Override
+ protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
+ {
+ return new KeyedStrongReference<K, V>(key, value);
+ }
+
+ @Override
+ protected ReferenceQueue<V> createQueue()
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class Soft<K, V> extends ReferenceValueMap2<K, V>
+ {
+ public Soft()
+ {
+ }
+
+ public Soft(Map<K, KeyedReference<K, V>> map)
+ {
+ super(map);
+ }
+
+ @Override
+ protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
+ {
+ return new KeyedSoftReference<K, V>(key, value, queue);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class Weak<K, V> extends ReferenceValueMap2<K, V>
+ {
+ public Weak()
+ {
+ }
+
+ public Weak(Map<K, KeyedReference<K, V>> map)
+ {
+ super(map);
+ }
+
+ @Override
+ protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
+ {
+ return new KeyedWeakReference<K, V>(key, value, queue);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private class EntrySet extends AbstractSet<Map.Entry<K, V>>
+ {
+ public EntrySet()
+ {
+ }
+
+ @Override
+ public int size()
+ {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object object)
+ {
+ if (object == null)
+ {
+ throw new IllegalArgumentException("object == null"); //$NON-NLS-1$
+ }
+
+ if (object instanceof Map.Entry<?, ?>)
+ {
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ return key != null && value != null && value.equals(get(key));
+ }
+
+ return false;
+ }
+
+ @Override
+ public Iterator<Map.Entry<K, V>> iterator()
+ {
+ return new EntrySetIterator();
+ }
+
+ @Override
+ public Object[] toArray()
+ {
+ Object[] a = new Object[size()];
+ int i = 0;
+ for (Map.Entry<K, V> entry : this)
+ {
+ a[i++] = entry;
+ }
+
+ return a;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T[] toArray(T[] a)
+ {
+ if (a == null)
+ {
+ throw new IllegalArgumentException("array == null"); //$NON-NLS-1$
+ }
+
+ int size = size();
+ if (a.length < size)
+ {
+ a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
+ }
+
+ int i = 0;
+ for (Map.Entry<K, V> entry : this)
+ {
+ a[i++] = (T)entry;
+ }
+
+ if (a.length > size)
+ {
+ a[size] = null;
+ }
+
+ return a;
+ }
+
+ @Override
+ public boolean remove(Object object)
+ {
+ if (object == null)
+ {
+ throw new IllegalArgumentException("object == null"); //$NON-NLS-1$
+ }
+
+ if (object instanceof Map.Entry<?, ?>)
+ {
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
+ return map.remove(entry.getKey()) != null;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void clear()
+ {
+ map.clear();
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private class EntrySetIterator implements Iterator<Map.Entry<K, V>>
+ {
+ private Iterator<Entry<K, KeyedReference<K, V>>> it = map.entrySet().iterator();
+
+ private MapEntry<K, V> nextEntry;
+
+ private K lastKey;
+
+ public EntrySetIterator()
+ {
+ }
+
+ public boolean hasNext()
+ {
+ if (nextEntry != null)
+ {
+ return true;
+ }
+
+ while (it.hasNext())
+ {
+ Entry<K, KeyedReference<K, V>> entry = it.next();
+ lastKey = entry.getKey();
+ V value = dereference(entry.getValue());
+ if (value != null)
+ {
+ nextEntry = new MapEntry<K, V>(lastKey, value);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public Entry<K, V> next()
+ {
+ if (nextEntry == null)
+ {
+ if (!hasNext())
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ try
+ {
+ return nextEntry;
+ }
+ finally
+ {
+ nextEntry = null;
+ }
+ }
+
+ public void remove()
+ {
+ if (lastKey == null)
+ {
+ throw new IllegalStateException("lastKey == null"); //$NON-NLS-1$
+ }
+
+ map.remove(lastKey);
+ lastKey = null;
+ nextEntry = null;
+ }
+ }
+}

Back to the top