diff --git a/platform/lang-impl/src/com/intellij/util/fileIndex/AbstractFileIndex.java b/platform/lang-impl/src/com/intellij/util/fileIndex/AbstractFileIndex.java index 0993ac7c31c8..81ca7db33dc3 100644 --- a/platform/lang-impl/src/com/intellij/util/fileIndex/AbstractFileIndex.java +++ b/platform/lang-impl/src/com/intellij/util/fileIndex/AbstractFileIndex.java @@ -334,7 +334,7 @@ public abstract class AbstractFileIndex imple myFileTypesToRefresh = fileTypesToRefresh; } - public VirtualFile[] queryNeededFiles() { + public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) { return AbstractFileIndex.this.queryNeededFiles(myIncludeChangedFiles, myFileTypesToRefresh); } diff --git a/platform/lang-impl/src/com/intellij/util/fileIndex/FileIndexRefreshCacheUpdater.java b/platform/lang-impl/src/com/intellij/util/fileIndex/FileIndexRefreshCacheUpdater.java index 17bec369758a..681ad1e118c3 100644 --- a/platform/lang-impl/src/com/intellij/util/fileIndex/FileIndexRefreshCacheUpdater.java +++ b/platform/lang-impl/src/com/intellij/util/fileIndex/FileIndexRefreshCacheUpdater.java @@ -19,6 +19,7 @@ package com.intellij.util.fileIndex; import com.intellij.ide.caches.CacheUpdater; import com.intellij.ide.caches.FileContent; import com.intellij.openapi.Disposable; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ex.ProjectRootManagerEx; import com.intellij.openapi.vfs.*; @@ -70,7 +71,7 @@ public class FileIndexRefreshCacheUpdater extends VirtualFileAdapter implements return 0; } - public VirtualFile[] queryNeededFiles() { + public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) { return VfsUtil.toVirtualFileArray(myChangedFiles); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index cdad30482b05..ced6e0cc5290 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -1937,7 +1937,7 @@ public class FileBasedIndex implements ApplicationComponent { } } - public static void iterateIndexableFiles(final ContentIterator processor, Project project) { + public static void iterateIndexableFiles(final ContentIterator processor, Project project, ProgressIndicator indicator) { if (project.isDisposed()) { return; } @@ -1948,7 +1948,6 @@ public class FileBasedIndex implements ApplicationComponent { if (project.isDisposed()) { return; } - ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); Set visitedRoots = new HashSet(); for (IndexedRootsProvider provider : Extensions.getExtensions(IndexedRootsProvider.EP_NAME)) { @@ -1999,6 +1998,7 @@ public class FileBasedIndex implements ApplicationComponent { private static void iterateRecursively(@Nullable final VirtualFile root, final ContentIterator processor, ProgressIndicator indicator) { if (root != null) { if (indicator != null) { + indicator.checkCanceled(); indicator.setText2(root.getPresentableUrl()); } @@ -2011,7 +2011,8 @@ public class FileBasedIndex implements ApplicationComponent { processor.processFile(file); } } - } else { + } + else { processor.processFile(root); } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java index c402b80d3050..2859e104bbcc 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java @@ -25,6 +25,7 @@ import com.intellij.ide.startup.StartupManagerEx; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.file.exclude.ProjectFileExclusionManager; import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerAdapter; @@ -105,7 +106,7 @@ public class FileBasedIndexProjectHandler extends AbstractProjectComponent imple return myIndex.getNumberOfPendingInvalidations(); } - public VirtualFile[] queryNeededFiles() { + public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) { Collection files = myIndex.getFilesToUpdate(myProject); return VfsUtil.toVirtualFileArray(files); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java index 0f5577238ff7..dc9179058f66 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java @@ -19,6 +19,7 @@ package com.intellij.util.indexing; import com.intellij.ide.caches.CacheUpdater; import com.intellij.ide.caches.FileContent; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.CollectingContentIterator; import com.intellij.openapi.vfs.VfsUtil; @@ -45,10 +46,10 @@ public class UnindexedFilesUpdater implements CacheUpdater { return myIndex.getNumberOfPendingInvalidations(); } - public VirtualFile[] queryNeededFiles() { + public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) { CollectingContentIterator finder = myIndex.createContentIterator(); long l = System.currentTimeMillis(); - FileBasedIndex.iterateIndexableFiles(finder, myProject); + FileBasedIndex.iterateIndexableFiles(finder, myProject, indicator); LOG.info("Indexable files iterated in " + (System.currentTimeMillis() - l) + " ms"); List files = finder.getFiles(); LOG.info("Unindexed files update started: " + files.size() + " files to update"); diff --git a/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java b/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java index 68cece670ad2..219f23bced4f 100644 --- a/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java +++ b/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java @@ -16,12 +16,13 @@ package com.intellij.ide.caches; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.vfs.VirtualFile; public interface CacheUpdater { int getNumberOfPendingUpdateJobs(); - VirtualFile[] queryNeededFiles(); + VirtualFile[] queryNeededFiles(ProgressIndicator indicator); void processFile(FileContent fileContent); diff --git a/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java b/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java index 51c59a3eb1cc..92e4002c5578 100644 --- a/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java +++ b/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbServiceImpl; import com.intellij.openapi.project.Project; @@ -48,7 +49,7 @@ public class ToggleDumbModeAction extends AnAction implements DumbAware { return 0; } - public VirtualFile[] queryNeededFiles() { + public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) { while (myDumb) { try { Thread.sleep(100); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index ddcdc4150324..cd634ec99ef5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -544,6 +544,9 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application public void dispose() { fireApplicationExiting(); + + ShutDownTracker.getInstance().ensureStopperThreadsFinished(); + disposeComponents(); ourThreadExecutorsService.shutdownNow(); diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index 298403bc1585..3583bfe99be4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -20,29 +20,22 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ex.ApplicationEx; -import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.progress.*; import com.intellij.openapi.progress.util.ProgressWindow; import com.intellij.openapi.progress.util.SmoothProgressAdapter; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; import com.intellij.psi.PsiLock; import com.intellij.ui.SystemNotifications; -import com.intellij.util.containers.SortedList; -import gnu.trove.THashMap; import org.jetbrains.annotations.*; import javax.swing.*; import java.awt.*; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.Comparator; -import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; public class ProgressManagerImpl extends ProgressManager implements Disposable{ @@ -57,7 +50,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ @NonNls private static final String NAME = "Progress Cancel Checker"; private static final boolean DISABLED = Comparing.equal(System.getProperty(PROCESS_CANCELED_EXCEPTION), "disabled"); - private static final Map myWastedTime = new THashMap(); private volatile boolean enabled = true; public ProgressManagerImpl(Application application) { @@ -274,7 +266,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ else { task.onCancel(); } - moreTimeWasted(time, task); return result; } @@ -362,7 +353,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { task.onCancel(); - moreTimeWasted(time, task); } }, ModalityState.NON_MODAL); } @@ -377,7 +367,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { task.onSuccess(); - moreTimeWasted(time, task); } }, ModalityState.NON_MODAL); } @@ -395,40 +384,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ } } - private static void moreTimeWasted(long time, Task timeEater) { - if (!ApplicationManagerEx.getApplicationEx().isInternal()) return; - - synchronized (myWastedTime) { - String title = timeEater.getTitle(); - Long total = myWastedTime.get(title); - myWastedTime.put(title, total == null ? time : total + time); - } - } - - public static long getWastedTime() { - synchronized (myWastedTime) { - long result = 0; - for (Map.Entry each : myWastedTime.entrySet()) { - result += each.getValue(); - } - return result; - } - } - - public static List> getTimeWasters() { - synchronized (myWastedTime) { - SortedList> result = new SortedList>(new Comparator>() { - public int compare(Pair o1, Pair o2) { - return o2.second.compareTo(o1.second); - } - }); - for (Map.Entry each : myWastedTime.entrySet()) { - result.add(Pair.create(each.getKey(), each.getValue())); - } - return result; - } - } - public void run(@NotNull final Task task) { if (task.isHeadless()) { new TaskRunnable(task, new EmptyProgressIndicator()).run(); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateSession.java b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateSession.java index 2dea17c17175..7b6f8ae021bd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateSession.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateSession.java @@ -48,7 +48,7 @@ public class CacheUpdateSession { indicator.checkCanceled(); try { jobsCount += each.getNumberOfPendingUpdateJobs(); - List updaterFiles = Arrays.asList(each.queryNeededFiles()); + List updaterFiles = Arrays.asList(each.queryNeededFiles(indicator)); processedUpdaters.add(each); myFilesToUpdate.addAll(updaterFiles); myUpdatersWithFiles.add(Pair.create(each, (Collection)new THashSet(updaterFiles))); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index 857a5e094fdb..a474a9e0f242 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -26,6 +26,7 @@ import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.BalloonHandler; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.wm.AppIconScheme; import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.WindowManager; @@ -293,7 +294,7 @@ public class DumbServiceImpl extends DumbService { @Override public void finish(@NotNull TaskInfo task) { - UIUtil.invokeAndWaitIfNeeded(new Runnable() { + UIUtil.invokeLaterIfNeeded(new Runnable() { public void run() { AppIcon appIcon = AppIcon.getInstance(); if (appIcon.hideProgress("indexUpdate")) { @@ -327,11 +328,15 @@ public class DumbServiceImpl extends DumbService { } }); + final ShutDownTracker shutdownTracker = ShutDownTracker.getInstance(); + final Thread self = Thread.currentThread(); try { HeavyProcessLatch.INSTANCE.processStarted(); + shutdownTracker.registerStopperThread(self); runAction(proxy, myAction); } finally { + shutdownTracker.unregisterStopperThread(self); HeavyProcessLatch.INSTANCE.processFinished(); } } diff --git a/platform/util/src/com/intellij/openapi/util/ShutDownTracker.java b/platform/util/src/com/intellij/openapi/util/ShutDownTracker.java index 4958360f44ec..b4b50d0e4cf4 100644 --- a/platform/util/src/com/intellij/openapi/util/ShutDownTracker.java +++ b/platform/util/src/com/intellij/openapi/util/ShutDownTracker.java @@ -52,26 +52,8 @@ public class ShutDownTracker implements Runnable { public void run() { myIsShutdownHookRunning = true; - Thread[] threads = getStopperThreads(); - while (threads.length > 0) { - Thread thread = threads[0]; - if (!thread.isAlive()) { - if (isRegistered(thread)) { - LOG.error("Thread '" + thread.getName() + "' did not unregister itself from ShutDownTracker."); - unregisterStopperThread(thread); - } - } - else { - try { - thread.join(100); - } - catch (InterruptedException ignored) { - } - } - threads = getStopperThreads(); - } - - + ensureStopperThreadsFinished(); + for (Runnable task = removeLast(myShutdownTasks); task != null; task = removeLast(myShutdownTasks)) { // task can change myShutdownTasks try { @@ -92,6 +74,27 @@ public class ShutDownTracker implements Runnable { } } + public final void ensureStopperThreadsFinished() { + Thread[] threads = getStopperThreads(); + while (threads.length > 0) { + Thread thread = threads[0]; + if (!thread.isAlive()) { + if (isRegistered(thread)) { + LOG.error("Thread '" + thread.getName() + "' did not unregister itself from ShutDownTracker."); + unregisterStopperThread(thread); + } + } + else { + try { + thread.join(100); + } + catch (InterruptedException ignored) { + } + } + threads = getStopperThreads(); + } + } + private synchronized boolean isRegistered(@NotNull Thread thread) { return myThreads.contains(thread); }