diff --git a/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java b/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java index 56b31cd7c09e..a77d857390e8 100644 --- a/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java +++ b/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java @@ -60,7 +60,6 @@ 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.StripedLockIntObjectConcurrentHashMap; import com.intellij.util.io.storage.HeavyProcessLatch; import com.intellij.util.messages.MessageBus; import gnu.trove.*; @@ -678,7 +677,7 @@ public class RefResolveServiceImpl extends RefResolveService implements Runnable int forwardSize = 0; int backwardSize = 0; final TIntObjectHashMap fileToBackwardIds = new TIntObjectHashMap(fileToForwardIds.size()); - for (StripedLockIntObjectConcurrentHashMap.IntEntry entry : fileToForwardIds.entries()) { + for (ConcurrentIntObjectMap.IntEntry entry : fileToForwardIds.entries()) { int fileId = entry.getKey(); int[] forwardIds = entry.getValue(); forwardSize += forwardIds.length; diff --git a/platform/util/src/com/intellij/openapi/util/Key.java b/platform/util/src/com/intellij/openapi/util/Key.java index 5bb14448f361..f7ac76da407c 100644 --- a/platform/util/src/com/intellij/openapi/util/Key.java +++ b/platform/util/src/com/intellij/openapi/util/Key.java @@ -15,8 +15,8 @@ */ package com.intellij.openapi.util; +import com.intellij.util.containers.ConcurrentIntObjectMap; import com.intellij.util.containers.ConcurrentWeakValueIntObjectHashMap; -import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -109,7 +109,7 @@ public class Key { */ @Nullable public static Key findKeyByName(String name) { - for (StripedLockIntObjectConcurrentHashMap.IntEntry key : allKeys.entries()) { + for (ConcurrentIntObjectMap.IntEntry key : allKeys.entries()) { if (name.equals(key.getValue().myName)) { //noinspection unchecked return key.getValue(); diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentIntObjectMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentIntObjectMap.java index f0301b920fb5..77bee46254c6 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentIntObjectMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentIntObjectMap.java @@ -17,6 +17,7 @@ package com.intellij.util.containers; import org.jetbrains.annotations.NotNull; +import java.util.Collection; import java.util.Enumeration; /** @@ -42,7 +43,7 @@ public interface ConcurrentIntObjectMap { boolean containsKey(int key); void clear(); @NotNull - Iterable> entries(); + Iterable> entries(); @NotNull int[] keys(); @@ -58,5 +59,13 @@ public interface ConcurrentIntObjectMap { boolean isEmpty(); @NotNull Enumeration elements(); + @NotNull + Collection values(); V putIfAbsent(int key, @NotNull V value); + boolean containsValue(@NotNull V value); + + public interface IntEntry { + int getKey(); + @NotNull V getValue(); + } } diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentRefValueIntObjectHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentRefValueIntObjectHashMap.java index 7fdf6085dddc..f6b936c2831a 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentRefValueIntObjectHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentRefValueIntObjectHashMap.java @@ -17,12 +17,11 @@ package com.intellij.util.containers; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.NoSuchElementException; +import java.util.*; /** * Base class for concurrent int key -> (weak/soft) value:V map @@ -121,35 +120,35 @@ abstract class ConcurrentRefValueIntObjectHashMap implements ConcurrentIntObj @NotNull @Override - public Iterable> entries() { - final Iterator>> entryIterator = myMap.entries().iterator(); - return new Iterable>() { + public Iterable> entries() { + final Iterator>> entryIterator = myMap.entries().iterator(); + return new Iterable>() { @Override - public Iterator> iterator() { - return new Iterator>() { - StripedLockIntObjectConcurrentHashMap.IntEntry next = nextAliveEntry(); + public Iterator> iterator() { + return new Iterator>() { + IntEntry next = nextAliveEntry(); @Override public boolean hasNext() { return next != null; } @Override - public StripedLockIntObjectConcurrentHashMap.IntEntry next() { + public IntEntry next() { if (!hasNext()) throw new NoSuchElementException(); - StripedLockIntObjectConcurrentHashMap.IntEntry result = next; + IntEntry result = next; next = nextAliveEntry(); return result; } - private StripedLockIntObjectConcurrentHashMap.IntEntry nextAliveEntry() { + private IntEntry nextAliveEntry() { while (entryIterator.hasNext()) { - StripedLockIntObjectConcurrentHashMap.IntEntry> entry = entryIterator.next(); + IntEntry> entry = entryIterator.next(); final V v = entry.getValue().get(); if (v == null) { continue; } final int key = entry.getKey(); - return new StripedLockIntObjectConcurrentHashMap.IntEntry() { + return new IntEntry() { @Override public int getKey() { return key; @@ -221,4 +220,21 @@ abstract class ConcurrentRefValueIntObjectHashMap implements ConcurrentIntObj IntReference prev = myMap.putIfAbsent(key, createReference(key, value, myQueue)); return prev == null ? null : prev.get(); } + + @Override + public Collection values() { + Set result = new THashSet(); + ContainerUtil.addAll(result, elements()); + return result; + } + + @Override + public boolean containsValue(@NotNull V value) { + for (IntEntry> entry : myMap.entries()) { + if (value.equals(entry.getValue().get())) { + return true; + } + } + return false; + } } diff --git a/platform/util/src/com/intellij/util/containers/StripedLockIntObjectConcurrentHashMap.java b/platform/util/src/com/intellij/util/containers/StripedLockIntObjectConcurrentHashMap.java index 2d96ff043d8a..91392663e5a1 100644 --- a/platform/util/src/com/intellij/util/containers/StripedLockIntObjectConcurrentHashMap.java +++ b/platform/util/src/com/intellij/util/containers/StripedLockIntObjectConcurrentHashMap.java @@ -16,12 +16,12 @@ package com.intellij.util.containers; +import com.intellij.openapi.util.Comparing; +import gnu.trove.THashSet; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.NoSuchElementException; +import java.util.*; /** similar to java.util.ConcurrentHashMap except: keys are ints @@ -29,7 +29,6 @@ import java.util.NoSuchElementException; -- using only one Segment -- eliminating unnecessary fields -- using one of 256 ReentrantLock for Segment statically pre-allocated in {@link StripedReentrantLocks} - added hashing strategy argument made not Serializable */ public class StripedLockIntObjectConcurrentHashMap implements ConcurrentIntObjectMap { @@ -218,7 +217,13 @@ public class StripedLockIntObjectConcurrentHashMap implements ConcurrentIntOb return new ValueIterator(); } - /* ---------------- Iterator Support -------------- */ + @Override + public Collection values() { + Set result = new THashSet(); + ContainerUtil.addAll(result, elements()); + return result; + } +/* ---------------- Iterator Support -------------- */ private class HashIterator { private int nextTableIndex = table.length - 1; @@ -279,12 +284,6 @@ public class StripedLockIntObjectConcurrentHashMap implements ConcurrentIntOb } } - public interface IntEntry { - int getKey(); - @NotNull V getValue(); - } - - @Override @NotNull public Iterable> entries() { @@ -485,6 +484,18 @@ public class StripedLockIntObjectConcurrentHashMap implements ConcurrentIntOb return false; } + @Override + public boolean containsValue(@NotNull V value) { + if (count != 0) { // read-volatile + ValueIterator valueIterator = new ValueIterator(); + while (valueIterator.hasNext()) { + V next = valueIterator.next(); + if (Comparing.equal(next, value)) return true; + } + } + return false; + } + @Override public boolean replace(int key, @NotNull V oldValue, @NotNull V newValue) { lock();