IDEA-251640 avoid dependency on trove in our concurrent weak/soft map (part 1)

GitOrigin-RevId: 4d0a086b3fd1a1fcdb6fcd432166bdecedeab09d
This commit is contained in:
Vladimir Krivosheev
2020-09-29 07:05:49 +00:00
committed by intellij-monorepo-bot
parent 450d54c7dc
commit 7b7535714d
23 changed files with 284 additions and 293 deletions
@@ -1,26 +1,12 @@
/*
* Copyright 2000-2016 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.
*/
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.search;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.impl.AnyPsiChangeListener;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -28,9 +14,9 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
class HighlightingCaches {
final class HighlightingCaches {
public static HighlightingCaches getInstance(Project project) {
return ServiceManager.getService(project, HighlightingCaches.class);
return project.getService(HighlightingCaches.class);
}
private final List<Map<?,?>> allCaches = ContainerUtil.createConcurrentList();
@@ -43,11 +29,6 @@ class HighlightingCaches {
allCaches.forEach(Map::clear);
}
}
@Override
public void afterPsiChanged(boolean isPhysical) {
}
});
}
@@ -60,9 +41,8 @@ class HighlightingCaches {
// baseMethod -> all overriding methods
final Map<PsiMethod, Iterable<PsiMethod>> OVERRIDING_METHODS = createWeakCache();
@NotNull
private <T,V> ConcurrentMap<T,V> createWeakCache() {
ConcurrentMap<T, V> map = ContainerUtil.createConcurrentWeakKeySoftValueMap(10, 0.7f, Runtime.getRuntime().availableProcessors(), ContainerUtil.canonicalStrategy());
private @NotNull <T,V> ConcurrentMap<T,V> createWeakCache() {
ConcurrentMap<T, V> map = CollectionFactory.createConcurrentWeakKeySoftValueMap(10, 0.7f, Runtime.getRuntime().availableProcessors());
allCaches.add(map);
return map;
}
@@ -13,7 +13,6 @@ import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.IdempotenceChecker;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ConcurrentWeakKeySoftValueHashMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,11 +35,6 @@ public class ResolveCache implements Disposable {
LowMemoryWatcher.register(() -> onLowMemory(), this);
}
@Deprecated
public ResolveCache(@NotNull MessageBus bus) {
clearCacheOnPsiChange(bus);
}
private void clearCacheOnPsiChange(@NotNull MessageBus bus) {
bus.connect().subscribe(PsiManagerImpl.ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener() {
@Override
@@ -91,7 +85,7 @@ public class ResolveCache implements Disposable {
@NotNull
private static <K,V> Map<K, V> createWeakMap() {
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<K, V>(100, 0.75f, Runtime.getRuntime().availableProcessors(), ContainerUtil.canonicalStrategy()){
return new ConcurrentWeakKeySoftValueHashMap<K, V>(100, 0.75f, Runtime.getRuntime().availableProcessors()) {
@NotNull
@Override
protected ValueReference<K, V> createValueReference(@NotNull V value, @NotNull ReferenceQueue<? super V> queue) {
@@ -1303,4 +1303,6 @@ gw.gosu.ij 5.0.0
com.illuminatedcloud.intellij 1.8.5.7-idea19 1.8.5.5-idea19
edu.clemson.resolve.jetbrains 0.1.2a
com.ritesh.intellij.plugin.reviewboard 0.1.4 0.1.3 v0.1.2 0.1.1 0.1.0 0.1.2-beta 0.1.1-beta 0.1.0-beta
org.jetbrains.visual.programming.ide 1.0-SNAPSHOT
org.jetbrains.visual.programming.ide 1.0-SNAPSHOT
de.nordgedanken.auto_hotkey 0.2.0
org.rust.lang 0.3.131.3366-202 0.3.131.3366-201
@@ -28,9 +28,9 @@ public class ContainerUtilCollectionsTest extends Assert {
private static final long TIMEOUT = 5 * 60 * 1000; // 5 minutes
private static final TObjectHashingStrategy<String> IGNORE_CASE_WITH_CRAZY_HASH_STRATEGY = new TObjectHashingStrategy<String>() {
private static final HashingStrategy<String> IGNORE_CASE_WITH_CRAZY_HASH_STRATEGY = new HashingStrategy<String>() {
@Override
public int computeHashCode(String object) {
public int hashCode(String object) {
return Character.toLowerCase(object.charAt(object.length() - 1));
}
@@ -48,7 +48,7 @@ public class ContainerUtilCollectionsTest extends Assert {
@Test(timeout = TIMEOUT)
public void testConcurrentSoftMapTossedEvenWithIdentityStrategy() {
ConcurrentMap<Object, Object> map = ContainerUtil.createConcurrentSoftMap(10, 0.5f, 8, ContainerUtil.identityStrategy());
ConcurrentMap<Object, Object> map = ContainerUtil.createConcurrentSoftMap(10, 0.5f, 8, HashingStrategy.identity());
checkKeyTossedEventually(map);
}
@@ -69,34 +69,34 @@ public class ContainerUtilCollectionsTest extends Assert {
@Test(timeout = TIMEOUT)
public void testConcurrentWeakKeyWeakValueTossedEvenWithIdentityStrategy() {
ConcurrentMap<Object, Object> map = ContainerUtil.createConcurrentWeakKeyWeakValueMap(ContainerUtil.identityStrategy());
ConcurrentMap<Object, Object> map = CollectionFactory.createConcurrentWeakKeyWeakValueIdentityMap();
checkKeyTossedEventually(map);
checkValueTossedEventually(map);
}
@Test(timeout = TIMEOUT)
public void testConcurrentSoftKeySoftValueTossedEvenWithIdentityStrategy() {
ConcurrentMap<Object, Object> map = ContainerUtil.createConcurrentSoftKeySoftValueMap(10, 0.5f, 8, ContainerUtil.identityStrategy());
ConcurrentMap<Object, Object> map = CollectionFactory.createConcurrentSoftKeySoftValueIdentityMap(10, 0.5f, 8);
checkKeyTossedEventually(map);
checkValueTossedEventually(map);
}
@Test(timeout = TIMEOUT)
public void testConcurrentWeakKeySoftValueTossedEvenWithIdentityStrategy() {
ConcurrentMap<Object, Object> map = ContainerUtil.createConcurrentWeakKeySoftValueMap(10, 0.5f, 8, ContainerUtil.identityStrategy());
ConcurrentMap<Object, Object> map = CollectionFactory.createConcurrentWeakKeySoftValueIdentityMap(10, 0.5f, 8);
checkKeyTossedEventually(map);
checkValueTossedEventually(map);
}
@Test(timeout = TIMEOUT)
public void testWeakMapTossedEvenWithIdentityStrategy() {
Map<Object, Object> map = ContainerUtil.createWeakMap(10,0.5f,ContainerUtil.identityStrategy());
Map<Object, Object> map = CollectionFactory.createWeakIdentityMap(10, 0.5f);
checkKeyTossedEventually(map);
}
@Test(timeout = TIMEOUT)
public void testSoftMapTossedEvenWithIdentityStrategy() {
Map<Object, Object> map = ContainerUtil.createSoftMap(ContainerUtil.identityStrategy());
Map<Object, Object> map = CollectionFactory.createSoftIdentityMap();
checkKeyTossedEventually(map);
}
@@ -148,7 +148,7 @@ public class ContainerUtilCollectionsTest extends Assert {
}
@Test(timeout = TIMEOUT)
public void testConcurrentSKSVMapDoesntRetainOldValueKeyAfterPutWithTheSameKeyButDifferentValue() {
checkMapDoesntLeakOldValueAfterPutWithTheSameKeyButDifferentValue(ContainerUtil.createConcurrentSoftKeySoftValueMap(1,1,1,ContainerUtil.canonicalStrategy()));
checkMapDoesntLeakOldValueAfterPutWithTheSameKeyButDifferentValue(CollectionFactory.createConcurrentSoftKeySoftValueMap(1, 1, 1));
}
private void checkMapDoesntLeakOldValueAfterPutWithTheSameKeyButDifferentValue(Map<Object, Object> map) {
@@ -281,14 +281,14 @@ public class ContainerUtilCollectionsTest extends Assert {
@Test(timeout = TIMEOUT)
public void testWeakNativeHashCodeDoesNotGetCalledWhenCustomStrategyIsSpecified() {
Map<Object, Object> map = ContainerUtil.createWeakMap(10,0.5f,ContainerUtil.identityStrategy());
Map<Object, Object> map = CollectionFactory.createWeakIdentityMap(10, 0.5f);
checkHashCodeDoesntCalledFor(map);
}
@Test(timeout = TIMEOUT)
public void testSoftNativeHashCodeDoesNotGetCalledWhenCustomStrategyIsSpecified() {
Map<Object, Object> map = ContainerUtil.createSoftMap(ContainerUtil.identityStrategy());
Map<Object, Object> map = CollectionFactory.createSoftIdentityMap();
checkHashCodeDoesntCalledFor(map);
}
@@ -7,6 +7,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.objectTree.ThrowableInterner;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
@@ -25,7 +26,7 @@ final class ObjectTree {
// guarded by treeLock
private final Map<Disposable, ObjectNode> myObject2NodeMap = new Reference2ObjectOpenHashMap<>();
// Disposable -> trace or boolean marker (if trace unavailable)
private final Map<Disposable, Object> myDisposedObjects = ContainerUtil.createWeakMap(100, 0.5f, ContainerUtil.identityStrategy()); // guarded by treeLock
private final Map<Disposable, Object> myDisposedObjects = CollectionFactory.createWeakIdentityMap(100, 0.5f); // guarded by treeLock
private final Object treeLock = new Object();
@@ -30,29 +30,56 @@ public final class CollectionFactory {
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakIdentityMap() {
return new ConcurrentWeakHashMap<>(ContainerUtil.identityStrategy());
return new ConcurrentWeakHashMap<>(HashingStrategy.identity());
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> Map<K, V> createWeakMap() {
return ContainerUtil.createWeakMap();
//noinspection deprecation
return new WeakHashMap<>(4, 0.8f, HashingStrategy.canonical());
}
@Contract(value = "_,_,_ -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeySoftValueIdentityMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.identity());
}
public static @NotNull <K, V> Map<K, V> createWeakIdentityMap(int initialCapacity, float loadFactor) {
//noinspection deprecation
return new WeakHashMap<>(initialCapacity, loadFactor, HashingStrategy.identity());
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeyWeakValueMap() {
return ContainerUtil.createConcurrentWeakKeyWeakValueMap(ContainerUtil.canonicalStrategy());
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeyWeakValueIdentityMap() {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.identity());
}
@Contract(value = "_,_,_ -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, ContainerUtil.canonicalStrategy());
return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical());
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeySoftValueMap() {
return ContainerUtil.createConcurrentWeakKeySoftValueMap();
return createConcurrentWeakKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors());
}
@Contract(value = "_,_,_,-> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical());
}
public static @NotNull <T> Map<CharSequence, T> createCharSequenceMap(boolean caseSensitive, int expectedSize, float loadFactor) {
@@ -95,6 +122,20 @@ public final class CollectionFactory {
return new Object2ObjectOpenCustomHashMap<>(FastUtilHashingStrategies.getCaseInsensitiveStringStrategy());
}
@Contract(value = "_,_,_ -> new", pure = true)
static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
return new ConcurrentSoftKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical());
}
@Contract(value = "_,_,_ -> new", pure = true)
static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftKeySoftValueIdentityMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
return new ConcurrentSoftKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.identity());
}
public static @NotNull Set<String> createFilePathSet() {
if (SystemInfoRt.isFileSystemCaseSensitive) {
return new HashSet<>();
@@ -128,7 +169,7 @@ public final class CollectionFactory {
public static @NotNull Set<String> createFilePathSet(String @NotNull[] paths, boolean isFileSystemCaseSensitive) {
if (isFileSystemCaseSensitive) {
return ContainerUtil.set(paths);
return new HashSet<>(Arrays.asList(paths));
}
return new ObjectOpenCustomHashSet<>(paths, FastUtilHashingStrategies.getCaseInsensitiveStringStrategy());
}
@@ -275,6 +316,11 @@ public final class CollectionFactory {
return new ConcurrentSoftHashMap<>();
}
public static @NotNull <K, V> Map<K, V> createSoftIdentityMap() {
//noinspection deprecation
return new SoftHashMap<>(HashingStrategy.identity());
}
public static void trimMap(@NotNull Map<?, ?> map) {
if (map instanceof Object2ObjectOpenHashMap<?, ?>) {
((Object2ObjectOpenHashMap<?, ?>)map).trim();
@@ -1,7 +1,6 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -15,11 +14,10 @@ import java.util.concurrent.ConcurrentMap;
* Null keys are allowed
* Null values are NOT allowed
*/
abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, TObjectHashingStrategy<K> {
abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, HashingStrategy<K> {
final ReferenceQueue<K> myReferenceQueue = new ReferenceQueue<>();
private final ConcurrentMap<KeyReference<K>, V> myMap; // hashing strategy must be canonical, we compute corresponding hash codes using our own myHashingStrategy
@NotNull
private final TObjectHashingStrategy<? super K> myHashingStrategy;
private final @NotNull HashingStrategy<? super K> myHashingStrategy;
@FunctionalInterface
interface KeyReference<K> {
@@ -33,8 +31,7 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
int hashCode();
}
@NotNull
abstract KeyReference<K> createKeyReference(@NotNull K key, @NotNull TObjectHashingStrategy<? super K> hashingStrategy);
abstract @NotNull KeyReference<K> createKeyReference(@NotNull K key, @NotNull HashingStrategy<? super K> hashingStrategy);
private static final HardKey<?> NULL_KEY = new HardKey<Object>() {
@Override
@@ -79,9 +76,9 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
this(initialCapacity, LOAD_FACTOR);
}
private static final TObjectHashingStrategy<?> THIS = new TObjectHashingStrategy<Object>() {
private static final HashingStrategy<?> THIS = new HashingStrategy<Object>() {
@Override
public int computeHashCode(Object object) {
public int hashCode(Object object) {
throw new UnsupportedOperationException();
}
@@ -90,20 +87,21 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
throw new UnsupportedOperationException();
}
};
private ConcurrentRefHashMap(int initialCapacity, float loadFactor) {
//noinspection unchecked
this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL, (TObjectHashingStrategy<? super K>)THIS);
this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL, (HashingStrategy<? super K>)THIS);
}
ConcurrentRefHashMap(@NotNull final TObjectHashingStrategy<? super K> hashingStrategy) {
ConcurrentRefHashMap(@NotNull HashingStrategy<? super K> hashingStrategy) {
this(DEFAULT_CAPACITY, LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL, hashingStrategy);
}
ConcurrentRefHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
myHashingStrategy = hashingStrategy == THIS ? this : hashingStrategy;
@Nullable HashingStrategy<? super K> hashingStrategy) {
myHashingStrategy = hashingStrategy == THIS ? this : (hashingStrategy == null ? HashingStrategy.canonical() : hashingStrategy);
myMap = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
}
@@ -175,7 +173,7 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
K key = (K)o;
//noinspection unchecked
HardKey<K> hardKey = (HardKey<K>)HARD_KEY.get();
hardKey.setKey(key, myHashingStrategy.computeHashCode(key));
hardKey.setKey(key, myHashingStrategy.hashCode(key));
return hardKey;
}
@@ -216,7 +214,7 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
myMap.clear();
}
private static class RefEntry<K, V> implements Map.Entry<K, V> {
private static final class RefEntry<K, V> implements Map.Entry<K, V> {
private final Map.Entry<?, V> ent;
private final K key; /* Strong reference to key, so that the GC
will leave it alone as long as this Entry
@@ -258,7 +256,7 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
}
/* Internal class for entry sets */
private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
private final Set<Map.Entry<KeyReference<K>, V>> hashEntrySet = myMap.entrySet();
@NotNull
@@ -388,8 +386,8 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
// MAKE SURE IT CONSISTENT WITH com.intellij.util.containers.ConcurrentHashMap
@Override
public int computeHashCode(final K object) {
int h = object.hashCode();
public int hashCode(@Nullable K object) {
int h = object == null ? 0 : object.hashCode();
h += ~(h << 9);
h ^= h >>> 14;
h += h << 4;
@@ -398,7 +396,7 @@ abstract class ConcurrentRefHashMap<K, V> extends AbstractMap<K, V> implements C
}
@Override
public boolean equals(final K o1, final K o2) {
return o1.equals(o2);
public boolean equals(K o1, K o2) {
return Objects.equals(o1, o2);
}
}
@@ -1,8 +1,6 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -21,17 +19,17 @@ final class ConcurrentSoftHashMap<K, V> extends ConcurrentRefHashMap<K, V> {
ConcurrentSoftHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
@NotNull HashingStrategy<? super K> hashingStrategy) {
super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
private static final class SoftKey<K> extends SoftReference<K> implements KeyReference<K> {
private final int myHash; // Hashcode of key, stored here since the key may be tossed by the GC
private final TObjectHashingStrategy<? super K> myStrategy;
private final HashingStrategy<? super K> myStrategy;
private SoftKey(@NotNull K k,
final int hash,
@NotNull TObjectHashingStrategy<? super K> strategy,
@NotNull HashingStrategy<? super K> strategy,
@NotNull ReferenceQueue<K> q) {
super(k, q);
myStrategy = strategy;
@@ -55,10 +53,9 @@ final class ConcurrentSoftHashMap<K, V> extends ConcurrentRefHashMap<K, V> {
}
}
@NotNull
@Override
protected KeyReference<K> createKeyReference(@NotNull K key,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new SoftKey<>(key, hashingStrategy.computeHashCode(key), hashingStrategy, myReferenceQueue);
protected @NotNull KeyReference<K> createKeyReference(@NotNull K key,
@NotNull HashingStrategy<? super K> hashingStrategy) {
return new SoftKey<>(key, hashingStrategy.hashCode(key), hashingStrategy, myReferenceQueue);
}
}
@@ -1,23 +1,7 @@
/*
* Copyright 2000-2016 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.
*/
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import com.intellij.util.ObjectUtils;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -27,28 +11,28 @@ import java.lang.ref.SoftReference;
* Concurrent map with soft keys and soft values.
* Null keys are NOT allowed
* Null values are NOT allowed
* To instantiate use {@link ContainerUtil#createConcurrentSoftKeySoftValueMap(int, float, int, TObjectHashingStrategy)}
* To instantiate use {@link ContainerUtil#createConcurrentSoftKeySoftValueMap(int, float, int, HashingStrategy)}
*/
class ConcurrentSoftKeySoftValueHashMap<K, V> extends ConcurrentWeakKeySoftValueHashMap<K,V> {
final class ConcurrentSoftKeySoftValueHashMap<K, V> extends ConcurrentWeakKeySoftValueHashMap<K,V> {
ConcurrentSoftKeySoftValueHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull final TObjectHashingStrategy<? super K> hashingStrategy) {
@NotNull HashingStrategy<? super K> hashingStrategy) {
super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
private static class SoftKey<K, V> extends SoftReference<K> implements KeyReference<K, V> {
private final int myHash; // Hash code of the key, stored here since the key may be tossed by the GC
private final TObjectHashingStrategy<? super K> myStrategy;
private final HashingStrategy<? super K> myStrategy;
@NotNull private final ValueReference<K, V> myValueReference;
SoftKey(@NotNull K k,
@NotNull ValueReference<K, V> valueReference,
@NotNull TObjectHashingStrategy<? super K> strategy,
@NotNull HashingStrategy<? super K> strategy,
@NotNull ReferenceQueue<? super K> queue) {
super(k, queue);
myValueReference = valueReference;
myHash = strategy.computeHashCode(k);
myHash = strategy.hashCode(k);
myStrategy = strategy;
}
@@ -78,7 +62,7 @@ class ConcurrentSoftKeySoftValueHashMap<K, V> extends ConcurrentWeakKeySoftValue
@NotNull
KeyReference<K,V> createKeyReference(@NotNull K k, @NotNull final V v) {
final ValueReference<K, V> valueReference = createValueReference(v, myValueQueue);
SoftKey<K, V> keyReference = new SoftKey<>(k, valueReference, myHashingStrategy, myKeyQueue);
KeyReference<K,V> keyReference = new SoftKey<>(k, valueReference, myHashingStrategy, myKeyQueue);
if (valueReference instanceof SoftValue) {
((SoftValue<K,V>)valueReference).myKeyReference = keyReference;
}
@@ -1,5 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import org.jetbrains.annotations.NotNull;
@@ -11,7 +10,7 @@ import java.lang.ref.SoftReference;
* Concurrent strong key:K -> soft value:V map
* Null keys are NOT allowed
* Null values are NOT allowed
* Use {@link ContainerUtil#createConcurrentSoftValueMap()} to create this
* Use {@link CollectionFactory#createConcurrentSoftValueMap()} to create this
*/
final class ConcurrentSoftValueHashMap<K,V> extends ConcurrentRefValueHashMap<K,V> {
private static final class MySoftReference<K, V> extends SoftReference<V> implements ValueReference<K, V> {
@@ -1,7 +1,6 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -15,11 +14,11 @@ import java.lang.ref.WeakReference;
final class ConcurrentWeakHashMap<K, V> extends ConcurrentRefHashMap<K, V> {
private static final class WeakKey<K> extends WeakReference<K> implements KeyReference<K> {
private final int myHash; /* Hashcode of key, stored here since the key may be tossed by the GC */
@NotNull private final TObjectHashingStrategy<? super K> myStrategy;
@NotNull private final HashingStrategy<? super K> myStrategy;
private WeakKey(@NotNull K k,
final int hash,
@NotNull TObjectHashingStrategy<? super K> strategy,
int hash,
@NotNull HashingStrategy<? super K> strategy,
@NotNull ReferenceQueue<K> q) {
super(k, q);
myStrategy = strategy;
@@ -43,26 +42,24 @@ final class ConcurrentWeakHashMap<K, V> extends ConcurrentRefHashMap<K, V> {
}
}
@NotNull
@Override
protected KeyReference<K> createKeyReference(@NotNull K key,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new WeakKey<>(key, hashingStrategy.computeHashCode(key), hashingStrategy, myReferenceQueue);
protected @NotNull KeyReference<K> createKeyReference(@NotNull K key,
@NotNull HashingStrategy<? super K> hashingStrategy) {
return new WeakKey<>(key, hashingStrategy.hashCode(key), hashingStrategy, myReferenceQueue);
}
ConcurrentWeakHashMap(float loadFactor) {
//noinspection unchecked
super(DEFAULT_CAPACITY, loadFactor, DEFAULT_CONCURRENCY_LEVEL, TObjectHashingStrategy.CANONICAL);
super(DEFAULT_CAPACITY, loadFactor, DEFAULT_CONCURRENCY_LEVEL, HashingStrategy.canonical());
}
ConcurrentWeakHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
@NotNull HashingStrategy<? super K> hashingStrategy) {
super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
ConcurrentWeakHashMap(@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
ConcurrentWeakHashMap(@NotNull HashingStrategy<? super K> hashingStrategy) {
super(hashingStrategy);
}
}
@@ -1,37 +1,42 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import com.intellij.openapi.util.Getter;
import com.intellij.util.ObjectUtils;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Concurrent map with weak keys and soft values.
* Null keys are NOT allowed
* Null values are NOT allowed
* @deprecated Use {@link ContainerUtil#createConcurrentWeakKeySoftValueMap(int, float, int, TObjectHashingStrategy)} instead
* @deprecated Use {@link ContainerUtil#createConcurrentWeakKeySoftValueMap(int, float, int, HashingStrategy)} instead
*/
@Deprecated
public class ConcurrentWeakKeySoftValueHashMap<K, V> implements ConcurrentMap<K, V> {
private final ConcurrentMap<KeyReference<K,V>, ValueReference<K,V>> myMap;
final ReferenceQueue<K> myKeyQueue = new ReferenceQueue<>();
final ReferenceQueue<V> myValueQueue = new ReferenceQueue<>();
@NotNull final TObjectHashingStrategy<? super K> myHashingStrategy;
@NotNull final HashingStrategy<? super K> myHashingStrategy;
protected ConcurrentWeakKeySoftValueHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
this(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical());
}
protected ConcurrentWeakKeySoftValueHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull final TObjectHashingStrategy<? super K> hashingStrategy) {
@NotNull HashingStrategy<? super K> hashingStrategy) {
myHashingStrategy = hashingStrategy;
myMap = ContainerUtil.newConcurrentMap(initialCapacity, loadFactor, concurrencyLevel);
myMap = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
}
public interface KeyReference<K, V> extends Getter<K> {
@@ -57,18 +62,18 @@ public class ConcurrentWeakKeySoftValueHashMap<K, V> implements ConcurrentMap<K,
V get();
}
static class WeakKey<K, V> extends WeakReference<K> implements KeyReference<K, V> {
static final class WeakKey<K, V> extends WeakReference<K> implements KeyReference<K, V> {
private final int myHash; // Hash code of the key, stored here since the key may be tossed by the GC
private final TObjectHashingStrategy<? super K> myStrategy;
private final HashingStrategy<? super K> myStrategy;
@NotNull private final ValueReference<K, V> myValueReference;
WeakKey(@NotNull K k,
@NotNull ValueReference<K, V> valueReference,
@NotNull TObjectHashingStrategy<? super K> strategy,
@NotNull HashingStrategy<? super K> strategy,
@NotNull ReferenceQueue<? super K> queue) {
super(k, queue);
myValueReference = valueReference;
myHash = strategy.computeHashCode(k);
myHash = strategy.hashCode(k);
myStrategy = strategy;
}
@@ -124,7 +129,7 @@ public class ConcurrentWeakKeySoftValueHashMap<K, V> implements ConcurrentMap<K,
@NotNull
KeyReference<K,V> createKeyReference(@NotNull K k, @NotNull final V v) {
final ValueReference<K, V> valueReference = createValueReference(v, myValueQueue);
WeakKey<K, V> keyReference = new WeakKey<>(k, valueReference, myHashingStrategy, myKeyQueue);
KeyReference<K,V> keyReference = new WeakKey<>(k, valueReference, myHashingStrategy, myKeyQueue);
if (valueReference instanceof SoftValue) {
((SoftValue<K, V>)valueReference).myKeyReference = keyReference;
}
@@ -197,7 +202,7 @@ public class ConcurrentWeakKeySoftValueHashMap<K, V> implements ConcurrentMap<K,
K key = (K)o;
//noinspection unchecked
HardKey<K,V> hardKey = (HardKey<K, V>)HARD_KEY.get();
hardKey.set(key, myHashingStrategy.computeHashCode(key));
hardKey.set(key, myHashingStrategy.hashCode(key));
return hardKey;
}
@@ -1,9 +1,7 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import com.intellij.util.ObjectUtils;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -15,11 +13,11 @@ import java.lang.ref.WeakReference;
* Null values are NOT allowed
* Use {@link ContainerUtil#createConcurrentWeakKeyWeakValueMap()} to create this
*/
class ConcurrentWeakKeyWeakValueHashMap<K, V> extends ConcurrentWeakKeySoftValueHashMap<K,V> {
final class ConcurrentWeakKeyWeakValueHashMap<K, V> extends ConcurrentWeakKeySoftValueHashMap<K,V> {
ConcurrentWeakKeyWeakValueHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull final TObjectHashingStrategy<? super K> hashingStrategy) {
@NotNull final HashingStrategy<? super K> hashingStrategy) {
super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
@@ -411,15 +411,6 @@ public class ContainerUtil {
return new THashSet<>(Arrays.asList(elements), strategy);
}
/**
* @deprecated Use {@link HashSet}.
*/
@Contract(pure = true)
@Deprecated
public static @NotNull <T> THashSet<T> newTroveSet(@NotNull TObjectHashingStrategy<T> strategy, @NotNull Collection<? extends T> elements) {
return new THashSet<>(elements, strategy);
}
/**
* @deprecated Use {@link THashSet#THashSet(Collection)}
*/
@@ -429,24 +420,6 @@ public class ContainerUtil {
return new THashSet<>(elements);
}
/**
* @deprecated Use {@link it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet}.
*/
@Deprecated
@Contract(pure = true)
public static @NotNull <K> THashSet<K> newIdentityTroveSet() {
return new THashSet<>(identityStrategy());
}
/**
* @deprecated Use {@link it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet}.
*/
@Deprecated
@Contract(pure = true)
public static @NotNull <K> THashSet<K> newIdentityTroveSet(@NotNull Collection<? extends K> collection) {
return new THashSet<>(collection, identityStrategy());
}
/**
* @deprecated Use {@link it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap}
*/
@@ -2351,15 +2324,6 @@ public class ContainerUtil {
}
}
/**
* @return read-only set consisting of the only element o
*/
@Contract(pure = true)
public static @NotNull <T> Set<T> singleton(final T o, final @NotNull TObjectHashingStrategy<T> strategy) {
return strategy == canonicalStrategy() ? new SingletonSet<>(o) : SingletonSet.withCustomStrategy(o, strategy);
}
/**
* @return read-only list consisting of the elements from all of the collections
*/
@@ -2660,41 +2624,34 @@ public class ContainerUtil {
}
@Contract(value = "_,_,_,_ -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
final @NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
final @NotNull HashingStrategy<? super K> hashingStrategy) {
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentSoftKeySoftValueMap() {
return createConcurrentSoftKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), canonicalStrategy());
}
@Contract(value = "_,_,_,_ -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentSoftKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
final @NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new ConcurrentSoftKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftKeySoftValueMap() {
return new ConcurrentSoftKeySoftValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeySoftValueMap() {
return createConcurrentWeakKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), canonicalStrategy());
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeyWeakValueMap() {
return createConcurrentWeakKeyWeakValueMap(canonicalStrategy());
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
}
@ApiStatus.Internal
@Contract(value = "_ -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeyWeakValueMap(@NotNull TObjectHashingStrategy<? super K> strategy) {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(),
strategy);
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeyWeakValueMap(@NotNull HashingStrategy<? super K> strategy) {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), strategy);
}
@Contract(value = " -> new", pure = true)
@@ -2712,25 +2669,44 @@ public class ContainerUtil {
return new ConcurrentWeakHashMap<>(0.75f);
}
@ApiStatus.Internal
@Contract(value = "_,_,_,_ -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentSoftMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull HashingStrategy<? super K> hashingStrategy) {
return new ConcurrentSoftHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
@Contract(value = "_,_,_,_ -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
public static @NotNull <K> HashingStrategy<K> createHashingStrategy(@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new HashingStrategy<K>() {
@Override
public int hashCode(@Nullable K object) {
return hashingStrategy.computeHashCode(object);
}
@Override
public boolean equals(@Nullable K o1, @Nullable K o2) {
return hashingStrategy.equals(o1, o2);
}
};
}
/**
* @deprecated Use {@link CollectionFactory#createConcurrentWeakMap(int, float, int)}
* or {@link CollectionFactory#createConcurrentWeakIdentityMap()} (int, float, int)}.
*/
@Deprecated
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, createHashingStrategy(hashingStrategy));
}
@Contract(value = "_ -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakMap(@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new ConcurrentWeakHashMap<>(hashingStrategy);
return new ConcurrentWeakHashMap<>(createHashingStrategy(hashingStrategy));
}
/**
@@ -3003,7 +2979,7 @@ public class ContainerUtil {
*/
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> Map<K,V> createSoftValueMap() {
return new SoftValueHashMap<>(canonicalStrategy());
return new SoftValueHashMap<>();
}
/**
@@ -3014,7 +2990,7 @@ public class ContainerUtil {
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> Map<K,V> createWeakValueMap() {
//noinspection deprecation
return new WeakValueHashMap<>(canonicalStrategy());
return new WeakValueHashMap<>();
}
/**
@@ -3029,7 +3005,7 @@ public class ContainerUtil {
}
@Contract(value = "_ -> new", pure = true)
public static @NotNull <K,V> Map<K,V> createSoftMap(@NotNull TObjectHashingStrategy<? super K> strategy) {
static @NotNull <K,V> Map<K,V> createSoftMap(@NotNull HashingStrategy<? super K> strategy) {
//noinspection deprecation
return new SoftHashMap<>(strategy);
}
@@ -3046,11 +3022,12 @@ public class ContainerUtil {
@Contract(value = "_ -> new", pure = true)
public static @NotNull <K,V> Map<K,V> createWeakMap(int initialCapacity) {
return createWeakMap(initialCapacity, 0.8f, canonicalStrategy());
//noinspection deprecation
return new WeakHashMap<>(initialCapacity, 0.8f, HashingStrategy.canonical());
}
@Contract(value = "_, _, _ -> new", pure = true)
public static @NotNull <K,V> Map<K,V> createWeakMap(int initialCapacity, float loadFactor, @NotNull TObjectHashingStrategy<? super K> strategy) {
public static @NotNull <K,V> Map<K,V> createWeakMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy<? super K> strategy) {
//noinspection deprecation
return new WeakHashMap<>(initialCapacity, loadFactor, strategy);
}
@@ -0,0 +1,52 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@ApiStatus.Internal
public interface HashingStrategy<T> {
int hashCode(@Nullable T object);
boolean equals(@Nullable T o1, @Nullable T o2);
static <T> HashingStrategy<T> canonical() {
//noinspection unchecked
return (HashingStrategy<T>)CanonicalHashingStrategy.INSTANCE;
}
static <T> HashingStrategy<T> identity() {
//noinspection unchecked
return (HashingStrategy<T>)IdentityHashingStrategy.INSTANCE;
}
}
final class CanonicalHashingStrategy<T> implements HashingStrategy<T> {
static final HashingStrategy<?> INSTANCE = new CanonicalHashingStrategy<>();
@Override
public int hashCode(T value) {
return Objects.hashCode(value);
}
@Override
public boolean equals(T o1, T o2) {
return Objects.equals(o1, o2);
}
}
final class IdentityHashingStrategy<T> implements HashingStrategy<T> {
static final HashingStrategy<?> INSTANCE = new IdentityHashingStrategy<>();
@Override
public int hashCode(T value) {
return System.identityHashCode(value);
}
@Override
public boolean equals(T o1, T o2) {
return o1 == o2;
}
}
@@ -18,17 +18,17 @@ abstract class RefHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
private final ReferenceQueue<K> myReferenceQueue = new ReferenceQueue<>();
private final HardKey myHardKeyInstance = new HardKey(); // "singleton"
@NotNull
private final TObjectHashingStrategy<? super K> myStrategy;
private final HashingStrategy<? super K> myStrategy;
private Set<Entry<K, V>> entrySet;
private boolean processingQueue;
RefHashMap(int initialCapacity, float loadFactor, @NotNull final TObjectHashingStrategy<? super K> strategy) {
RefHashMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy<? super K> strategy) {
myStrategy = strategy;
myMap = new MyMap(initialCapacity, loadFactor);
}
RefHashMap(int initialCapacity, float loadFactor) {
this(initialCapacity, loadFactor, ContainerUtil.canonicalStrategy());
this(initialCapacity, loadFactor, HashingStrategy.canonical());
}
RefHashMap(int initialCapacity) {
@@ -44,11 +44,11 @@ abstract class RefHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
putAll(t);
}
RefHashMap(@NotNull final TObjectHashingStrategy<? super K> hashingStrategy) {
RefHashMap(@NotNull HashingStrategy<? super K> hashingStrategy) {
this(4, 0.8f, hashingStrategy);
}
static <K> boolean keyEqual(K k1, K k2, TObjectHashingStrategy<? super K> strategy) {
static <K> boolean keyEqual(K k1, K k2, HashingStrategy<? super K> strategy) {
return k1 == k2 || strategy.equals(k1, k2);
}
@@ -118,7 +118,7 @@ abstract class RefHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
}
@NotNull
protected abstract <T> Key<T> createKey(@NotNull T k, @NotNull TObjectHashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q);
protected abstract <T> Key<T> createKey(@NotNull T k, @NotNull HashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q);
private class HardKey implements Key<K> {
private K myObject;
@@ -131,7 +131,7 @@ abstract class RefHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
private void set(@NotNull K object) {
myObject = object;
myHash = myStrategy.computeHashCode(object);
myHash = myStrategy.hashCode(object);
}
private void clear() {
@@ -257,9 +257,9 @@ abstract class RefHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
private final Entry<?, V> ent;
private final K key; // Strong reference to key, so that the GC will leave it alone as long as this Entry exists
private final int myKeyHashCode;
@NotNull private final TObjectHashingStrategy<? super K> myStrategy;
@NotNull private final HashingStrategy<? super K> myStrategy;
private MyEntry(@NotNull Entry<?, V> ent, @NotNull K key, int keyHashCode, @NotNull TObjectHashingStrategy<? super K> strategy) {
private MyEntry(@NotNull Entry<?, V> ent, @NotNull K key, int keyHashCode, @NotNull HashingStrategy<? super K> strategy) {
this.ent = ent;
this.key = key;
myKeyHashCode = keyHashCode;
@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import com.intellij.openapi.util.Getter;
@@ -10,11 +10,12 @@ import org.jetbrains.annotations.Debug;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import java.util.*;
@Debug.Renderer(text = "\"size = \" + size()", hasChildren = "!isEmpty()", childrenArray = "childrenArray()")
abstract class RefValueHashMap<K,V> implements Map<K,V>{
private final Map<K,MyReference<K,V>> myMap;
abstract class RefValueHashMap<K, V> implements Map<K, V> {
private final Map<K, MyReference<K, V>> myMap;
private final ReferenceQueue<V> myQueue = new ReferenceQueue<>();
@NotNull
@@ -33,7 +34,7 @@ abstract class RefValueHashMap<K,V> implements Map<K,V>{
}
RefValueHashMap() {
myMap = new THashMap<>();
myMap = new HashMap<>();
}
RefValueHashMap(@NotNull TObjectHashingStrategy<K> strategy) {
@@ -94,7 +95,7 @@ abstract class RefValueHashMap<K,V> implements Map<K,V>{
@Override
public boolean isEmpty() {
return myMap.isEmpty();
return myMap.isEmpty();
}
@Override
@@ -1,40 +1,25 @@
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import com.intellij.util.PairProcessor;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.BiPredicate;
/**
* @author peter
*/
public class SoftArrayHashMap<T,V> implements Cloneable {
public final class SoftArrayHashMap<T,V> implements Cloneable {
private Map<T, SoftArrayHashMap<T,V>> myContinuationMap;
private Map<T,V> myValuesMap;
private V myEmptyValue;
private final TObjectHashingStrategy<T> myStrategy;
private final HashingStrategy<T> myStrategy;
public SoftArrayHashMap() {
this(ContainerUtil.canonicalStrategy());
this(HashingStrategy.canonical());
}
public SoftArrayHashMap(@NotNull TObjectHashingStrategy<T> strategy) {
private SoftArrayHashMap(@NotNull HashingStrategy<T> strategy) {
myStrategy = strategy;
}
@@ -60,10 +45,12 @@ public class SoftArrayHashMap<T,V> implements Cloneable {
return get(key, 0);
}
public boolean processLeafEntries(final PairProcessor<T, V> processor) {
public boolean processLeafEntries(@NotNull BiPredicate<T, V> processor) {
if (myValuesMap != null) {
for (T t : myValuesMap.keySet()) {
if (!processor.process(t, myValuesMap.get(t))) return false;
if (!processor.test(t, myValuesMap.get(t))) {
return false;
}
}
}
if (myContinuationMap != null) {
@@ -78,12 +65,14 @@ public class SoftArrayHashMap<T,V> implements Cloneable {
final T key = array[index];
if (index == array.length - 1) {
if (myValuesMap == null) {
myValuesMap = ContainerUtil.createSoftMap(myStrategy);
//noinspection deprecation
myValuesMap = new SoftHashMap<>(myStrategy);
}
myValuesMap.put(key, value);
} else {
if (myContinuationMap == null) {
myContinuationMap = ContainerUtil.createSoftMap(myStrategy);
//noinspection deprecation
myContinuationMap = new SoftHashMap<>(myStrategy);
}
SoftArrayHashMap<T, V> softArrayHashMap = myContinuationMap.get(key);
if (softArrayHashMap == null) {
@@ -121,8 +110,9 @@ public class SoftArrayHashMap<T,V> implements Cloneable {
}
private <X> Map<T, X> copyMap(final Map<T, X> map) {
final Map<T, X> copy = ContainerUtil.createSoftMap();
for (final Map.Entry<T, X> entry : map.entrySet()) {
//noinspection deprecation
Map<T, X> copy = new SoftHashMap<>(map.size());
for (Map.Entry<T, X> entry : map.entrySet()) {
copy.put(entry.getKey(), entry.getValue());
}
return copy;
@@ -3,7 +3,6 @@ package com.intellij.util.containers;
import com.intellij.reference.SoftReference;
import com.intellij.util.DeprecatedMethodException;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -23,7 +22,7 @@ public final class SoftHashMap<K,V> extends RefHashMap<K,V> {
* Null keys are NOT allowed
* Null values are allowed
*
* @deprecated use {@link ContainerUtil#createSoftMap()} instead
* @deprecated use {@link CollectionFactory#createSoftMap()} instead
*/
@Deprecated
public SoftHashMap() {
@@ -34,25 +33,23 @@ public final class SoftHashMap<K,V> extends RefHashMap<K,V> {
super(initialCapacity);
}
SoftHashMap(@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
SoftHashMap(@NotNull HashingStrategy<? super K> hashingStrategy) {
super(hashingStrategy);
}
@NotNull
@Override
protected <T> Key<T> createKey(@NotNull T k, @NotNull TObjectHashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
protected @NotNull <T> Key<T> createKey(@NotNull T k, @NotNull HashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
return new SoftKey<>(k, strategy, q);
}
private static final class SoftKey<T> extends SoftReference<T> implements Key<T> {
private final int myHash; /* Hash code of key, stored here since the key may be tossed by the GC */
@NotNull private final TObjectHashingStrategy<? super T> myStrategy;
@NotNull private final HashingStrategy<? super T> myStrategy;
private SoftKey(@NotNull T k, @NotNull TObjectHashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
private SoftKey(@NotNull T k, @NotNull HashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
super(k, q);
myStrategy = strategy;
myHash = strategy.computeHashCode(k);
myHash = strategy.hashCode(k);
}
@Override
@@ -1,22 +1,7 @@
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import com.intellij.reference.SoftReference;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -40,11 +25,6 @@ final class SoftValueHashMap<K,V> extends RefValueHashMap<K,V>{
}
}
SoftValueHashMap(@NotNull TObjectHashingStrategy<K> strategy) {
super(strategy);
}
@Override
protected MyReference<K, V> createReference(@NotNull K key, V value, @NotNull ReferenceQueue<? super V> queue) {
return new MySoftReference<>(key, value, queue);
@@ -2,7 +2,6 @@
package com.intellij.util.containers;
import com.intellij.util.DeprecatedMethodException;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -19,37 +18,37 @@ import java.lang.ref.WeakReference;
* Do not use this class if you have null keys (shame on you).
* Otherwise it's the same as java.util.WeakHashMap, you are free to use either.
*
* @deprecated use {@link ContainerUtil#createWeakMap()} instead
* @deprecated use {@link CollectionFactory#createWeakMap()} instead
*/
@Deprecated
public final class WeakHashMap<K, V> extends RefHashMap<K, V> {
public WeakHashMap(int initialCapacity) {
super(initialCapacity);
DeprecatedMethodException.report("Use ContainerUtil.createWeakMap() instead");
DeprecatedMethodException.report("Use CollectionFactory.createWeakMap() instead");
}
public WeakHashMap() {
DeprecatedMethodException.report("Use ContainerUtil.createWeakMap() instead");
DeprecatedMethodException.report("Use CollectionFactory.createWeakMap() instead");
}
WeakHashMap(int initialCapacity, float loadFactor, @NotNull TObjectHashingStrategy<? super K> strategy) {
WeakHashMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy<? super K> strategy) {
super(initialCapacity, loadFactor, strategy);
}
@NotNull
@Override
protected <T> Key<T> createKey(@NotNull T k, @NotNull TObjectHashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
protected <T> Key<T> createKey(@NotNull T k, @NotNull HashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
return new WeakKey<>(k, strategy, q);
}
private static final class WeakKey<T> extends WeakReference<T> implements Key<T> {
private final int myHash; // Hashcode of key, stored here since the key may be tossed by the GC
@NotNull private final TObjectHashingStrategy<? super T> myStrategy;
@NotNull private final HashingStrategy<? super T> myStrategy;
private WeakKey(@NotNull T k, @NotNull TObjectHashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
private WeakKey(@NotNull T k, @NotNull HashingStrategy<? super T> strategy, @NotNull ReferenceQueue<? super T> q) {
super(k, q);
myStrategy = strategy;
myHash = strategy.computeHashCode(k);
myHash = strategy.hashCode(k);
}
@Override
@@ -27,7 +27,8 @@ public class WeakInterner<T> extends Interner<T> {
}
public WeakInterner(@NotNull TObjectHashingStrategy<? super T> strategy) {
myMap = ContainerUtil.createConcurrentWeakKeyWeakValueMap(strategy);
myMap = new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(),
ContainerUtil.createHashingStrategy(strategy));
}
@Override
@@ -1,8 +1,6 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.containers;
import com.intellij.util.DeprecatedMethodException;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -33,11 +31,6 @@ public final class WeakValueHashMap<K,V> extends RefValueHashMap<K,V> {
*/
@Deprecated
public WeakValueHashMap() {
DeprecatedMethodException.report("Use ContainerUtil#createWeakValueMap() instead");
}
WeakValueHashMap(@NotNull TObjectHashingStrategy<K> strategy) {
super(strategy);
}
@Override