mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
introduce ref-value maps with evictionListener
GitOrigin-RevId: 9f20025f191386a9d0c964c871a7c470fa4255a9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
989a7dc786
commit
018e5f86ea
@@ -183,7 +183,7 @@ public class ContainerUtilCollectionsTest extends Assert {
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testValueTossedEvenInCaseOfSuccessfulPutIfAbsentInConcurrentSoftValueMap() {
|
||||
ConcurrentSoftValueHashMap<Object, Object> map = new ConcurrentSoftValueHashMap<>();
|
||||
ConcurrentMap<Object, Object> map = CollectionFactory.createConcurrentSoftValueMap();
|
||||
Object value = new Object();
|
||||
Reference<Object> ref = new SoftReference<>(value);
|
||||
map.put(1, value);
|
||||
@@ -196,7 +196,7 @@ public class ContainerUtilCollectionsTest extends Assert {
|
||||
while (ref.get()!=null);
|
||||
Object old = map.putIfAbsent(2, new Object());
|
||||
assertNull(old);
|
||||
assertFalse(map.processQueue());
|
||||
assertFalse(((ConcurrentRefValueHashMap<?, ?>)map).processQueue());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue") // Map contract is tested, not implied here
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
// ContainerUtil requires trove in classpath
|
||||
public final class CollectionFactory {
|
||||
@@ -30,12 +31,24 @@ public final class CollectionFactory {
|
||||
|
||||
@Contract(value = " -> new", pure = true)
|
||||
public static @NotNull <K, V> ConcurrentMap<@NotNull K, @NotNull V> createConcurrentWeakValueMap() {
|
||||
return new ConcurrentWeakValueHashMap<>();
|
||||
return new ConcurrentWeakValueHashMap<>(null);
|
||||
}
|
||||
|
||||
@Contract(value = " -> new", pure = true)
|
||||
public static @NotNull <K, V> ConcurrentMap<@NotNull K, @NotNull V> createConcurrentSoftValueMap() {
|
||||
return new ConcurrentSoftValueHashMap<>();
|
||||
return new ConcurrentSoftValueHashMap<>(null);
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
public static @NotNull <K, V> ConcurrentMap<@NotNull K, @NotNull V> createConcurrentWeakValueMap(
|
||||
@NotNull Consumer<K> evictionListener) {
|
||||
return new ConcurrentWeakValueHashMap<>(evictionListener);
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
public static @NotNull <K, V> ConcurrentMap<@NotNull K, @NotNull V> createConcurrentSoftValueMap(
|
||||
@NotNull Consumer<K> evictionListener) {
|
||||
return new ConcurrentSoftValueHashMap<>(evictionListener);
|
||||
}
|
||||
|
||||
@Contract(value = " -> new", pure = true)
|
||||
|
||||
@@ -4,12 +4,13 @@ package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.openapi.util.text.Strings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.HashSet;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Base class for concurrent strong key:K -> (soft/weak) value:V map
|
||||
@@ -17,9 +18,15 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* Null values are NOT allowed
|
||||
*/
|
||||
abstract class ConcurrentRefValueHashMap<K, V> implements ConcurrentMap<K, V> {
|
||||
|
||||
private final ConcurrentMap<K, ValueReference<K, V>> myMap = new ConcurrentHashMap<>();
|
||||
private final Consumer<K> myEvictionListener;
|
||||
protected final ReferenceQueue<V> myQueue = new ReferenceQueue<>();
|
||||
|
||||
ConcurrentRefValueHashMap(@Nullable Consumer<K> evictionListener) {
|
||||
myEvictionListener = evictionListener;
|
||||
}
|
||||
|
||||
interface ValueReference<K, V> {
|
||||
@NotNull
|
||||
K getKey();
|
||||
@@ -35,7 +42,10 @@ abstract class ConcurrentRefValueHashMap<K, V> implements ConcurrentMap<K, V> {
|
||||
//noinspection unchecked
|
||||
ValueReference<K, V> ref = (ValueReference<K, V>)myQueue.poll();
|
||||
if (ref == null) break;
|
||||
myMap.remove(ref.getKey(), ref);
|
||||
K key = ref.getKey();
|
||||
if (myMap.remove(key, ref) && myEvictionListener != null) {
|
||||
myEvictionListener.accept(key);
|
||||
}
|
||||
processed = true;
|
||||
}
|
||||
return processed;
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Concurrent strong key:K -> soft value:V map
|
||||
@@ -13,6 +15,11 @@ import java.lang.ref.SoftReference;
|
||||
* Use {@link CollectionFactory#createConcurrentSoftValueMap()} to create this
|
||||
*/
|
||||
final class ConcurrentSoftValueHashMap<K,V> extends ConcurrentRefValueHashMap<K,V> {
|
||||
|
||||
ConcurrentSoftValueHashMap(@Nullable Consumer<K> evictionListener) {
|
||||
super(evictionListener);
|
||||
}
|
||||
|
||||
private static final class MySoftReference<K, V> extends SoftReference<V> implements ValueReference<K, V> {
|
||||
private final K key;
|
||||
private MySoftReference(@NotNull K key, @NotNull V referent, @NotNull ReferenceQueue<V> q) {
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Concurrent strong key:K -> weak value:V map
|
||||
@@ -14,6 +16,11 @@ import java.lang.ref.WeakReference;
|
||||
* Use {@link ContainerUtil#createConcurrentWeakValueMap()} to create this
|
||||
*/
|
||||
final class ConcurrentWeakValueHashMap<K,V> extends ConcurrentRefValueHashMap<K,V> {
|
||||
|
||||
ConcurrentWeakValueHashMap(@Nullable Consumer<K> evictionListener) {
|
||||
super(evictionListener);
|
||||
}
|
||||
|
||||
private static final class MyWeakReference<K, V> extends WeakReference<V> implements ValueReference<K, V> {
|
||||
private final K key;
|
||||
private MyWeakReference(@NotNull K key, @NotNull V referent, @NotNull ReferenceQueue<V> q) {
|
||||
|
||||
Reference in New Issue
Block a user