From 895e6311d6bd024471e5632887fbb379faf8d629 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 19 Dec 2019 17:19:59 +0100 Subject: [PATCH] Ensure that it's possible to subscribe via to an application-level topic GitOrigin-RevId: dc955939689955763f5c3e092ad4751599f94c41 --- .../util/messages/impl/MessageBusImpl.java | 57 ++++++++----------- .../openapi/project/impl/DefaultProject.java | 9 +++ .../PlatformComponentManagerImpl.kt | 2 +- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/platform/core-api/src/com/intellij/util/messages/impl/MessageBusImpl.java b/platform/core-api/src/com/intellij/util/messages/impl/MessageBusImpl.java index a156825ccf55..13db337b87d5 100644 --- a/platform/core-api/src/com/intellij/util/messages/impl/MessageBusImpl.java +++ b/platform/core-api/src/com/intellij/util/messages/impl/MessageBusImpl.java @@ -71,6 +71,8 @@ public class MessageBusImpl implements MessageBus { private final Map myLazyConnections; + private boolean myIgnoreParentLazyListeners; + public MessageBusImpl(@NotNull MessageBusOwner owner, @NotNull MessageBusImpl parentBus) { myOwner = owner; myConnectionDisposable = createConnectionDisposable(owner); @@ -102,6 +104,10 @@ public class MessageBusImpl implements MessageBus { myParentBus = null; } + public void setIgnoreParentLazyListeners(boolean ignoreParentLazyListeners) { + myIgnoreParentLazyListeners = ignoreParentLazyListeners; + } + /** * Must be a concurrent map, because remove operation may be concurrently performed (synchronized only per topic). */ @@ -109,7 +115,7 @@ public class MessageBusImpl implements MessageBus { public void setLazyListeners(@NotNull ConcurrentMap> map) { if (myTopicClassToListenerClass != Collections.>emptyMap()) { myTopicClassToListenerClass.putAll(map); - myPublishers.clear(); + clearSubscriberCache(); } else { myTopicClassToListenerClass = map; @@ -192,31 +198,14 @@ public class MessageBusImpl implements MessageBus { Class listenerClass = topic.getListenerClass(); - if (myTopicClassToListenerClass.isEmpty()) { - Object newInstance = Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, createTopicHandler(topic)); - Object prev = myPublishers.putIfAbsent(topic, newInstance); - //noinspection unchecked - return (L)(prev == null ? newInstance : prev); - } - else { - // remove is atomic operation, so, even if topic concurrently created and our topic instance will be not used, still, listeners will be added, - // but problem is that if another topic will be returned earlier, then these listeners will not get fired event - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (topic) { - return subscribeLazyListeners(topic, listenerClass); - } - } + Object newInstance = Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, createTopicHandler(topic)); + Object prev = myPublishers.putIfAbsent(topic, newInstance); + //noinspection unchecked + return (L)(prev == null ? newInstance : prev); } - @NotNull - private L subscribeLazyListeners(@NotNull Topic topic, @NotNull Class listenerClass) { - //noinspection unchecked - L publisher = (L)myPublishers.get(topic); - if (publisher != null) { - return publisher; - } - - List listenerDescriptors = myTopicClassToListenerClass.remove(listenerClass.getName()); + private void subscribeLazyListeners(@NotNull Topic topic) { + List listenerDescriptors = myTopicClassToListenerClass.remove(topic.getListenerClass().getName()); if (listenerDescriptors != null) { MultiMap listenerMap = new MultiMap<>(); for (ListenerDescriptor listenerDescriptor : listenerDescriptors) { @@ -239,11 +228,6 @@ public class MessageBusImpl implements MessageBus { } } } - - //noinspection unchecked - publisher = (L)Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, createTopicHandler(topic)); - myPublishers.put(topic, publisher); - return publisher; } @ApiStatus.Internal @@ -339,7 +323,12 @@ public class MessageBusImpl implements MessageBus { return myOwner.toString(); } - private void calcSubscribers(@NotNull Topic topic, @NotNull List result) { + private void calcSubscribers(@NotNull Topic topic, + @NotNull List result, + boolean subscribeLazyListeners) { + if (subscribeLazyListeners) { + subscribeLazyListeners(topic); + } final List topicSubscribers = mySubscribers.get(topic); if (topicSubscribers != null) { result.addAll(topicSubscribers); @@ -349,12 +338,14 @@ public class MessageBusImpl implements MessageBus { if (direction == Topic.BroadcastDirection.TO_CHILDREN) { for (MessageBusImpl childBus : myChildBuses) { - childBus.calcSubscribers(topic, result); + if (!childBus.isDisposed()) { + childBus.calcSubscribers(topic, result, !childBus.myIgnoreParentLazyListeners); + } } } if (direction == Topic.BroadcastDirection.TO_PARENT && myParentBus != null) { - myParentBus.calcSubscribers(topic, result); + myParentBus.calcSubscribers(topic, result, true); } } @@ -383,7 +374,7 @@ public class MessageBusImpl implements MessageBus { List topicSubscribers = mySubscriberCache.get(topic); if (topicSubscribers == null) { topicSubscribers = new ArrayList<>(); - calcSubscribers(topic, topicSubscribers); + calcSubscribers(topic, topicSubscribers, true); mySubscriberCache.put(topic, topicSubscribers); myRootBus.myClearedSubscribersCache = false; } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java index 8c0ca9916d09..83d43def9d73 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java @@ -18,6 +18,7 @@ import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.project.ProjectStoreOwner; import com.intellij.util.messages.MessageBus; +import com.intellij.util.messages.impl.MessageBusImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.SystemIndependent; @@ -90,6 +91,14 @@ final class DefaultProject extends UserDataHolderBase implements Project, Projec public int hashCode() { return DEFAULT_HASH_CODE; } + + @NotNull + @Override + protected synchronized MessageBusImpl getOrCreateMessageBusUnderLock() { + MessageBusImpl messageBus = super.getOrCreateMessageBusUnderLock(); + messageBus.setIgnoreParentLazyListeners(true); + return messageBus; + } }; } diff --git a/platform/service-container/src/com/intellij/serviceContainer/PlatformComponentManagerImpl.kt b/platform/service-container/src/com/intellij/serviceContainer/PlatformComponentManagerImpl.kt index e490c7f8b900..5213c78f1536 100644 --- a/platform/service-container/src/com/intellij/serviceContainer/PlatformComponentManagerImpl.kt +++ b/platform/service-container/src/com/intellij/serviceContainer/PlatformComponentManagerImpl.kt @@ -396,7 +396,7 @@ abstract class PlatformComponentManagerImpl @JvmOverloads constructor(internal v } @Synchronized - private fun getOrCreateMessageBusUnderLock(): MessageBusImpl { + protected open fun getOrCreateMessageBusUnderLock(): MessageBusImpl { var messageBus = this.messageBus if (messageBus != null) { return messageBus