mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
make FileTypeAssocTable thread-safe to avoid crashes accessing them from background
GitOrigin-RevId: a26c1fc6570229197fbcccc2b60f40e7fa1947ec
This commit is contained in:
committed by
intellij-monorepo-bot
parent
32c292c8e9
commit
463c805fc2
@@ -15,6 +15,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class FileTypeAssocTable<T> {
|
||||
@@ -29,15 +30,11 @@ public final class FileTypeAssocTable<T> {
|
||||
@NotNull Map<? extends CharSequence, ? extends T> exactFileNameAnyCaseMappings,
|
||||
@NotNull Map<String, ? extends T> hashBangMap,
|
||||
@NotNull List<? extends Pair<FileNameMatcher, T>> matchingMappings) {
|
||||
myExtensionMappings = CollectionFactory.createCharSequenceMap(false, Math.max(10, extensionMappings.size()), 0.5f);
|
||||
myExtensionMappings.putAll(extensionMappings);
|
||||
myExactFileNameMappings = CollectionFactory.createCharSequenceMap(true, Math.max(10, exactFileNameMappings.size()), 0.5f);
|
||||
myExactFileNameMappings.putAll(exactFileNameMappings);
|
||||
myExactFileNameAnyCaseMappings = CollectionFactory.createCharSequenceMap(false, Math.max(10, exactFileNameAnyCaseMappings.size()), 0.5f);
|
||||
myExactFileNameAnyCaseMappings.putAll(exactFileNameAnyCaseMappings);
|
||||
myHashBangMap = CollectionFactory.createSmallMemoryFootprintMap(Math.max(10, hashBangMap.size()), 0.5f);
|
||||
myHashBangMap.putAll(hashBangMap);
|
||||
myMatchingMappings = new ArrayList<>(matchingMappings);
|
||||
myExtensionMappings = createCharSequenceConcurrentMap(extensionMappings);
|
||||
myExactFileNameMappings = new ConcurrentHashMap<>(exactFileNameMappings);
|
||||
myExactFileNameAnyCaseMappings = createCharSequenceConcurrentMap(exactFileNameAnyCaseMappings);
|
||||
myHashBangMap = new ConcurrentHashMap<>(hashBangMap);
|
||||
myMatchingMappings = Collections.synchronizedList(new ArrayList<>(matchingMappings));
|
||||
}
|
||||
|
||||
public FileTypeAssocTable() {
|
||||
@@ -75,11 +72,9 @@ public final class FileTypeAssocTable<T> {
|
||||
myMatchingMappings.add(Pair.create(matcher, type));
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
Pair<FileNameMatcher, T> old = myMatchingMappings.get(i);
|
||||
myMatchingMappings.set(i, Pair.create(matcher, type));
|
||||
return Pair.getSecond(old);
|
||||
}
|
||||
Pair<FileNameMatcher, T> old = myMatchingMappings.get(i);
|
||||
myMatchingMappings.set(i, Pair.create(matcher, type));
|
||||
return Pair.getSecond(old);
|
||||
}
|
||||
|
||||
void addHashBangPattern(@NotNull String hashBang, @NotNull T type) {
|
||||
@@ -289,4 +284,11 @@ public final class FileTypeAssocTable<T> {
|
||||
Map<String, T> getInternalRawHashBangPatterns() {
|
||||
return CollectionFactory.createSmallMemoryFootprintMap(myHashBangMap);
|
||||
}
|
||||
|
||||
private static @NotNull <T> Map<CharSequence, T> createCharSequenceConcurrentMap(@NotNull Map<? extends CharSequence, ? extends T> source) {
|
||||
// todo convert to ConcurrentCollectionFactory when it's available in the classpath
|
||||
Map<CharSequence, T> map = CollectionFactory.createCharSequenceMap(false, source.size(), 0.5f);
|
||||
map.putAll(source);
|
||||
return Collections.synchronizedMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +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.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.util.text.Strings;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -26,8 +27,25 @@ public interface HashingStrategy<T> {
|
||||
static @NotNull HashingStrategy<String> caseInsensitive() {
|
||||
return CaseInsensitiveStringHashingStrategy.INSTANCE;
|
||||
}
|
||||
static @NotNull HashingStrategy<CharSequence> caseInsensitiveCharSequence() {
|
||||
return CaseInsensitiveCharSequenceHashingStrategy.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
class CaseInsensitiveCharSequenceHashingStrategy implements HashingStrategy<CharSequence> {
|
||||
static final CaseInsensitiveCharSequenceHashingStrategy INSTANCE = new CaseInsensitiveCharSequenceHashingStrategy();
|
||||
|
||||
@Override
|
||||
public int hashCode(CharSequence object) {
|
||||
return Strings.stringHashCodeInsensitive(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(CharSequence s1, CharSequence s2) {
|
||||
return StringUtil.equalsIgnoreCase(s1, s2);
|
||||
}
|
||||
};
|
||||
|
||||
final class CanonicalHashingStrategy<T> implements HashingStrategy<T> {
|
||||
static final HashingStrategy<?> INSTANCE = new CanonicalHashingStrategy<>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user