@Override public boolean runInReadActionWithWriteActionPriority(@NotNull Runnable action) { if (ApplicationManager.getApplication().isReadAccessAllowed()) { throw new AssertionError( "runInReadActionWithWriteActionPriority shouldn't be invoked from read action"); } boolean success = ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(action); if (!success) { ProgressIndicatorUtils.yieldToPendingWriteActions(); } return success; }
void execute(BrowseMode browseMode) { myBrowseMode = browseMode; Document document = myEditor.getDocument(); final PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document); if (file == null) return; PsiDocumentManager.getInstance(myProject).commitAllDocuments(); if (EditorUtil.inVirtualSpace(myEditor, myPosition)) { return; } final int offset = myEditor.logicalPositionToOffset(myPosition); int selStart = myEditor.getSelectionModel().getSelectionStart(); int selEnd = myEditor.getSelectionModel().getSelectionEnd(); if (offset >= selStart && offset < selEnd) return; ProgressIndicatorUtils.scheduleWithWriteActionPriority( myProgress, new ReadTask() { @Override public void computeInReadAction(@NotNull ProgressIndicator indicator) { doExecute(file, offset); } @Override public void onCanceled(@NotNull ProgressIndicator indicator) {} }); }
@Override public void onCanceled(@NotNull ProgressIndicator indicator) { if (!myProject.isDisposed()) { ProgressIndicatorUtils.scheduleWithWriteActionPriority(this); } }
private void processBatch( @NotNull final ProgressIndicator indicator, @NotNull Set<VirtualFile> files) { assert !myApplication.isDispatchThread(); final int resolvedInPreviousBatch = this.resolvedInPreviousBatch; final int totalSize = files.size() + resolvedInPreviousBatch; final ConcurrentIntObjectMap<int[]> fileToForwardIds = ContainerUtil.createConcurrentIntObjectMap(); final Set<VirtualFile> toProcess = Collections.synchronizedSet(files); indicator.setIndeterminate(false); ProgressIndicatorUtils.forceWriteActionPriority(indicator, (Disposable) indicator); long start = System.currentTimeMillis(); Processor<VirtualFile> processor = file -> { double fraction = 1 - toProcess.size() * 1.0 / totalSize; indicator.setFraction(fraction); try { if (!file.isDirectory() && toResolve(file, myProject)) { int fileId = getAbsId(file); int i = totalSize - toProcess.size(); indicator.setText(i + "/" + totalSize + ": Resolving " + file.getPresentableUrl()); int[] forwardIds = processFile(file, fileId, indicator); if (forwardIds == null) { // queueUpdate(file); return false; } fileToForwardIds.put(fileId, forwardIds); } toProcess.remove(file); return true; } catch (RuntimeException e) { indicator.checkCanceled(); } return true; }; boolean success = true; try { success = processFilesConcurrently(files, indicator, processor); } finally { this.resolvedInPreviousBatch = toProcess.isEmpty() ? 0 : totalSize - toProcess.size(); queue(toProcess, "re-added after fail. success=" + success); storeIds(fileToForwardIds); long end = System.currentTimeMillis(); log( "Resolved batch of " + (totalSize - toProcess.size()) + " from " + totalSize + " files in " + ((end - start) / 1000) + "sec. (Gap: " + storage.gap + ")"); synchronized (filesToResolve) { upToDate = filesToResolve.isEmpty(); log("upToDate = " + upToDate); if (upToDate) { for (Listener listener : myListeners) { listener.allFilesResolved(); } } } } }