diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java index 9a43becef50..3e7a477555f 100644 --- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java +++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java @@ -53,7 +53,7 @@ public final class AdapterManager implements IAdapterManager { * note: always use the compute methods to update the map and make sure the * values (inner map) are never modified but replaced if necessary. */ - private final ConcurrentMap>> adapterLookup; + private final ConcurrentMap adapterLookup; /** * Cache of classes for a given type name. Avoids too many loadClass calls. @@ -77,7 +77,7 @@ public final class AdapterManager implements IAdapterManager { * the adaptable class that the factory provides adapters for. Value is a * List of IAdapterFactory. */ - private final Map> factories; + private final ConcurrentMap> factories; private final Queue lazyFactoryProviders; @@ -173,14 +173,8 @@ public String[] computeAdapterTypes(Class adaptable) { */ private Map> getFactories(Class adaptable) { // cache reference to lookup to protect against concurrent flush - return adapterLookup.computeIfAbsent(adaptable.getName(), adaptableType -> { - // calculate adapters for the class - Map> table = new HashMap<>(4); - for (Class cl : computeClassOrder(adaptable)) { - addFactoriesFor(cl.getName(), table); - } - return Collections.unmodifiableMap(table); - }); + return adapterLookup.computeIfAbsent(adaptable.getName(), adaptableType -> new AdapterLookup(adaptable, this)) + .getMap(); } /** @@ -241,7 +235,7 @@ private static void computeInterfaceOrder(Class[] interfaces, Collection */ - public synchronized void flushLookup() { + public void flushLookup() { adapterLookup.clear(); classLookup.clear(); classSearchOrderLookup.clear(); @@ -346,7 +340,7 @@ public Object loadAdapter(Object adaptable, String adapterTypeName) { * @see IAdapterManager#registerAdapters */ @Override - public synchronized void registerAdapters(IAdapterFactory factory, Class adaptable) { + public void registerAdapters(IAdapterFactory factory, Class adaptable) { registerFactory(factory, adaptable.getName()); flushLookup(); } @@ -362,29 +356,33 @@ public void registerFactory(IAdapterFactory factory, String adaptableType) { * @see IAdapterManager#unregisterAdapters */ @Override - public synchronized void unregisterAdapters(IAdapterFactory factory) { - for (List list : factories.values()) - list.remove(factory); - flushLookup(); + public void unregisterAdapters(IAdapterFactory factory) { + for (List list : factories.values()) { + if (list.remove(factory)) { + flushLookup(); + } + } } /* * @see IAdapterManager#unregisterAdapters */ @Override - public synchronized void unregisterAdapters(IAdapterFactory factory, Class adaptable) { + public void unregisterAdapters(IAdapterFactory factory, Class adaptable) { List factoryList = factories.get(adaptable.getName()); - if (factoryList == null) + if (factoryList == null || factoryList.isEmpty()) { return; - factoryList.remove(factory); - flushLookup(); + } + if (factoryList.remove(factory)) { + flushLookup(); + } } /* * Shuts down the adapter manager by removing all factories and removing the * registry change listener. Should only be invoked during platform shutdown. */ - public synchronized void unregisterAllAdapters() { + public void unregisterAllAdapters() { lazyFactoryProviders.clear(); factories.clear(); flushLookup(); @@ -409,7 +407,7 @@ public Map> getFactories() { } /** - * Try to laod the given factory according to the force parameter + * Try to load the given factory according to the force parameter * * @param factory the factory to load * @param force if loading should be forced @@ -421,4 +419,28 @@ private static Optional loadFactory(IAdapterFactory factory, bo } return Optional.ofNullable(factory); } + + private static final class AdapterLookup { + + private Class adaptable; + private AdapterManager manager; + private Map> map; + + AdapterLookup(Class adaptable, AdapterManager manager) { + this.adaptable = adaptable; + this.manager = manager; + } + + synchronized Map> getMap() { + if (map == null) { + // calculate adapters for the class + Map> table = new HashMap<>(4); + for (Class cl : manager.computeClassOrder(adaptable)) { + manager.addFactoriesFor(cl.getName(), table); + } + map = Collections.unmodifiableMap(table); + } + return map; + } + } }