mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
added WeakKeySoftValueMap
This commit is contained in:
@@ -298,6 +298,10 @@ public class ConcurrentMapsTest {
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testWeakKeyWeakValueTossedWeakKeyAndValue() {
|
||||
WeakKeyWeakValueHashMap<Object, Object> map = new WeakKeyWeakValueHashMap<>();
|
||||
checkTossed(map);
|
||||
}
|
||||
|
||||
private static void checkTossed(RefKeyRefValueHashMap<Object, Object> map) {
|
||||
map.put(new Object(), new Object());
|
||||
|
||||
do {
|
||||
@@ -306,6 +310,32 @@ public class ConcurrentMapsTest {
|
||||
}
|
||||
while (!map.processQueue());
|
||||
assertTrue(map.isEmpty());
|
||||
|
||||
Object hardKey = map;
|
||||
map.put(hardKey, new Object());
|
||||
|
||||
do {
|
||||
tryGcSoftlyReachableObjects();
|
||||
System.gc();
|
||||
}
|
||||
while (!map.processQueue());
|
||||
assertTrue(map.isEmpty());
|
||||
|
||||
Object hardValue = map;
|
||||
map.put(new Object(), hardValue);
|
||||
|
||||
do {
|
||||
tryGcSoftlyReachableObjects();
|
||||
System.gc();
|
||||
}
|
||||
while (!map.processQueue());
|
||||
assertTrue(map.isEmpty());
|
||||
}
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testWeakKeySoftValueTossedWeakKeyAndValue() {
|
||||
WeakKeySoftValueHashMap<Object, Object> map = new WeakKeySoftValueHashMap<>();
|
||||
checkTossed(map);
|
||||
}
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
|
||||
@@ -2821,5 +2821,10 @@ public class ContainerUtil extends ContainerUtilRt {
|
||||
return new TreeMap<K, Collection<V>>();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <K,V> Map<K,V> createWeakKeySoftValueMap() {
|
||||
return new WeakKeySoftValueHashMap<K, V>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.*;
|
||||
|
||||
abstract class RefKeyRefValueHashMap<K,V> implements Map<K,V>{
|
||||
private final RefHashMap<K, ValueReference<K,V>> myWeakKeyMap;
|
||||
private final ReferenceQueue<V> myQueue = new ReferenceQueue<V>();
|
||||
|
||||
public RefKeyRefValueHashMap(@NotNull RefHashMap<K, ValueReference<K, V>> weakKeyMap) {
|
||||
myWeakKeyMap = weakKeyMap;
|
||||
}
|
||||
|
||||
protected interface ValueReference<K, V> {
|
||||
@NotNull
|
||||
RefHashMap.Key<K> getKey();
|
||||
|
||||
V get();
|
||||
}
|
||||
protected V dereference(ValueReference<K, V> reference) {
|
||||
return reference == null ? null : reference.get();
|
||||
}
|
||||
|
||||
protected abstract ValueReference<K,V> createValueReference(@NotNull RefHashMap.Key<K> key, V referent, ReferenceQueue<? super V> q);
|
||||
|
||||
// returns true if some refs were tossed
|
||||
boolean processQueue() {
|
||||
boolean processed = myWeakKeyMap.processQueue();
|
||||
while(true) {
|
||||
ValueReference<K,V> ref = (ValueReference<K, V>)myQueue.poll();
|
||||
if (ref == null) break;
|
||||
RefHashMap.Key<K> weakKey = ref.getKey();
|
||||
myWeakKeyMap.removeKey(weakKey);
|
||||
processed = true;
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
ValueReference<K,V> ref = myWeakKeyMap.get(key);
|
||||
return dereference(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
processQueue();
|
||||
RefHashMap.Key<K> weakKey = myWeakKeyMap.createKey(key);
|
||||
ValueReference<K, V> reference = createValueReference(weakKey, value, myQueue);
|
||||
ValueReference<K,V> oldRef = myWeakKeyMap.putKey(weakKey, reference);
|
||||
return dereference(oldRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
processQueue();
|
||||
ValueReference<K,V> ref = myWeakKeyMap.remove(key);
|
||||
return dereference(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NotNull Map<? extends K, ? extends V> t) {
|
||||
throw new RuntimeException("method not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
myWeakKeyMap.clear();
|
||||
processQueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return myWeakKeyMap.size(); //?
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return myWeakKeyMap.isEmpty(); //?
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
throw new RuntimeException("method not implemented");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return myWeakKeyMap.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
List<V> result = new ArrayList<V>();
|
||||
final Collection<ValueReference<K, V>> refs = myWeakKeyMap.values();
|
||||
for (ValueReference<K, V> ref : refs) {
|
||||
final V value = ref.get();
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
throw new RuntimeException("method not implemented");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Map;
|
||||
|
||||
final class WeakKeySoftValueHashMap<K,V> extends RefKeyRefValueHashMap<K,V> implements Map<K,V>{
|
||||
public WeakKeySoftValueHashMap() {
|
||||
super(new WeakHashMap<K, ValueReference<K, V>>());
|
||||
}
|
||||
|
||||
private static class SoftValueReference<K,V> extends SoftReference<V> implements ValueReference<K,V> {
|
||||
@NotNull private final RefHashMap.Key<K> key;
|
||||
|
||||
private SoftValueReference(@NotNull WeakHashMap.Key<K> key, V referent, ReferenceQueue<? super V> q) {
|
||||
super(referent, q);
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public RefHashMap.Key<K> getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValueReference<K, V> createValueReference(@NotNull RefHashMap.Key<K> key,
|
||||
V referent,
|
||||
ReferenceQueue<? super V> q) {
|
||||
return new SoftValueReference<K, V>(key, referent, q);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,115 +15,36 @@
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.reference.SoftReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
|
||||
public final class WeakKeyWeakValueHashMap<K,V> implements Map<K,V>{
|
||||
private final WeakHashMap<K, ValueReference<K,V>> myWeakKeyMap = new WeakHashMap<K, ValueReference<K, V>>();
|
||||
private final ReferenceQueue<V> myQueue = new ReferenceQueue<V>();
|
||||
public final class WeakKeyWeakValueHashMap<K,V> extends RefKeyRefValueHashMap<K,V> implements Map<K,V>{
|
||||
public WeakKeyWeakValueHashMap() {
|
||||
super(new WeakHashMap<K, ValueReference<K, V>>());
|
||||
}
|
||||
|
||||
private static class ValueReference<K,V> extends WeakReference<V> {
|
||||
private static class WeakValueReference<K,V> extends WeakReference<V> implements ValueReference<K,V> {
|
||||
@NotNull private final WeakHashMap.Key<K> key;
|
||||
|
||||
private ValueReference(@NotNull WeakHashMap.Key<K> key, V referent, ReferenceQueue<? super V> q) {
|
||||
private WeakValueReference(@NotNull WeakHashMap.Key<K> key, V referent, ReferenceQueue<? super V> q) {
|
||||
super(referent, q);
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if some refs were tossed
|
||||
boolean processQueue() {
|
||||
boolean processed = myWeakKeyMap.processQueue();
|
||||
while(true) {
|
||||
ValueReference<K,V> ref = (ValueReference<K, V>)myQueue.poll();
|
||||
if (ref == null) break;
|
||||
WeakHashMap.Key<K> weakKey = ref.key;
|
||||
myWeakKeyMap.removeKey(weakKey);
|
||||
processed = true;
|
||||
@NotNull
|
||||
@Override
|
||||
public RefHashMap.Key<K> getKey() {
|
||||
return key;
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
ValueReference<K,V> ref = myWeakKeyMap.get(key);
|
||||
return SoftReference.dereference(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
processQueue();
|
||||
WeakHashMap.Key<K> weakKey = myWeakKeyMap.createKey(key);
|
||||
ValueReference<K, V> reference = new ValueReference<K, V>(weakKey, value, myQueue);
|
||||
ValueReference<K,V> oldRef = myWeakKeyMap.putKey(weakKey, reference);
|
||||
return SoftReference.dereference(oldRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
processQueue();
|
||||
ValueReference<K,V> ref = myWeakKeyMap.remove(key);
|
||||
return SoftReference.dereference(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NotNull Map<? extends K, ? extends V> t) {
|
||||
throw new RuntimeException("method not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
myWeakKeyMap.clear();
|
||||
processQueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return myWeakKeyMap.size(); //?
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return myWeakKeyMap.isEmpty(); //?
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
throw new RuntimeException("method not implemented");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return myWeakKeyMap.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
List<V> result = new ArrayList<V>();
|
||||
final Collection<ValueReference<K, V>> refs = myWeakKeyMap.values();
|
||||
for (ValueReference<K, V> ref : refs) {
|
||||
final V value = ref.get();
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
throw new RuntimeException("method not implemented");
|
||||
protected ValueReference<K, V> createValueReference(@NotNull RefHashMap.Key<K> key,
|
||||
V referent,
|
||||
ReferenceQueue<? super V> q) {
|
||||
return new WeakValueReference<K, V>(key, referent, q);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user