From bcef32f3518856dc669fa359ebb216b910af935c Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Fri, 7 Oct 2011 21:01:45 +0400 Subject: [PATCH] Optimization: remove synchronized sections. --- .../util/pico/DefaultPicoContainer.java | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java index 47318908f8fb..842cd469f4a4 100644 --- a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java +++ b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java @@ -17,7 +17,6 @@ package com.intellij.util.pico; import com.intellij.util.ReflectionCache; import com.intellij.util.containers.ConcurrentHashMap; -import com.intellij.util.containers.OrderedSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.picocontainer.*; @@ -25,6 +24,8 @@ import org.picocontainer.defaults.*; import java.io.Serializable; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicReference; public class DefaultPicoContainer implements MutablePicoContainer, Serializable { private final ComponentAdapterFactory componentAdapterFactory; @@ -33,24 +34,23 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable private final Set children = new HashSet(); private final Map componentKeyToAdapterCache = new ConcurrentHashMap(); - private final Collection componentAdapters = Collections.synchronizedCollection(new OrderedSet()); + private final AtomicReference> componentAdapters = new AtomicReference>(new LinkedHashSet()); // Keeps track of instantiation order. - private final List orderedComponentAdapters = Collections.synchronizedList(new OrderedSet()); + private final AtomicReference> orderedComponentAdapters = new AtomicReference>(new LinkedHashSet()); private final Map classNameToAdapter = new ConcurrentHashMap(); - private final Collection nonAssignableComponentAdapters = Collections.synchronizedCollection(new OrderedSet()); + private final CopyOnWriteArrayList nonAssignableComponentAdapters = new CopyOnWriteArrayList(); public DefaultPicoContainer(@NotNull ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) { this.componentAdapterFactory = componentAdapterFactory; this.parent = parent == null ? null : ImmutablePicoContainerProxyFactory.newProxyInstance(parent); } - protected DefaultPicoContainer() { this(new DefaultComponentAdapterFactory(), null); } public Collection getComponentAdapters() { - return Collections.unmodifiableCollection(componentAdapters); + return Collections.unmodifiableCollection(componentAdapters.get()); } public Map getAssignablesCache() { @@ -59,7 +59,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable public Collection getNonAssignableAdapters() { - return Collections.unmodifiableCollection(nonAssignableComponentAdapters); + return nonAssignableComponentAdapters; } @Nullable @@ -144,20 +144,48 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable nonAssignableComponentAdapters.add(componentAdapter); } - componentAdapters.add(componentAdapter); + addElement(componentAdapters, componentAdapter); + componentKeyToAdapterCache.put(componentKey, componentAdapter); return componentAdapter; } + private static void addElement(AtomicReference> collectionHolder, T element) { + do { + LinkedHashSet oldCollection = collectionHolder.get(); + if (oldCollection.contains(element)) { + return; + } + + LinkedHashSet newCollection = new LinkedHashSet(oldCollection); + newCollection.add(element); + + if (collectionHolder.compareAndSet(oldCollection, newCollection)) break; + } while (true); + } + + private static void removeElement(AtomicReference> collectionHolder, T element) { + do { + LinkedHashSet oldCollection = collectionHolder.get(); + + LinkedHashSet newCollection = new LinkedHashSet(oldCollection); + newCollection.remove(element); + + if (collectionHolder.compareAndSet(oldCollection, newCollection)) break; + } while (true); + } + public ComponentAdapter unregisterComponent(Object componentKey) { ComponentAdapter adapter = componentKeyToAdapterCache.remove(componentKey); - componentAdapters.remove(adapter); - orderedComponentAdapters.remove(adapter); + + removeElement(componentAdapters, adapter); + removeElement(orderedComponentAdapters, adapter); + return adapter; } private void addOrderedComponentAdapter(ComponentAdapter componentAdapter) { - orderedComponentAdapters.add(componentAdapter); + addElement(orderedComponentAdapters, componentAdapter); } public List getComponentInstances() throws PicoException { @@ -170,7 +198,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable } Map adapterToInstanceMap = new HashMap(); - for (final ComponentAdapter componentAdapter : componentAdapters) { + for (final ComponentAdapter componentAdapter : componentAdapters.get()) { if (ReflectionCache.isAssignable(componentType, componentAdapter.getComponentImplementation())) { Object componentInstance = getInstance(componentAdapter); adapterToInstanceMap.put(componentAdapter, componentInstance); @@ -182,7 +210,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable } List result = new ArrayList(); - for (ComponentAdapter componentAdapter : orderedComponentAdapters) { + for (ComponentAdapter componentAdapter : orderedComponentAdapters.get()) { final Object componentInstance = adapterToInstanceMap.get(componentAdapter); if (componentInstance != null) { // may be null in the case of the "implicit" adapter @@ -212,7 +240,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable @Nullable private Object getInstance(ComponentAdapter componentAdapter) { - final boolean isLocal = componentAdapters.contains(componentAdapter); + final boolean isLocal = componentAdapters.get().contains(componentAdapter); if (isLocal) { return getLocalInstance(componentAdapter);