mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
IJPL-568 ConcurrentRefValueHashMap.putIfAbsent does not get rid of obsolete references when the insertion succeeds from the first try
GitOrigin-RevId: 377c170b64fc92f732d33ce811601b6d20ea1a73
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9a6807daab
commit
0fe1ce6791
@@ -17,6 +17,8 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestRule;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@@ -179,6 +181,24 @@ public class ContainerUtilCollectionsTest extends Assert {
|
||||
checkValueTossedEventually(map);
|
||||
}
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testValueTossedEvenInCaseOfSuccessfulPutIfAbsentInConcurrentSoftValueMap() {
|
||||
ConcurrentSoftValueHashMap<Object, Object> map = new ConcurrentSoftValueHashMap<>();
|
||||
Object value = new Object();
|
||||
Reference<Object> ref = new SoftReference<>(value);
|
||||
map.put(1, value);
|
||||
assertEquals(1, map.size());
|
||||
value = null;
|
||||
|
||||
do {
|
||||
GCUtil.tryGcSoftlyReachableObjects();
|
||||
}
|
||||
while (ref.get()!=null);
|
||||
Object old = map.putIfAbsent(2, new Object());
|
||||
assertNull(old);
|
||||
assertFalse(map.processQueue());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue") // Map contract is tested, not implied here
|
||||
private void checkClearsEventuallyAfterGCPressure(Map<Object, Object> map, @NotNull Runnable putKey) {
|
||||
assertTrue(map.isEmpty());
|
||||
|
||||
@@ -61,9 +61,9 @@ abstract class ConcurrentRefValueHashMap<K, V> implements ConcurrentMap<K, V> {
|
||||
public V putIfAbsent(@NotNull K key, @NotNull V value) {
|
||||
ValueReference<K, V> newRef = createValueReference(key, value);
|
||||
while (true) {
|
||||
processQueue();
|
||||
ValueReference<K, V> oldRef = myMap.putIfAbsent(key, newRef);
|
||||
if (oldRef == null) return null;
|
||||
processQueue();
|
||||
V oldVal = oldRef.get();
|
||||
if (oldVal == null) {
|
||||
if (myMap.replace(key, oldRef, newRef)) return null;
|
||||
|
||||
Reference in New Issue
Block a user