From 1668d7132f5632c8580ce0c76dc03ebd8f7c1aae Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 5 Feb 2016 12:46:49 +0300 Subject: [PATCH] following IDEA-CR-8206 (IDEA-151182) --- .../documentation/DocumentationManager.java | 10 +++---- .../QuickDocOnMouseOverManager.java | 8 +++--- .../progress/util/ProgressIndicatorUtils.java | 26 +++++++++++++++++-- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index e6688df30497..21ee66b2ba6f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1172,18 +1172,14 @@ public class DocumentationManager extends DockablePopupManager result = new Ref(); - long deadline = System.currentTimeMillis() + DOC_GENERATION_TIMEOUT_MILLISECONDS; - while (!ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(new Runnable() { + ProgressIndicatorUtils.runInReadActionWithWriteActionPriorityWithRetries(new Runnable() { @Override public void run() { final SmartPsiElementPointer originalElement = myElement.getUserData(ORIGINAL_ELEMENT_KEY); String doc = provider.generateDoc(myElement, originalElement != null ? originalElement.getElement() : null); result.set(doc); } - }) && System.currentTimeMillis() < deadline) { - //noinspection BusyWait - Thread.sleep(DOC_GENERATION_PAUSE_MILLISECONDS); - } + }, DOC_GENERATION_TIMEOUT_MILLISECONDS, DOC_GENERATION_PAUSE_MILLISECONDS); return result.get(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java index 70bbfd33f357..0308249b70a0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java @@ -295,12 +295,14 @@ public class QuickDocOnMouseOverManager { @Override public void run() { Ref targetElementRef = new Ref<>(); - ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(new Runnable() { + ProgressIndicatorUtils.runInReadActionWithWriteActionPriorityWithRetries(new Runnable() { @Override public void run() { - targetElementRef.set(docManager.findTargetElement(editor, offset, originalElement.getContainingFile(), originalElement)); + if (originalElement.isValid()) { + targetElementRef.set(docManager.findTargetElement(editor, offset, originalElement.getContainingFile(), originalElement)); + } } - }); + }, 5000, 100); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java index f2e804fc4aaa..6b5e2a3d5136 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.ide.PooledThreadExecutor; import java.util.concurrent.Executor; +import java.util.concurrent.locks.LockSupport; /** * Methods in this class are used to equip long background processes which take read actions with a special listener @@ -66,9 +67,30 @@ public class ProgressIndicatorUtils { scheduleWithWriteActionPriority(progressIndicator, PooledThreadExecutor.INSTANCE, readTask); } + /** + * Repeatedly tries to run given task in read action without blocking write actions (for this to work effectively the action should invoke + * {@link ProgressManager#checkCanceled()} or {@link ProgressIndicator#checkCanceled()} often enough). + * + * @param action task to run + * @param timeout timeout in milliseconds + * @param pauseBetweenRetries pause between retries in milliseconds + * @return true if the action succeeded to run without interruptions, false otherwise + * @throws InterruptedException if execution was interrupted while waiting for the next attempt + */ + public static boolean runInReadActionWithWriteActionPriorityWithRetries(@NotNull final Runnable action, + long timeout, long pauseBetweenRetries) { + boolean result; + long deadline = System.currentTimeMillis() + timeout; + while (!(result = runInReadActionWithWriteActionPriority(action)) && System.currentTimeMillis() < deadline) { + LockSupport.parkNanos(pauseBetweenRetries * 1000); + } + return result; + } + /** * This method attempts to run provided action synchronously in a read action, so that, if possible, it wouldn't impact any pending, - * executing or future write actions. + * executing or future write actions (for this to work effectively the action should invoke {@link ProgressManager#checkCanceled()} or + * {@link ProgressIndicator#checkCanceled()} often enough). * It returns true if action was executed successfully. It returns false if the action was not * executed successfully, i.e. if: *