shorten RefreshQueueImpl by using ReadAction.nonBlocking

GitOrigin-RevId: 4530628b533b30764a72db4c9c1ac7cade8f0138
This commit is contained in:
peter
2019-11-07 02:40:58 +00:00
committed by intellij-monorepo-bot
parent 203c44d2c2
commit 7bbe0d2500
@@ -1,14 +1,12 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.vfs.newvfs;
import com.intellij.concurrency.SensitiveProgressWrapper;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.*;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.diagnostic.FrequentEventDetector;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.AsyncFileListener;
import com.intellij.openapi.vfs.VfsBundle;
@@ -27,7 +25,6 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author max
@@ -43,16 +40,6 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
private int myBusyThreads;
private final TLongObjectHashMap<RefreshSession> mySessions = new TLongObjectHashMap<>();
private final FrequentEventDetector myEventCounter = new FrequentEventDetector(100, 100, FrequentEventDetector.Level.WARN);
private final AtomicLong myWriteActionCounter = new AtomicLong();
public RefreshQueueImpl() {
ApplicationManager.getApplication().addApplicationListener(new ApplicationListener() {
@Override
public void writeActionStarted(@NotNull Object action) {
myWriteActionCounter.incrementAndGet();
}
}, this);
}
public void execute(@NotNull RefreshSessionImpl session) {
if (session.isAsynchronous()) {
@@ -98,15 +85,19 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
private void scheduleAsynchronousPreprocessing(@NotNull RefreshSessionImpl session, @NotNull ModalityState modality) {
try {
myEventProcessingQueue.execute(() -> {
startRefreshActivity();
try (AccessToken ignored = HeavyProcessLatch.INSTANCE.processStarted("Processing VFS events. " + session)) {
processAndFireEvents(session, modality);
}
finally {
finishRefreshActivity();
}
});
ReadAction
.nonBlocking(() -> {
startRefreshActivity();
try (AccessToken ignored = HeavyProcessLatch.INSTANCE.processStarted("Processing VFS events. " + session)) {
return runAsyncListeners(session);
}
finally {
finishRefreshActivity();
}
})
.cancelWith(myRefreshIndicator)
.finishOnUiThread(modality, Runnable::run)
.submit(myEventProcessingQueue);
}
catch (RejectedExecutionException e) {
LOG.debug(e);
@@ -125,35 +116,14 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
}
}
private void processAndFireEvents(@NotNull RefreshSessionImpl session, @NotNull ModalityState modality) {
while (true) {
ProgressIndicator progress = new SensitiveProgressWrapper(myRefreshIndicator);
boolean success = ProgressIndicatorUtils.runWithWriteActionPriority(() -> tryProcessingEvents(session, modality), progress);
if (success) {
break;
}
ProgressIndicatorUtils.yieldToPendingWriteActions();
}
}
private void tryProcessingEvents(@NotNull RefreshSessionImpl session, @NotNull ModalityState modality) {
private static Runnable runAsyncListeners(@NotNull RefreshSessionImpl session) {
List<? extends VFileEvent> events = ContainerUtil.filter(session.getEvents(), e -> {
VirtualFile file = e instanceof VFileCreateEvent ? ((VFileCreateEvent)e).getParent() : e.getFile();
return file == null || file.isValid();
});
List<AsyncFileListener.ChangeApplier> appliers = AsyncEventSupport.runAsyncListeners(events);
long stamp = myWriteActionCounter.get();
ApplicationManager.getApplication().invokeLater(() -> {
if (stamp == myWriteActionCounter.get()) {
session.fireEvents(events, appliers);
}
else {
scheduleAsynchronousPreprocessing(session, modality);
}
}, modality);
return () -> session.fireEvents(events, appliers);
}
private void doScan(@NotNull RefreshSessionImpl session) {