From e6d60c3e3eb114e59abb70e1eb06be7846898cdb Mon Sep 17 00:00:00 2001 From: Ilya Sergey Date: Wed, 4 Nov 2009 15:11:22 +0100 Subject: [PATCH] possible solution to avoid thread blast --- .../groovy/dsl/GroovyDslFileIndex.java | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java index 70f333407b0a..7e1a2ad5f826 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java @@ -42,8 +42,7 @@ import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.unscramble.UnscrambleDialog; -import com.intellij.util.containers.ConcurrentFactoryMap; -import com.intellij.util.containers.ConcurrentHashMap; +import com.intellij.util.containers.*; import com.intellij.util.indexing.*; import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.KeyDescriptor; @@ -57,8 +56,8 @@ import javax.swing.event.HyperlinkEvent; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.util.Collections; -import java.util.Map; +import java.util.*; +import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -78,6 +77,8 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { private static final Map> ourMapping = new ConcurrentHashMap>(); + private static final MultiMap>> filesInProcessing = + new ConcurrentMultiMap>>(); private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); private static final byte[] ENABLED_FLAG = new byte[]{(byte)239}; @@ -281,24 +282,40 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { final long stamp, final String text) { final Project project = file.getProject(); - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + final String fileUrl = vfile.getUrl(); + + final Runnable parseScript = new Runnable() { public void run() { - synchronized (vfile) { //ensure that only one thread calculates dsl executor - GroovyDslExecutor executor = getCachedExecutor(vfile, stamp); - if (executor == null) { - executor = createExecutor(text, vfile, project); - // executor is not only time-consuming to create, but also takes some PermGenSpace - // => we can't afford garbage-collecting it together with PsiFile - // => cache globally by file path - ourMapping.put(vfile.getUrl(), Pair.create(executor, stamp)); - if (executor != null) { - activateUntilModification(vfile); - } + GroovyDslExecutor executor = getCachedExecutor(vfile, stamp); + if (executor == null) { + executor = createExecutor(text, vfile, project); + // executor is not only time-consuming to create, but also takes some PermGenSpace + // => we can't afford garbage-collecting it together with PsiFile + // => cache globally by file path + ourMapping.put(vfile.getUrl(), Pair.create(executor, stamp)); + if (executor != null) { + activateUntilModification(vfile); + } + } + + // access to our multimap should be synchronized + synchronized (vfile) { + // put evaluated executor to all queues + final Collection>> queuesForFile = filesInProcessing.remove(fileUrl); + for (LinkedBlockingQueue> queue : queuesForFile) { + queue.offer(Pair.create(file, executor)); } - queue.offer(Pair.create(file, executor)); } } - }); + }; + + synchronized (vfile) { //ensure that only one thread calculates dsl executor + final boolean isNewRequest = !filesInProcessing.containsKey(fileUrl); + filesInProcessing.putValue(fileUrl, queue); + if (isNewRequest) { + ApplicationManager.getApplication().executeOnPooledThread(parseScript); + } + } } @Nullable @@ -324,7 +341,6 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { return null; } } - private static void invokeDslErrorPopup(Throwable e, final Project project, VirtualFile vfile) { final StringWriter writer = new StringWriter(); e.printStackTrace(new PrintWriter(writer));