mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
background task queue: allow to specify modality and custom progress for the task
This commit is contained in:
@@ -17,15 +17,18 @@ package com.intellij.util.concurrency;
|
||||
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.AsynchConsumer;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PairConsumer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>QueueProcessor processes elements which are being added to a queue via {@link #add(Object)} and {@link #addFirst(Object)} methods.</p>
|
||||
@@ -48,6 +51,7 @@ public class QueueProcessor<T> {
|
||||
|
||||
private final ThreadToUse myThreadToUse;
|
||||
private final Condition<?> myDeathCondition;
|
||||
private final Map<MyOverrideEquals, ModalityState> myModalityState;
|
||||
|
||||
/**
|
||||
* Constructs a QueueProcessor with the given processor and autostart setting.
|
||||
@@ -65,6 +69,7 @@ public class QueueProcessor<T> {
|
||||
myStarted = autostart;
|
||||
myThreadToUse = threadToUse;
|
||||
myDeathCondition = deathCondition;
|
||||
myModalityState = new HashMap<MyOverrideEquals, ModalityState>();
|
||||
|
||||
myContinuationContext = new Runnable() {
|
||||
@Override
|
||||
@@ -85,6 +90,11 @@ public class QueueProcessor<T> {
|
||||
this(wrappingProcessor(processor), autostart, ThreadToUse.POOLED, deathCondition);
|
||||
}
|
||||
|
||||
public void add(T t, ModalityState state) {
|
||||
myModalityState.put(new MyOverrideEquals(t), state);
|
||||
doAdd(t, false);
|
||||
}
|
||||
|
||||
private static<T> PairConsumer<T, Runnable> wrappingProcessor(final Consumer<T> processor) {
|
||||
return new PairConsumer<T, Runnable>() {
|
||||
@Override
|
||||
@@ -176,7 +186,12 @@ public class QueueProcessor<T> {
|
||||
};
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
if (ThreadToUse.AWT.equals(myThreadToUse)) {
|
||||
application.invokeLater(runnable);
|
||||
final ModalityState state = myModalityState.remove(new MyOverrideEquals(item));
|
||||
if (state != null) {
|
||||
application.invokeLater(runnable, state);
|
||||
} else {
|
||||
application.invokeLater(runnable);
|
||||
}
|
||||
} else {
|
||||
application.executeOnPooledThread(runnable);
|
||||
}
|
||||
@@ -193,4 +208,22 @@ public class QueueProcessor<T> {
|
||||
AWT,
|
||||
POOLED
|
||||
}
|
||||
|
||||
private static class MyOverrideEquals {
|
||||
private final Object myDelegate;
|
||||
|
||||
private MyOverrideEquals(Object delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myDelegate.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return ((MyOverrideEquals) obj).myDelegate == myDelegate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,21 @@
|
||||
package com.intellij.openapi.progress;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import com.intellij.util.concurrency.QueueProcessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Runs backgroundable tasks one by one.
|
||||
* To add a task to the queue use {@link #run(com.intellij.openapi.progress.Task.Backgroundable)}
|
||||
@@ -39,7 +44,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class BackgroundTaskQueue {
|
||||
private static final Logger LOG = Logger.getInstance(BackgroundTaskQueue.class.getName());
|
||||
//private final Project myProject;
|
||||
private final QueueProcessor<Task.Backgroundable> myProcessor;
|
||||
private final QueueProcessor<Pair<Task.Backgroundable, Getter<ProgressIndicator>>> myProcessor;
|
||||
private Boolean myForcedTestMode;
|
||||
|
||||
public BackgroundTaskQueue(@Nullable Project project, @NotNull String title) {
|
||||
@@ -48,7 +53,7 @@ public class BackgroundTaskQueue {
|
||||
|
||||
public BackgroundTaskQueue(@Nullable final Project project, @NotNull String title, final Boolean forcedHeadlessMode) {
|
||||
final boolean headless = forcedHeadlessMode != null ? forcedHeadlessMode : ApplicationManager.getApplication().isHeadlessEnvironment();
|
||||
myProcessor = new QueueProcessor<Task.Backgroundable>(headless ?
|
||||
myProcessor = new QueueProcessor<Pair<Task.Backgroundable, Getter<ProgressIndicator>>>(headless ?
|
||||
new BackgroundableHeadlessRunner() : new BackgroundableUnderProgressRunner(title, project), true,
|
||||
headless ? QueueProcessor.ThreadToUse.POOLED : QueueProcessor.ThreadToUse.AWT, new Condition<Object>() {
|
||||
@Override
|
||||
@@ -68,23 +73,28 @@ public class BackgroundTaskQueue {
|
||||
}
|
||||
|
||||
public void run(Task.Backgroundable task) {
|
||||
run(task, null, null);
|
||||
}
|
||||
|
||||
public void run(Task.Backgroundable task, final ModalityState state, final Getter<ProgressIndicator> pi) {
|
||||
if (isTestMode()) { // test tasks are executed in this thread without the progress manager
|
||||
RunBackgroundable.runIfBackgroundThread(task, new EmptyProgressIndicator(), null);
|
||||
} else {
|
||||
myProcessor.add(task);
|
||||
myProcessor.add(new Pair<Task.Backgroundable, Getter<ProgressIndicator>>(task, pi), state);
|
||||
}
|
||||
}
|
||||
|
||||
private static class BackgroundableHeadlessRunner implements PairConsumer<Task.Backgroundable, Runnable> {
|
||||
private static class BackgroundableHeadlessRunner implements PairConsumer<Pair<Task.Backgroundable, Getter<ProgressIndicator>>, Runnable> {
|
||||
@Override
|
||||
public void consume(Task.Backgroundable backgroundable, Runnable runnable) {
|
||||
public void consume(Pair<Task.Backgroundable, Getter<ProgressIndicator>> pair, Runnable runnable) {
|
||||
final Task.Backgroundable backgroundable = pair.getFirst();
|
||||
// synchronously
|
||||
ProgressManager.getInstance().run(backgroundable);
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
private static class BackgroundableUnderProgressRunner implements PairConsumer<Task.Backgroundable, Runnable> {
|
||||
private static class BackgroundableUnderProgressRunner implements PairConsumer<Pair<Task.Backgroundable, Getter<ProgressIndicator>>, Runnable> {
|
||||
private final String myTitle;
|
||||
private final Project myProject;
|
||||
|
||||
@@ -94,7 +104,8 @@ public class BackgroundTaskQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume(final Task.Backgroundable backgroundable, final Runnable runnable) {
|
||||
public void consume(final Pair<Task.Backgroundable, Getter<ProgressIndicator>> pair, final Runnable runnable) {
|
||||
final Task.Backgroundable backgroundable = pair.getFirst();
|
||||
final ProgressIndicator[] pi = new ProgressIndicator[1];
|
||||
final boolean taskTitleIsEmpty = StringUtil.isEmptyOrSpaces(backgroundable.getTitle());
|
||||
|
||||
@@ -112,7 +123,12 @@ public class BackgroundTaskQueue {
|
||||
pm.runProcessWithProgressSynchronously(wrappedTask, taskTitleIsEmpty ? myTitle : backgroundable.getTitle(),
|
||||
backgroundable.isCancellable(), myProject);
|
||||
} else {
|
||||
pi[0] = new BackgroundableProcessIndicator(backgroundable);
|
||||
if (pair.getSecond() != null) {
|
||||
pi[0] = pair.getSecond().get();
|
||||
}
|
||||
if (pi[0] == null) {
|
||||
pi[0] = new BackgroundableProcessIndicator(backgroundable);
|
||||
}
|
||||
if (taskTitleIsEmpty) {
|
||||
((BackgroundableProcessIndicator) pi[0]).setTitle(myTitle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user