mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
treeui race conditions look fixed
This commit is contained in:
@@ -18,7 +18,6 @@ package com.intellij.ide.util.treeView;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Log;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.*;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
@@ -1640,8 +1639,6 @@ public class AbstractTreeUi {
|
||||
private ActionCallback resetToReadyNow() {
|
||||
assertIsDispatchThread();
|
||||
|
||||
Log.print("resetToReadyNow children=" + myUpdatingChildren + " loadedInBg=" + myLoadedInBackground + " workers=" + myActiveWorkerTasks);
|
||||
|
||||
DefaultMutableTreeNode[] uc = myUpdatingChildren.toArray(new DefaultMutableTreeNode[myUpdatingChildren.size()]);
|
||||
for (DefaultMutableTreeNode each : uc) {
|
||||
resetIncompleteNode(each);
|
||||
@@ -1764,13 +1761,18 @@ public class AbstractTreeUi {
|
||||
|
||||
private void executeYieldingRequest(Runnable runnable, TreeUpdatePass pass) {
|
||||
try {
|
||||
myYeildingPasses.remove(pass);
|
||||
runnable.run();
|
||||
}
|
||||
finally {
|
||||
if (!isReleased()) {
|
||||
maybeYeildingFinished();
|
||||
try {
|
||||
myYeildingPasses.remove(pass);
|
||||
runnable.run();
|
||||
}
|
||||
finally {
|
||||
if (!isReleased()) {
|
||||
maybeYeildingFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
resetToReady();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1789,6 +1791,9 @@ public class AbstractTreeUi {
|
||||
if (isReady()) {
|
||||
myRevalidatedObjects.clear();
|
||||
|
||||
setCancelRequested(false);
|
||||
myResettingToReadyNow.set(false);
|
||||
|
||||
myInitialized.setDone();
|
||||
|
||||
if (canInitiateNewActivity()) {
|
||||
@@ -2079,8 +2084,6 @@ public class AbstractTreeUi {
|
||||
|
||||
setCancelRequested(true);
|
||||
|
||||
Log.print("cancelUpdate requested isReleased=" + isReleased() + " cancelProcessed=" + isCancelProcessed());
|
||||
|
||||
final ActionCallback done = new ActionCallback();
|
||||
|
||||
invokeLaterIfNeeded(new Runnable() {
|
||||
@@ -2091,19 +2094,15 @@ public class AbstractTreeUi {
|
||||
}
|
||||
|
||||
if (myResettingToReadyNow.get()) {
|
||||
Log.print("1");
|
||||
getReady(this).notify(done);
|
||||
} else if (isReady()) {
|
||||
Log.print("2");
|
||||
resetToReadyNow();
|
||||
done.setDone();
|
||||
} else {
|
||||
if (isIdle() && hasPendingWork()) {
|
||||
Log.print("3");
|
||||
resetToReadyNow();
|
||||
done.setDone();
|
||||
} else {
|
||||
Log.print("4 cancelProcessed=" + isCancelProcessed());
|
||||
getReady(this).notify(done);
|
||||
}
|
||||
}
|
||||
@@ -2147,7 +2146,14 @@ public class AbstractTreeUi {
|
||||
|
||||
try {
|
||||
progressive.run(indicator);
|
||||
} finally {
|
||||
} catch (ProcessCanceledException e) {
|
||||
resetToReadyNow().doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
callback.setRejected();
|
||||
}
|
||||
});
|
||||
return callback;
|
||||
}finally {
|
||||
if (isReleased()) return new ActionCallback.Rejected();
|
||||
|
||||
getReady(this).doWhenDone(new Runnable() {
|
||||
@@ -3091,7 +3097,6 @@ public class AbstractTreeUi {
|
||||
|
||||
private void registerWorkerTask(Runnable runnable, Object id) {
|
||||
synchronized (myActiveWorkerTasks) {
|
||||
Log.print("worker started canDoNewActivity=" + canInitiateNewActivity() + " id=" + id);
|
||||
myActiveWorkerTasks.add(runnable);
|
||||
}
|
||||
}
|
||||
@@ -3101,9 +3106,6 @@ public class AbstractTreeUi {
|
||||
|
||||
synchronized (myActiveWorkerTasks) {
|
||||
wasRemoved = myActiveWorkerTasks.remove(runnable);
|
||||
if (wasRemoved) {
|
||||
Log.print("worker finished id=" + id);
|
||||
}
|
||||
}
|
||||
|
||||
if (wasRemoved && finalizeRunnable != null) {
|
||||
@@ -3714,32 +3716,37 @@ public class AbstractTreeUi {
|
||||
final boolean checkIfInStructure,
|
||||
final boolean canSmartExpand) {
|
||||
|
||||
runDone(new Runnable() {
|
||||
public void run() {
|
||||
if (element.length == 0) {
|
||||
runDone(onDone);
|
||||
return;
|
||||
}
|
||||
|
||||
if (myUpdaterState != null) {
|
||||
myUpdaterState.clearExpansion();
|
||||
}
|
||||
|
||||
|
||||
final ActionCallback done = new ActionCallback(element.length);
|
||||
done.doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
runDone(new Runnable() {
|
||||
public void run() {
|
||||
if (element.length == 0) {
|
||||
runDone(onDone);
|
||||
return;
|
||||
}
|
||||
}).doWhenRejected(new Runnable() {
|
||||
public void run() {
|
||||
runDone(onDone);
|
||||
}
|
||||
});
|
||||
|
||||
expandNext(element, 0, parentsOnly, checkIfInStructure, canSmartExpand, done, 0);
|
||||
}
|
||||
});
|
||||
if (myUpdaterState != null) {
|
||||
myUpdaterState.clearExpansion();
|
||||
}
|
||||
|
||||
|
||||
final ActionCallback done = new ActionCallback(element.length);
|
||||
done.doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
runDone(onDone);
|
||||
}
|
||||
}).doWhenRejected(new Runnable() {
|
||||
public void run() {
|
||||
runDone(onDone);
|
||||
}
|
||||
});
|
||||
|
||||
expandNext(element, 0, parentsOnly, checkIfInStructure, canSmartExpand, done, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
runDone(onDone);
|
||||
}
|
||||
}
|
||||
|
||||
private void expandNext(final Object[] elements,
|
||||
@@ -4230,7 +4237,6 @@ public class AbstractTreeUi {
|
||||
return;
|
||||
}
|
||||
|
||||
//myRequestedExpand = null;
|
||||
|
||||
final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.intellij.ide.util.treeView;
|
||||
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
|
||||
@@ -57,7 +57,6 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
}
|
||||
|
||||
public void testCancelUpdate() throws Exception {
|
||||
System.out.println("TreeUiTest.testCancelUpdate --------------------");
|
||||
assertInterruption(Interruption.invokeCancel);
|
||||
}
|
||||
|
||||
@@ -917,8 +916,6 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
}
|
||||
|
||||
private void assertInterruption(Interruption cancelled) throws Exception {
|
||||
Log.print("assert interruption started ");
|
||||
|
||||
buildStructure(myRoot);
|
||||
|
||||
expand(getPath("/"));
|
||||
@@ -937,25 +934,18 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
" -xunit\n" +
|
||||
" runner\n");
|
||||
|
||||
Log.print("--------------- 1 ready=" + getBuilder().getUi().isReady());
|
||||
runAndInterrupt(new MyRunnable() {
|
||||
public void runSafe() throws Exception {
|
||||
updateFrom(new NodeElement("/"));
|
||||
}
|
||||
}, "update", new NodeElement("jetbrains"), cancelled);
|
||||
|
||||
Log.print("--------------- 1 PASSED ready=" + getBuilder().getUi().isReady());
|
||||
|
||||
Log.print("--------------- 2 ready=" + getBuilder().getUi().isReady());
|
||||
runAndInterrupt(new MyRunnable() {
|
||||
@Override
|
||||
public void runSafe() throws Exception {
|
||||
updateFrom(new NodeElement("/"));
|
||||
}
|
||||
}, "getChildren", new NodeElement("jetbrains"), cancelled);
|
||||
Log.print("--------------- 2 PASSED ready=" + getBuilder().getUi().isReady());
|
||||
|
||||
Log.print("assert interruption finished ");
|
||||
}
|
||||
|
||||
|
||||
@@ -1019,8 +1009,6 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
private void runAndInterrupt(final Runnable action, final String interruptAction, final Object interruptElement, final Interruption interruption) throws Exception {
|
||||
myElementUpdate.clear();
|
||||
|
||||
Log.print("runAndInterrupt action=" + interruptAction + " element=" + interruptElement + " cancelRequest=" + myCancelRequest + " interruption=" + interruption + " builder=" + getBuilder());
|
||||
|
||||
final Ref<Thread> thread = new Ref<Thread>();
|
||||
|
||||
final boolean[] wasInterrupted = new boolean[] {false};
|
||||
@@ -1031,22 +1019,15 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
}
|
||||
|
||||
|
||||
if (thread.get() != Thread.currentThread()) {
|
||||
Log.print("FFFFFFFFFFUUUUUUUUUUUUUCCCCCCCCCCCCKKKKKKKKK!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
|
||||
boolean toInterrupt = element.equals(interruptElement) && action.equals(interruptAction);
|
||||
Log.print("-- onElementAction action=" + action + " element=" + element + " wasInterrupted=" + wasInterrupted[0] + " toInterrupt=" + toInterrupt + " cancelProcessed" + getBuilder().getUi().isCancelProcessed());
|
||||
|
||||
if (wasInterrupted[0]) {
|
||||
if (myCancelRequest == null) {
|
||||
String status = getBuilder().getUi().getStatus();
|
||||
Log.print("!!!! status=" + status);
|
||||
myCancelRequest = new AssertionError("Not supposed to be update after interruption request: action=" + action + " element=" + element + " interruptAction=" + interruptAction + " interruptElement=" + interruptElement);
|
||||
}
|
||||
} else {
|
||||
if (toInterrupt) {
|
||||
Log.print("-- send interruption ready=" + getBuilder().getUi().isReady());
|
||||
wasInterrupted[0] = true;
|
||||
switch (interruption) {
|
||||
case throwProcessCancelled:
|
||||
@@ -1933,9 +1914,9 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
|
||||
|
||||
public static TestSuite suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
//suite.addTestSuite(Passthrough.class);
|
||||
//suite.addTestSuite(SyncUpdate.class);
|
||||
//suite.addTestSuite(YieldingUpdate.class);
|
||||
suite.addTestSuite(Passthrough.class);
|
||||
suite.addTestSuite(SyncUpdate.class);
|
||||
suite.addTestSuite(YieldingUpdate.class);
|
||||
suite.addTestSuite(VeryQuickBgLoadingSyncUpdate.class);
|
||||
suite.addTestSuite(QuickBgLoadingSyncUpdate.class);
|
||||
suite.addTestSuite(BgLoadingSyncUpdate.class);
|
||||
|
||||
Reference in New Issue
Block a user