From a0f09d45d5bc0007177522ed9e5e6d9dfc0716cd Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 May 2013 16:00:07 +0200 Subject: [PATCH] less memory consumption in pico container --- .../util/pico/DefaultPicoContainer.java | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java index 265582c0cbf1..d6fb6c3d4193 100644 --- a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java +++ b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java @@ -170,9 +170,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable } private void addOrderedComponentAdapter(ComponentAdapter componentAdapter) { - if (!orderedComponentAdapters.contains(componentAdapter)) { - orderedComponentAdapters.add(componentAdapter); - } + orderedComponentAdapters.add(componentAdapter); } @Override @@ -225,10 +223,8 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable } @Nullable - private Object getInstance(ComponentAdapter componentAdapter) { - final boolean isLocal = componentAdapters.contains(componentAdapter); - - if (isLocal) { + private Object getInstance(@NotNull ComponentAdapter componentAdapter) { + if (componentAdapters.getImmutableSet().contains(componentAdapter)) { return getLocalInstance(componentAdapter); } if (parent != null) { @@ -360,33 +356,35 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable public PicoContainer getParent() { return parent; } - + + /** + * A linked hash set that's copied on write operations. + * @param + */ private static class LinkedHashSetWrapper { - + private final Object lock = new Object(); private volatile Set immutableSet; - - private final LinkedHashSet synchronizedSet = new LinkedHashSet(); - - private final ConcurrentHashMap concurrentSet = new ConcurrentHashMap(); - - public boolean contains(@Nullable T element) { - return element != null && concurrentSet.containsKey(element); - } - - public void add(@NotNull T element) { - synchronized (synchronizedSet) { - immutableSet = null; - synchronizedSet.add(element); - concurrentSet.put(element, element); + private LinkedHashSet synchronizedSet = new LinkedHashSet(); + + public synchronized void add(@NotNull T element) { + synchronized (lock) { + if (!synchronizedSet.contains(element)) { + copySyncSetIfExposedAsImmutable().add(element); + } } } - - public void remove(@Nullable T element) { - if (element == null) return; - synchronized (synchronizedSet) { + + private LinkedHashSet copySyncSetIfExposedAsImmutable() { + if (immutableSet != null) { immutableSet = null; - synchronizedSet.remove(element); - concurrentSet.remove(element); + synchronizedSet = new LinkedHashSet(synchronizedSet); + } + return synchronizedSet; + } + + public void remove(@Nullable T element) { + synchronized (lock) { + copySyncSetIfExposedAsImmutable().remove(element); } } @@ -394,11 +392,11 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable public Set getImmutableSet() { Set res = immutableSet; if (res == null) { - synchronized (synchronizedSet) { + synchronized (lock) { res = immutableSet; if (res == null) { - res = Collections.unmodifiableSet((Set)synchronizedSet.clone()); - immutableSet = res; + // Expose the same set as immutable. It should be never modified again. Next add/remove operations will copy synchronizedSet + immutableSet = res = Collections.unmodifiableSet(synchronizedSet); } } }