mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
extract IntObjectMap/ObjectIntMap interfaces to generalize custom maps
This commit is contained in:
@@ -53,8 +53,8 @@ import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ConcurrentBitSet;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import gnu.trove.*;
|
||||
@@ -451,7 +451,7 @@ public class RefResolveServiceImpl extends RefResolveService implements Runnable
|
||||
assert !myApplication.isDispatchThread();
|
||||
final int resolvedInPreviousBatch = this.resolvedInPreviousBatch;
|
||||
final int totalSize = files.size() + resolvedInPreviousBatch;
|
||||
final ConcurrentIntObjectMap<int[]> fileToForwardIds = ContainerUtil.createConcurrentIntObjectMap();
|
||||
final IntObjectMap<int[]> fileToForwardIds = ContainerUtil.createConcurrentIntObjectMap();
|
||||
final Set<VirtualFile> toProcess = Collections.synchronizedSet(files);
|
||||
indicator.setIndeterminate(false);
|
||||
ProgressIndicatorUtils.forceWriteActionPriority(indicator, (Disposable)indicator);
|
||||
@@ -652,11 +652,11 @@ public class RefResolveServiceImpl extends RefResolveService implements Runnable
|
||||
return forwardIds;
|
||||
}
|
||||
|
||||
private void storeIds(@NotNull ConcurrentIntObjectMap<int[]> fileToForwardIds) {
|
||||
private void storeIds(@NotNull IntObjectMap<int[]> fileToForwardIds) {
|
||||
int forwardSize = 0;
|
||||
int backwardSize = 0;
|
||||
final TIntObjectHashMap<TIntArrayList> fileToBackwardIds = new TIntObjectHashMap<>(fileToForwardIds.size());
|
||||
for (ConcurrentIntObjectMap.IntEntry<int[]> entry : fileToForwardIds.entries()) {
|
||||
for (IntObjectMap.Entry<int[]> entry : fileToForwardIds.entries()) {
|
||||
int fileId = entry.getKey();
|
||||
int[] forwardIds = entry.getValue();
|
||||
forwardSize += forwardIds.length;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.jetbrains.io.jsonRpc;
|
||||
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.channel.Channel;
|
||||
@@ -13,12 +13,12 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.AsyncPromise;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class Client extends UserDataHolderBase {
|
||||
protected final Channel channel;
|
||||
|
||||
final ConcurrentIntObjectMap<AsyncPromise<Object>> messageCallbackMap = ContainerUtil.createConcurrentIntObjectMap();
|
||||
final IntObjectMap<AsyncPromise<Object>> messageCallbackMap = ContainerUtil.createConcurrentIntObjectMap();
|
||||
|
||||
protected Client(@NotNull Channel channel) {
|
||||
this.channel = channel;
|
||||
@@ -55,10 +55,10 @@ public abstract class Client extends UserDataHolderBase {
|
||||
|
||||
final void rejectAsyncResults(@NotNull ExceptionHandler exceptionHandler) {
|
||||
if (!messageCallbackMap.isEmpty()) {
|
||||
Enumeration<AsyncPromise<Object>> elements = messageCallbackMap.elements();
|
||||
while (elements.hasMoreElements()) {
|
||||
Collection<AsyncPromise<Object>> elements = messageCallbackMap.values();
|
||||
for (AsyncPromise<Object> element : elements) {
|
||||
try {
|
||||
elements.nextElement().setError("rejected");
|
||||
element.setError("rejected");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
exceptionHandler.exceptionCaught(e);
|
||||
@@ -69,9 +69,9 @@ public abstract class Client extends UserDataHolderBase {
|
||||
|
||||
private static final class ChannelFutureAwarePromise<T> extends AsyncPromise<T> implements ChannelFutureListener {
|
||||
private final int messageId;
|
||||
private final ConcurrentIntObjectMap<?> messageCallbackMap;
|
||||
private final IntObjectMap<?> messageCallbackMap;
|
||||
|
||||
public ChannelFutureAwarePromise(int messageId, ConcurrentIntObjectMap<?> messageCallbackMap) {
|
||||
public ChannelFutureAwarePromise(int messageId, IntObjectMap<?> messageCallbackMap) {
|
||||
this.messageId = messageId;
|
||||
this.messageCallbackMap = messageCallbackMap;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.intellij.openapi.util;
|
||||
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -37,16 +37,16 @@ public interface Iconable {
|
||||
Icon getIcon(@IconFlags int flags);
|
||||
|
||||
class LastComputedIcon {
|
||||
private static final Key<ConcurrentIntObjectMap<Icon>> LAST_COMPUTED_ICON = Key.create("lastComputedIcon");
|
||||
private static final Key<IntObjectMap<Icon>> LAST_COMPUTED_ICON = Key.create("lastComputedIcon");
|
||||
|
||||
@Nullable
|
||||
public static Icon get(@NotNull UserDataHolder holder, int flags) {
|
||||
ConcurrentIntObjectMap<Icon> map = holder.getUserData(LAST_COMPUTED_ICON);
|
||||
IntObjectMap<Icon> map = holder.getUserData(LAST_COMPUTED_ICON);
|
||||
return map == null ? null : map.get(flags);
|
||||
}
|
||||
|
||||
public static void put(@NotNull UserDataHolder holder, Icon icon, int flags) {
|
||||
ConcurrentIntObjectMap<Icon> map = holder.getUserData(LAST_COMPUTED_ICON);
|
||||
IntObjectMap<Icon> map = holder.getUserData(LAST_COMPUTED_ICON);
|
||||
if (icon == null) {
|
||||
if (map != null) {
|
||||
map.remove(flags);
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import gnu.trove.TObjectIntProcedure;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -32,8 +31,8 @@ import java.io.*;
|
||||
* Date: Feb 12, 2008
|
||||
*/
|
||||
public class ID<K, V> extends IndexId<K,V> {
|
||||
private static final ConcurrentIntObjectMap<ID> ourRegistry = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private static final TObjectIntHashMap<String> ourNameToIdRegistry = new TObjectIntHashMap<String>();
|
||||
private static final IntObjectMap<ID> ourRegistry = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private static final TObjectIntHashMap<String> ourNameToIdRegistry = new TObjectIntHashMap<>();
|
||||
static final int MAX_NUMBER_OF_INDICES = Short.MAX_VALUE;
|
||||
|
||||
private final short myUniqueId;
|
||||
@@ -41,30 +40,23 @@ public class ID<K, V> extends IndexId<K,V> {
|
||||
static {
|
||||
final File indices = getEnumFile();
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(new FileReader(indices));
|
||||
TObjectIntHashMap<String> nameToIdRegistry = new TObjectIntHashMap<String>();
|
||||
try {
|
||||
TObjectIntHashMap<String> nameToIdRegistry = new TObjectIntHashMap<>();
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(indices))) {
|
||||
int cnt = 0;
|
||||
do {
|
||||
cnt++;
|
||||
final String name = reader.readLine();
|
||||
if (name == null) break;
|
||||
nameToIdRegistry.put(name, cnt);
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
cnt++;
|
||||
final String name = reader.readLine();
|
||||
if (name == null) break;
|
||||
nameToIdRegistry.put(name, cnt);
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
synchronized (ourNameToIdRegistry) {
|
||||
ourNameToIdRegistry.ensureCapacity(nameToIdRegistry.size());
|
||||
nameToIdRegistry.forEachEntry(new TObjectIntProcedure<String>() {
|
||||
@Override
|
||||
public boolean execute(String name, int index) {
|
||||
ourNameToIdRegistry.put(name, index);
|
||||
return true;
|
||||
}
|
||||
nameToIdRegistry.forEachEntry((name, index) -> {
|
||||
ourNameToIdRegistry.put(name, index);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -113,25 +105,18 @@ public class ID<K, V> extends IndexId<K,V> {
|
||||
private static void writeEnumFile() {
|
||||
try {
|
||||
final File f = getEnumFile();
|
||||
final BufferedWriter w = new BufferedWriter(new FileWriter(f));
|
||||
try {
|
||||
try (BufferedWriter w = new BufferedWriter(new FileWriter(f))) {
|
||||
final String[] names = new String[ourNameToIdRegistry.size()];
|
||||
|
||||
ourNameToIdRegistry.forEachEntry(new TObjectIntProcedure<String>() {
|
||||
@Override
|
||||
public boolean execute(final String key, final int value) {
|
||||
names[value - 1] = key;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
ourNameToIdRegistry.forEachEntry((key, value) -> {
|
||||
names[value - 1] = key;
|
||||
return true;
|
||||
});
|
||||
|
||||
for (String name : names) {
|
||||
w.write(name);
|
||||
w.newLine();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
w.close();
|
||||
w.write(name);
|
||||
w.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -142,7 +127,7 @@ public class ID<K, V> extends IndexId<K,V> {
|
||||
@NotNull
|
||||
public static <K, V> ID<K, V> create(@NonNls @NotNull String name) {
|
||||
final ID<K, V> found = findByName(name);
|
||||
return found != null ? found : new ID<K, V>(name);
|
||||
return found != null ? found : new ID<>(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -18,8 +18,8 @@ package com.intellij.openapi.module.impl.scopes;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.impl.ModuleScopeProvider;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class ModuleScopeProviderImpl implements ModuleScopeProvider {
|
||||
private final Module myModule;
|
||||
private final ConcurrentIntObjectMap<GlobalSearchScope> myScopeCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final IntObjectMap<GlobalSearchScope> myScopeCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private ModuleWithDependentsTestScope myModuleTestsWithDependentsScope;
|
||||
|
||||
public ModuleScopeProviderImpl(@NotNull Module module) {
|
||||
|
||||
@@ -69,8 +69,8 @@ import com.intellij.ui.ReplacePromptDialog;
|
||||
import com.intellij.usages.ChunkExtractor;
|
||||
import com.intellij.usages.UsageViewManager;
|
||||
import com.intellij.usages.impl.SyntaxHighlighterOverEditorHighlighter;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.containers.Predicate;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
@@ -786,7 +786,7 @@ public class FindManagerImpl extends FindManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static final ConcurrentIntObjectMap<Boolean> ourReportedPatterns = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private static final IntObjectMap<Boolean> ourReportedPatterns = ContainerUtil.createConcurrentIntObjectMap();
|
||||
|
||||
private static Matcher compileRegExp(FindModel model, CharSequence text) {
|
||||
Pattern pattern = model.compileRegExp();
|
||||
|
||||
@@ -34,8 +34,8 @@ import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -118,7 +118,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
protected RootIndex.InfoCache createRootInfoCache() {
|
||||
return new RootIndex.InfoCache() {
|
||||
// Upsource can't use int-mapping because different files may have the same id there
|
||||
private final ConcurrentIntObjectMap<DirectoryInfo> myInfoCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final IntObjectMap<DirectoryInfo> myInfoCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
@Override
|
||||
public void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info) {
|
||||
myInfoCache.put(((NewVirtualFile)dir).getId(), info);
|
||||
|
||||
@@ -28,8 +28,8 @@ import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -271,7 +271,7 @@ public class SemServiceImpl extends SemService{
|
||||
}
|
||||
|
||||
private static class SemCacheChunk {
|
||||
private final ConcurrentIntObjectMap<List<SemElement>> map = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final IntObjectMap<List<SemElement>> map = ContainerUtil.createConcurrentIntObjectMap();
|
||||
|
||||
public List<SemElement> getSemElements(SemKey<?> key) {
|
||||
return map.get(key.getUniqueId());
|
||||
|
||||
@@ -75,8 +75,8 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.SerializationManagerEx;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.gist.GistManager;
|
||||
import com.intellij.util.gist.GistManagerImpl;
|
||||
import com.intellij.util.indexing.impl.InvertedIndexValueIterator;
|
||||
@@ -1830,7 +1830,7 @@ public class FileBasedIndexImpl extends FileBasedIndex implements BaseComponent,
|
||||
}
|
||||
|
||||
private final class ChangedFilesCollector extends IndexedFilesListener {
|
||||
private final ConcurrentIntObjectMap<VirtualFile> myFilesToUpdate = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final IntObjectMap<VirtualFile> myFilesToUpdate = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final VfsEventsMerger myVfsEventsMerger = new VfsEventsMerger();
|
||||
private final Phaser myWorkersFinishedSync = new Phaser() {
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,8 @@ import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
|
||||
import com.intellij.psi.stubs.StubIndexKey;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import gnu.trove.TObjectLongHashMap;
|
||||
import gnu.trove.TObjectLongProcedure;
|
||||
@@ -340,7 +340,7 @@ public class IndexingStamp {
|
||||
}
|
||||
}
|
||||
|
||||
private static final ConcurrentIntObjectMap<Timestamps> myTimestampsCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private static final IntObjectMap<IndexingStamp.Timestamps> myTimestampsCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private static final BlockingQueue<Integer> ourFinishedFiles = new ArrayBlockingQueue<>(100);
|
||||
|
||||
public static long getIndexStamp(int fileId, ID<?, ?> indexName) {
|
||||
|
||||
@@ -26,8 +26,8 @@ import com.intellij.openapi.vfs.VirtualFileWithId;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -40,7 +40,7 @@ import java.util.List;
|
||||
* @author gregsh
|
||||
*/
|
||||
public final class LightDirectoryIndex<T> {
|
||||
private final ConcurrentIntObjectMap<T> myInfoCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final IntObjectMap<T> myInfoCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final T myDefValue;
|
||||
private final Consumer<LightDirectoryIndex<T>> myInitializer;
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ package com.intellij.util.indexing;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -87,7 +87,7 @@ public class VfsEventsMerger {
|
||||
return myChangeInfos.values().stream().map(ChangeInfo::getFile);
|
||||
}
|
||||
|
||||
private final ConcurrentIntObjectMap<ChangeInfo> myChangeInfos = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final IntObjectMap<VfsEventsMerger.ChangeInfo> myChangeInfos = ContainerUtil.createConcurrentIntObjectMap();
|
||||
|
||||
private static final short FILE_ADDED = 1;
|
||||
private static final short FILE_REMOVED = 2;
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.util.concurrency.AtomicFieldUpdater;
|
||||
import com.intellij.util.containers.ConcurrentBitSet;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.keyFMap.KeyFMap;
|
||||
import com.intellij.util.text.CharSequenceHashingStrategy;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -84,7 +85,7 @@ public class VfsData {
|
||||
private static final ConcurrentIntObjectMap<Segment> ourSegments = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private static final ConcurrentBitSet ourInvalidatedIds = new ConcurrentBitSet();
|
||||
private static TIntHashSet ourDyingIds = new TIntHashSet();
|
||||
private static final ConcurrentIntObjectMap<VirtualDirectoryImpl> ourChangedParents = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private static final IntObjectMap<VirtualDirectoryImpl> ourChangedParents = ContainerUtil.createConcurrentIntObjectMap();
|
||||
|
||||
static {
|
||||
ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() {
|
||||
|
||||
@@ -30,8 +30,8 @@ import com.intellij.openapi.vfs.newvfs.impl.FileNameCache;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.IntArrayList;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
import com.intellij.util.io.storage.*;
|
||||
@@ -1127,7 +1127,7 @@ public class FSRecords {
|
||||
|
||||
// returns (list of id and its parent ids up to and including id of already cached parent, that already cached parent)
|
||||
@NotNull
|
||||
static Pair<TIntArrayList, VirtualFileSystemEntry> getParents(int id, @NotNull ConcurrentIntObjectMap<VirtualFileSystemEntry> idCache) {
|
||||
static Pair<TIntArrayList, VirtualFileSystemEntry> getParents(int id, @NotNull IntObjectMap<VirtualFileSystemEntry> idCache) {
|
||||
TIntArrayList ids = new TIntArrayList(10);
|
||||
r.lock();
|
||||
VirtualFileSystemEntry cached = null;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.vfs.newvfs.persistent;
|
||||
|
||||
import com.intellij.concurrency.ConcurrentCollectionFactory;
|
||||
import com.intellij.concurrency.JobSchedulerImpl;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
@@ -41,14 +42,17 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.UriUtil;
|
||||
import com.intellij.concurrency.ConcurrentCollectionFactory;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.io.ReplicatorInputStream;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import gnu.trove.*;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -67,7 +71,8 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
|
||||
private final Map<String, VirtualFileSystemEntry> myRoots =
|
||||
ConcurrentCollectionFactory.createMap(10, 0.4f, JobSchedulerImpl.CORES_COUNT, FileUtil.PATH_HASHING_STRATEGY);
|
||||
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myRootsById = ContainerUtil.createConcurrentIntObjectMap(10, 0.4f, JobSchedulerImpl.CORES_COUNT);
|
||||
private final IntObjectMap<VirtualFileSystemEntry>
|
||||
myRootsById = ContainerUtil.createConcurrentIntObjectMap(10, 0.4f, JobSchedulerImpl.CORES_COUNT);
|
||||
|
||||
// FS roots must be in this map too. findFileById() relies on this.
|
||||
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myIdToDirCache = ContainerUtil.createConcurrentIntObjectSoftValueMap();
|
||||
|
||||
@@ -60,6 +60,12 @@ public class ContainerUtilCollectionsTest {
|
||||
checkClearsEventuallyAfterGCPressure(map, ()->map.put(new Object(), new Object()));
|
||||
checkClearsEventuallyAfterGCPressure(map, ()->map.put(new Object(), this));
|
||||
}
|
||||
private void checkKeyTossedEventually(ObjectIntMap<Object> map) {
|
||||
checkClearsEventuallyAfterGCPressure(map, ()->map.put(new Object(), 0));
|
||||
}
|
||||
private void checkValueTossedEventually(IntObjectMap<Object> map) {
|
||||
checkClearsEventuallyAfterGCPressure(map, ()->map.put(0, new Object()));
|
||||
}
|
||||
private void checkValueTossedEventually(Map<Object, Object> map) {
|
||||
checkClearsEventuallyAfterGCPressure(map, ()->map.put(new Object(), new Object()));
|
||||
checkClearsEventuallyAfterGCPressure(map, ()->map.put(this, new Object()));
|
||||
@@ -172,6 +178,58 @@ public class ContainerUtilCollectionsTest {
|
||||
assertNull(map.get(strong));
|
||||
}
|
||||
|
||||
private static final int RANDOM_INT = 987654321;
|
||||
private void checkClearsEventuallyAfterGCPressure(ObjectIntMap<Object> map, @NotNull Runnable put) {
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
put.run();
|
||||
strong = new Object();
|
||||
//noinspection SizeReplaceableByIsEmpty
|
||||
do {
|
||||
map.put(strong, RANDOM_INT); // to run processQueues();
|
||||
assertFalse(map.isEmpty());
|
||||
map.remove(strong);
|
||||
assertEquals(0, map.get(strong));
|
||||
|
||||
GCUtil.tryGcSoftlyReachableObjects();
|
||||
System.gc();
|
||||
}
|
||||
while (map.size() != 0);
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
map.put(this, RANDOM_INT);
|
||||
assertEquals(1, map.size());
|
||||
map.clear();
|
||||
assertEquals(0, map.size());
|
||||
assertEquals(0, map.get(strong));
|
||||
}
|
||||
|
||||
private void checkClearsEventuallyAfterGCPressure(IntObjectMap<Object> map, @NotNull Runnable put) {
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
put.run();
|
||||
|
||||
strong = new Object();
|
||||
//noinspection SizeReplaceableByIsEmpty
|
||||
do {
|
||||
map.put(RANDOM_INT, strong); // to run processQueues();
|
||||
assertFalse(map.isEmpty());
|
||||
map.remove(RANDOM_INT);
|
||||
assertNull(map.get(RANDOM_INT));
|
||||
|
||||
GCUtil.tryGcSoftlyReachableObjects();
|
||||
System.gc();
|
||||
}
|
||||
while (map.size() != 0);
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
map.put(RANDOM_INT, this);
|
||||
assertEquals(1, map.size());
|
||||
map.clear();
|
||||
assertEquals(0, map.size());
|
||||
assertNull(map.get(RANDOM_INT));
|
||||
}
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testSoftMapCustomStrategy() {
|
||||
Map<String, String> map = ContainerUtil.createSoftMap(IGNORE_CASE_WITH_CRAZY_HASH_STRATEGY);
|
||||
@@ -312,7 +370,7 @@ public class ContainerUtilCollectionsTest {
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testConcurrentIntObjectHashMap() {
|
||||
ConcurrentIntObjectMap<Object> map = ContainerUtil.createConcurrentIntObjectMap();
|
||||
IntObjectMap<Object> map = ContainerUtil.createConcurrentIntObjectMap();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
Object prev = map.put(i, i);
|
||||
assertNull(prev);
|
||||
@@ -500,4 +558,15 @@ public class ContainerUtilCollectionsTest {
|
||||
set.add(this);
|
||||
assertEquals(1, set.size());
|
||||
}
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testWeakKeyIntValueMapTossed() {
|
||||
ObjectIntMap<Object> map = ContainerUtil.createWeakKeyIntValueMap();
|
||||
checkKeyTossedEventually(map);
|
||||
}
|
||||
@Test(timeout = TIMEOUT)
|
||||
public void testIntKeyWeakValueMapTossed() {
|
||||
IntObjectMap<Object> map = ContainerUtil.createIntKeyWeakValueMap();
|
||||
checkValueTossedEventually(map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package com.intellij.openapi.util;
|
||||
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -31,12 +31,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* @author max
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
|
||||
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
|
||||
public class Key<T> {
|
||||
private static final AtomicInteger ourKeysCounter = new AtomicInteger();
|
||||
private final int myIndex = ourKeysCounter.getAndIncrement();
|
||||
private final String myName; // for debug purposes only
|
||||
private static final ConcurrentIntObjectMap<Key> allKeys = ContainerUtil.createConcurrentIntObjectWeakValueMap();
|
||||
private static final IntObjectMap<Key> allKeys = ContainerUtil.createConcurrentIntObjectWeakValueMap();
|
||||
|
||||
public Key(@NotNull @NonNls String name) {
|
||||
myName = name;
|
||||
@@ -118,7 +118,7 @@ public class Key<T> {
|
||||
*/
|
||||
@Nullable
|
||||
public static Key<?> findKeyByName(String name) {
|
||||
for (ConcurrentIntObjectMap.IntEntry<Key> key : allKeys.entries()) {
|
||||
for (IntObjectMap.Entry<Key> key : allKeys.entries()) {
|
||||
if (name.equals(key.getValue().myName)) {
|
||||
//noinspection unchecked
|
||||
return key.getValue();
|
||||
|
||||
@@ -127,36 +127,36 @@ abstract class ConcurrentIntKeyRefValueHashMap<V> implements ConcurrentIntObject
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<IntEntry<V>> entries() {
|
||||
final Iterator<IntEntry<IntReference<V>>> entryIterator = myMap.entries().iterator();
|
||||
return new Iterable<ConcurrentIntObjectMap.IntEntry<V>>() {
|
||||
public Iterable<Entry<V>> entries() {
|
||||
final Iterator<Entry<IntReference<V>>> entryIterator = myMap.entries().iterator();
|
||||
return new Iterable<Entry<V>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<ConcurrentIntObjectMap.IntEntry<V>> iterator() {
|
||||
return new Iterator<IntEntry<V>>() {
|
||||
private IntEntry<V> next = nextAliveEntry();
|
||||
public Iterator<Entry<V>> iterator() {
|
||||
return new Iterator<Entry<V>>() {
|
||||
private Entry<V> next = nextAliveEntry();
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntEntry<V> next() {
|
||||
public Entry<V> next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
IntEntry<V> result = next;
|
||||
Entry<V> result = next;
|
||||
next = nextAliveEntry();
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntEntry<V> nextAliveEntry() {
|
||||
private Entry<V> nextAliveEntry() {
|
||||
while (entryIterator.hasNext()) {
|
||||
IntEntry<IntReference<V>> entry = entryIterator.next();
|
||||
Entry<IntReference<V>> entry = entryIterator.next();
|
||||
final V v = entry.getValue().get();
|
||||
if (v == null) {
|
||||
continue;
|
||||
}
|
||||
final int key = entry.getKey();
|
||||
return new IntEntry<V>() {
|
||||
return new Entry<V>() {
|
||||
@Override
|
||||
public int getKey() {
|
||||
return key;
|
||||
@@ -193,8 +193,8 @@ abstract class ConcurrentIntKeyRefValueHashMap<V> implements ConcurrentIntObject
|
||||
return myMap.isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@NotNull
|
||||
public Enumeration<V> elements() {
|
||||
final Enumeration<IntReference<V>> elementRefs = myMap.elements();
|
||||
return new Enumeration<V>() {
|
||||
|
||||
@@ -130,7 +130,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
* are special, and contain null keys and values (but are never
|
||||
* exported). Otherwise, keys and vals are never null.
|
||||
*/
|
||||
static class Node<V> implements IntEntry<V> {
|
||||
static class Node<V> implements Entry<V> {
|
||||
final int hash;
|
||||
final int key;
|
||||
volatile V val;
|
||||
@@ -168,9 +168,9 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
public final boolean equals(Object o) {
|
||||
Object v;
|
||||
Object u;
|
||||
IntEntry<?> e;
|
||||
return ((o instanceof IntEntry) &&
|
||||
(e = (IntEntry<?>)o).getKey() == key &&
|
||||
Entry<?> e;
|
||||
return ((o instanceof Entry) &&
|
||||
(e = (Entry<?>)o).getKey() == key &&
|
||||
(v = e.getValue()) != null &&
|
||||
(v == (u = val) || v.equals(u)));
|
||||
}
|
||||
@@ -770,7 +770,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
*
|
||||
* @return the set view
|
||||
*/
|
||||
public Set<IntEntry<V>> entrySet() {
|
||||
public Set<Entry<V>> entrySet() {
|
||||
EntrySetView<V> es;
|
||||
return (es = entrySet) != null ? es : (entrySet = new EntrySetView<V>(this));
|
||||
}
|
||||
@@ -846,7 +846,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
if (!(o instanceof ConcurrentIntObjectMap)) {
|
||||
return false;
|
||||
}
|
||||
ConcurrentIntObjectMap<?> m = (ConcurrentIntObjectMap)o;
|
||||
IntObjectMap<?> m = (IntObjectMap)o;
|
||||
Node<V>[] t;
|
||||
int f = (t = table) == null ? 0 : t.length;
|
||||
Traverser<V> it = new Traverser<V>(t, f, 0, f);
|
||||
@@ -857,7 +857,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (IntEntry e : m.entries()) {
|
||||
for (Entry e : m.entries()) {
|
||||
int mk = e.getKey();
|
||||
Object mv;
|
||||
Object v;
|
||||
@@ -958,7 +958,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
Object[] entries = new EntrySetView<V>(this).toArray();
|
||||
int[] result = new int[entries.length];
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
IntEntry<V> entry = (IntEntry<V>)entries[i];
|
||||
Entry<V> entry = (Entry<V>)entries[i];
|
||||
result[i] = entry.getKey();
|
||||
}
|
||||
return result;
|
||||
@@ -2396,14 +2396,14 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
}
|
||||
|
||||
static final class EntryIterator<V> extends BaseIterator<V>
|
||||
implements Iterator<IntEntry<V>> {
|
||||
implements Iterator<Entry<V>> {
|
||||
EntryIterator(Node<V>[] tab, int index, int size, int limit,
|
||||
ConcurrentIntObjectHashMap<V> map) {
|
||||
super(tab, index, size, limit, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IntEntry<V> next() {
|
||||
public final Entry<V> next() {
|
||||
Node<V> p;
|
||||
if ((p = next) == null) {
|
||||
throw new NoSuchElementException();
|
||||
@@ -2412,7 +2412,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
final V v = p.val;
|
||||
lastReturned = p;
|
||||
advance();
|
||||
return new IntEntry<V>() {
|
||||
return new Entry<V>() {
|
||||
@Override
|
||||
public int getKey() {
|
||||
return k;
|
||||
@@ -2673,7 +2673,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<IntEntry<V>> entries() {
|
||||
public Iterable<Entry<V>> entries() {
|
||||
return new EntrySetView<V>(this);
|
||||
}
|
||||
|
||||
@@ -2682,8 +2682,8 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
* entries. This class cannot be directly instantiated. See
|
||||
* {@link #entrySet()}.
|
||||
*/
|
||||
static final class EntrySetView<V> extends CollectionView<V, IntEntry<V>>
|
||||
implements Set<IntEntry<V>> {
|
||||
static final class EntrySetView<V> extends CollectionView<V, Entry<V>>
|
||||
implements Set<Entry<V>> {
|
||||
|
||||
EntrySetView(ConcurrentIntObjectHashMap<V> map) {
|
||||
super(map);
|
||||
@@ -2693,9 +2693,9 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
public boolean contains(Object o) {
|
||||
Object v;
|
||||
Object r;
|
||||
IntEntry<?> e;
|
||||
return ((o instanceof IntEntry) &&
|
||||
(r = map.get((e = (IntEntry)o).getKey())) != null &&
|
||||
Entry<?> e;
|
||||
return ((o instanceof IntObjectMap.Entry) &&
|
||||
(r = map.get((e = (Entry)o).getKey())) != null &&
|
||||
(v = e.getValue()) != null &&
|
||||
(v == r || v.equals(r)));
|
||||
}
|
||||
@@ -2703,9 +2703,9 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
Object v;
|
||||
IntEntry<?> e;
|
||||
Entry<?> e;
|
||||
return ((o instanceof Map.Entry) &&
|
||||
(e = (IntEntry<?>)o) != null &&
|
||||
(e = (Entry<?>)o) != null &&
|
||||
(v = e.getValue()) != null &&
|
||||
map.remove(e.getKey(), v));
|
||||
}
|
||||
@@ -2715,7 +2715,7 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<IntEntry<V>> iterator() {
|
||||
public Iterator<Entry<V>> iterator() {
|
||||
ConcurrentIntObjectHashMap<V> m = map;
|
||||
Node<V>[] t;
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
@@ -2723,14 +2723,14 @@ class ConcurrentIntObjectHashMap<V> implements ConcurrentIntObjectMap<V> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(IntEntry<V> e) {
|
||||
public boolean add(Entry<V> e) {
|
||||
return map.putVal(e.getKey(), e.getValue(), false) == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends IntEntry<V>> c) {
|
||||
public boolean addAll(Collection<? extends Entry<V>> c) {
|
||||
boolean added = false;
|
||||
for (IntEntry<V> e : c) {
|
||||
for (Entry<V> e : c) {
|
||||
if (add(e)) {
|
||||
added = true;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.intellij.util.containers;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
@@ -27,7 +26,7 @@ import java.util.Enumeration;
|
||||
* Methods are adapted from {@link java.util.concurrent.ConcurrentMap} to integer keys
|
||||
* @see java.util.concurrent.ConcurrentMap
|
||||
*/
|
||||
public interface ConcurrentIntObjectMap<V> {
|
||||
public interface ConcurrentIntObjectMap<V> extends IntObjectMap<V> {
|
||||
/**
|
||||
* @return written value
|
||||
*/
|
||||
@@ -36,17 +35,8 @@ public interface ConcurrentIntObjectMap<V> {
|
||||
boolean remove(int key, @NotNull V value);
|
||||
boolean replace(int key, @NotNull V oldValue, @NotNull V newValue);
|
||||
|
||||
// regular Map methods
|
||||
V put(int key, @NotNull V value);
|
||||
V get(int key);
|
||||
V remove(int key);
|
||||
boolean containsKey(int key);
|
||||
void clear();
|
||||
@NotNull
|
||||
Iterable<IntEntry<V>> entries();
|
||||
|
||||
@NotNull
|
||||
int[] keys();
|
||||
Enumeration<V> elements();
|
||||
|
||||
/**
|
||||
* @return Approximate number of elements in the map.
|
||||
@@ -55,23 +45,13 @@ public interface ConcurrentIntObjectMap<V> {
|
||||
* and Second, for weak- or soft- keyed maps it returns the total number of references
|
||||
* rather than alive values because otherwise it would be too expensive
|
||||
*/
|
||||
@Override
|
||||
int size();
|
||||
|
||||
boolean isEmpty();
|
||||
@NotNull
|
||||
Enumeration<V> elements();
|
||||
@NotNull
|
||||
Collection<V> values();
|
||||
boolean containsValue(@NotNull V value);
|
||||
/**
|
||||
* @return the previous value associated with the specified key,
|
||||
* or {@code null} if there was no mapping for the key
|
||||
*/
|
||||
V putIfAbsent(int key, @NotNull V value);
|
||||
|
||||
interface IntEntry<V> {
|
||||
int getKey();
|
||||
@NotNull
|
||||
V getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2855,5 +2855,14 @@ public class ContainerUtil extends ContainerUtilRt {
|
||||
public static <T> Set<T> createWeakSet() {
|
||||
return new WeakHashSet<T>();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> IntObjectMap<T> createIntKeyWeakValueMap() {
|
||||
return new IntKeyWeakValueHashMap<T>();
|
||||
}
|
||||
@NotNull
|
||||
public static <T> ObjectIntMap<T> createWeakKeyIntValueMap() {
|
||||
return new WeakKeyIntValueHashMap<T>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,17 +15,22 @@
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import gnu.trove.TIntObjectIterator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
class WeakValueIntObjectHashMap<V> {
|
||||
class IntKeyWeakValueHashMap<V> implements IntObjectMap<V> {
|
||||
private final TIntObjectHashMap<MyReference<V>> myMap = new TIntObjectHashMap<MyReference<V>>();
|
||||
private final ReferenceQueue<V> myQueue = new ReferenceQueue<V>();
|
||||
|
||||
@@ -47,19 +52,16 @@ class WeakValueIntObjectHashMap<V> {
|
||||
}
|
||||
int key = ref.key;
|
||||
myMap.remove(key);
|
||||
keyExpired(key);
|
||||
}
|
||||
}
|
||||
|
||||
protected void keyExpired(int key) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V get(int key) {
|
||||
MyReference<V> ref = myMap.get(key);
|
||||
return SoftReference.dereference(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V put(int key, @NotNull V value) {
|
||||
processQueue();
|
||||
MyReference<V> ref = new MyReference<V>(key, value, myQueue);
|
||||
@@ -68,29 +70,35 @@ class WeakValueIntObjectHashMap<V> {
|
||||
return SoftReference.dereference(oldRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V remove(int key) {
|
||||
processQueue();
|
||||
MyReference<V> ref = myMap.remove(key);
|
||||
return SoftReference.dereference(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void clear() {
|
||||
myMap.clear();
|
||||
processQueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int size() {
|
||||
return myMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEmpty() {
|
||||
return myMap.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean containsKey(int key) {
|
||||
throw RefValueHashMap.pointlessContainsKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final Collection<V> values() {
|
||||
List<V> result = new ArrayList<V>();
|
||||
@@ -104,4 +112,63 @@ class WeakValueIntObjectHashMap<V> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public int[] keys() {
|
||||
throw new IncorrectOperationException("keys() makes no sense for weak/soft map because GC can clear the value any moment now");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(@NotNull V value) {
|
||||
return values().contains(value);
|
||||
}
|
||||
|
||||
private static final Object GCED = new Object();
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<Entry<V>> entries() {
|
||||
return new Iterable<Entry<V>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<Entry<V>> iterator() {
|
||||
final TIntObjectIterator<MyReference<V>> tIterator = myMap.iterator();
|
||||
return ContainerUtil.filterIterator(new Iterator<Entry<V>>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return tIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry<V> next() {
|
||||
tIterator.advance();
|
||||
return new Entry<V>() {
|
||||
@Override
|
||||
public int getKey() {
|
||||
return tIterator.key();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public V getValue() {
|
||||
V v = SoftReference.dereference(tIterator.value());
|
||||
//noinspection unchecked
|
||||
return ObjectUtils.notNull(v, (V)GCED);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, new Condition<Entry<V>>() {
|
||||
@Override
|
||||
public boolean value(Entry<V> o) {
|
||||
return o.getValue() != GCED;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2000-2017 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.util.Collection;
|
||||
|
||||
public interface IntObjectMap<V> {
|
||||
V put(int key, @NotNull V value);
|
||||
|
||||
V get(int key);
|
||||
|
||||
V remove(int key);
|
||||
|
||||
boolean containsKey(int key);
|
||||
|
||||
void clear();
|
||||
|
||||
@NotNull
|
||||
int[] keys();
|
||||
|
||||
int size();
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
@NotNull
|
||||
Collection<V> values();
|
||||
|
||||
boolean containsValue(@NotNull V value);
|
||||
|
||||
interface Entry<V> {
|
||||
int getKey();
|
||||
@NotNull
|
||||
V getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Iterable<Entry<V>> entries();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2000-2017 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.util.Set;
|
||||
|
||||
public interface ObjectIntMap<K> {
|
||||
int get(@NotNull K key);
|
||||
|
||||
int put(@NotNull K key, int value);
|
||||
|
||||
int remove(@NotNull K key);
|
||||
|
||||
boolean containsKey(@NotNull K key);
|
||||
|
||||
void clear();
|
||||
|
||||
@NotNull
|
||||
Set<K> keySet();
|
||||
|
||||
int size();
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
@NotNull
|
||||
int[] values();
|
||||
|
||||
boolean containsValue(int value);
|
||||
|
||||
interface Entry<K> {
|
||||
@NotNull
|
||||
K getKey();
|
||||
|
||||
int getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Iterable<Entry<K>> entries();
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
// Copyright 2000-2017 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 com.intellij.openapi.util.Condition;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import gnu.trove.TObjectIntIterator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
class WeakKeyIntValueHashMap<K> implements ObjectIntMap<K> {
|
||||
private final TObjectIntHashMap<MyReference<K>> myMap = new TObjectIntHashMap<MyReference<K>>();
|
||||
private final ReferenceQueue<K> myQueue = new ReferenceQueue<K>();
|
||||
|
||||
private static class MyReference<T> extends WeakReference<T> {
|
||||
private final int myHashCode;
|
||||
|
||||
private MyReference(@NotNull T key, ReferenceQueue<? super T> q) {
|
||||
super(key, q);
|
||||
myHashCode = key.hashCode();
|
||||
}
|
||||
|
||||
// when key is GC-ed, equality should be identity-based
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof MyReference)) return false;
|
||||
MyReference<T> other = (MyReference)obj;
|
||||
T myKey = get();
|
||||
T otherKey = other.get();
|
||||
return obj == this || myKey != null && otherKey != null && myKey.equals(otherKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myHashCode;
|
||||
}
|
||||
}
|
||||
|
||||
private void processQueue() {
|
||||
while(true){
|
||||
MyReference<K> ref = (MyReference)myQueue.poll();
|
||||
if (ref == null) {
|
||||
return;
|
||||
}
|
||||
myMap.remove(ref);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int get(@NotNull K key) {
|
||||
MyReference<K> ref = new MyReference<K>(key, null);
|
||||
return myMap.get(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int put(@NotNull K key, int value) {
|
||||
processQueue();
|
||||
MyReference<K> ref = new MyReference<K>(key, myQueue);
|
||||
return myMap.put(ref, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int remove(@NotNull K key) {
|
||||
processQueue();
|
||||
MyReference<K> ref = new MyReference<K>(key, myQueue);
|
||||
return myMap.remove(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void clear() {
|
||||
myMap.clear();
|
||||
processQueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int size() {
|
||||
return myMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEmpty() {
|
||||
return myMap.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean containsKey(@NotNull K key) {
|
||||
MyReference<K> ref = new MyReference<K>(key, null);
|
||||
return myMap.containsKey(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final int[] values() {
|
||||
throw new IncorrectOperationException("values() makes no sense for weak/soft key map because GC can clear the key any moment now");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return new THashSet<K>(ContainerUtil.map(myMap.keys(), new Function<Object, K>() {
|
||||
@Override
|
||||
public K fun(Object ref) {
|
||||
return SoftReference.dereference((MyReference<K>)ref);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(int value) {
|
||||
throw RefValueHashMap.pointlessContainsValue();
|
||||
}
|
||||
|
||||
private static final Object GCED = new Object();
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<Entry<K>> entries() {
|
||||
return new Iterable<Entry<K>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<Entry<K>> iterator() {
|
||||
final TObjectIntIterator<MyReference<K>> tIterator = myMap.iterator();
|
||||
return ContainerUtil.filterIterator(new Iterator<Entry<K>>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return tIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry<K> next() {
|
||||
tIterator.advance();
|
||||
return new Entry<K>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public K getKey() {
|
||||
K v = SoftReference.dereference(tIterator.key());
|
||||
//noinspection unchecked
|
||||
return ObjectUtils.notNull(v, (K)GCED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getValue() {
|
||||
return tIterator.value();
|
||||
}
|
||||
};
|
||||
}
|
||||
}, new Condition<Entry<K>>() {
|
||||
@Override
|
||||
public boolean value(Entry<K> o) {
|
||||
return o.getKey() != GCED;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ package com.intellij.vcs.log.data;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.PeekingIterator;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntObjectMap;
|
||||
import com.intellij.vcs.log.VcsCommitMetadata;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -28,7 +28,7 @@ import java.util.List;
|
||||
|
||||
public class TopCommitsCache {
|
||||
@NotNull private final VcsLogStorage myStorage;
|
||||
@NotNull private final ConcurrentIntObjectMap<VcsCommitMetadata> myCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
@NotNull private final IntObjectMap<VcsCommitMetadata> myCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
@NotNull private List<VcsCommitMetadata> mySortedDetails = ContainerUtil.newArrayList();
|
||||
|
||||
public TopCommitsCache(@NotNull VcsLogStorage storage) {
|
||||
|
||||
Reference in New Issue
Block a user