mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
TreeUi: correct dispose during building
This commit is contained in:
@@ -258,7 +258,7 @@ public class AbstractTreeBuilder implements Disposable {
|
||||
}
|
||||
|
||||
public final boolean isDisposed() {
|
||||
return getUi() == null || getUi().isReleased();
|
||||
return getUi() == null || getUi().isReleaseRequested();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,7 +386,10 @@ public class AbstractTreeBuilder implements Disposable {
|
||||
public void dispose() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
myUi.release();
|
||||
myUi.requestRelease();
|
||||
}
|
||||
|
||||
void releaseUi() {
|
||||
myUi = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ public class AbstractTreeUi {
|
||||
|
||||
private UpdaterTreeState myUpdaterState;
|
||||
private AbstractTreeBuilder myBuilder;
|
||||
private boolean myReleaseRequested;
|
||||
|
||||
private final Set<DefaultMutableTreeNode> myUpdatingChildren = new HashSet<DefaultMutableTreeNode>();
|
||||
private long myJanitorPollPeriod = Time.SECOND * 10;
|
||||
@@ -187,14 +188,14 @@ public class AbstractTreeUi {
|
||||
public void showNotify() {
|
||||
myShowing = true;
|
||||
myWasEverShown = true;
|
||||
if (!isReleased()) {
|
||||
if (!isReleaseRequested()) {
|
||||
activate(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void hideNotify() {
|
||||
myShowing = false;
|
||||
if (!isReleased()) {
|
||||
if (!validateReleaseRequested()) {
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
@@ -268,7 +269,7 @@ public class AbstractTreeUi {
|
||||
protected void doCleanUp() {
|
||||
Runnable cleanup = new Runnable() {
|
||||
public void run() {
|
||||
if (!isReleased()) {
|
||||
if (!isReleaseRequested()) {
|
||||
cleanUpNow();
|
||||
}
|
||||
}
|
||||
@@ -323,10 +324,19 @@ public class AbstractTreeUi {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestRelease() {
|
||||
if (isReleaseRequested()) return;
|
||||
|
||||
public void release() {
|
||||
if (isReleased()) return;
|
||||
assertIsDispatchThread();
|
||||
|
||||
myReleaseRequested = true;
|
||||
|
||||
getUpdater().requestRelease();
|
||||
|
||||
maybeReady();
|
||||
}
|
||||
|
||||
private void releaseNow() {
|
||||
myTree.removeTreeExpansionListener(myExpansionListener);
|
||||
myTree.removeTreeSelectionListener(mySelectionListener);
|
||||
myTree.removeFocusListener(myFocusListener);
|
||||
@@ -347,8 +357,8 @@ public class AbstractTreeUi {
|
||||
myTree = null;
|
||||
setUpdater(null);
|
||||
myWorker = null;
|
||||
//todo [kirillk] afraid to do so just in release day, to uncomment
|
||||
// myTreeStructure = null;
|
||||
myTreeStructure = null;
|
||||
myBuilder.releaseUi();
|
||||
myBuilder = null;
|
||||
|
||||
clearNodeActions();
|
||||
@@ -358,6 +368,23 @@ public class AbstractTreeUi {
|
||||
myYeildingDoneRunnables.clear();
|
||||
}
|
||||
|
||||
public boolean isReleaseRequested() {
|
||||
return myReleaseRequested;
|
||||
}
|
||||
|
||||
public boolean validateReleaseRequested() {
|
||||
if (isReleaseRequested()) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
maybeReady();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReleased() {
|
||||
return myBuilder == null;
|
||||
}
|
||||
@@ -366,9 +393,13 @@ public class AbstractTreeUi {
|
||||
if (!myUnbuiltNodes.contains(node)) return;
|
||||
if (isLoadedInBackground(getElementFor(node))) return;
|
||||
|
||||
getTreeStructure().commit();
|
||||
addSubtreeToUpdate(node);
|
||||
getUpdater().performUpdate();
|
||||
if (!isReleaseRequested()) {
|
||||
getTreeStructure().commit();
|
||||
addSubtreeToUpdate(node);
|
||||
getUpdater().performUpdate();
|
||||
} else {
|
||||
processNodeActionsIfReady(node);
|
||||
}
|
||||
}
|
||||
|
||||
public final AbstractTreeStructure getTreeStructure() {
|
||||
@@ -710,7 +741,7 @@ public class AbstractTreeUi {
|
||||
else {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
if (!isReleased()) {
|
||||
if (!validateReleaseRequested()) {
|
||||
result.setDone(_update(nodeDescriptor));
|
||||
}
|
||||
else {
|
||||
@@ -1067,6 +1098,7 @@ public class AbstractTreeUi {
|
||||
.doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed(node)) {
|
||||
removeFromUpdating(node);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1106,10 +1138,17 @@ public class AbstractTreeUi {
|
||||
}).doWhenProcessed(new Runnable() {
|
||||
public void run() {
|
||||
myWillBeExpaned.remove(node);
|
||||
removeFromUpdating(node);
|
||||
processNodeActionsIfReady(node);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}).doWhenRejected(new Runnable() {
|
||||
public void run() {
|
||||
removeFromUpdating(node);
|
||||
processNodeActionsIfReady(node);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isDisposed(DefaultMutableTreeNode node) {
|
||||
@@ -1343,9 +1382,17 @@ public class AbstractTreeUi {
|
||||
else {
|
||||
if (isToYieldUpdateFor(node)) {
|
||||
pass.setCurrentNode(node);
|
||||
yieldAndRun(new Runnable() {
|
||||
boolean wasRun = yieldAndRun(new Runnable() {
|
||||
public void run() {
|
||||
if (pass.isExpired()) return;
|
||||
if (validateReleaseRequested()) {
|
||||
result.setRejected();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass.isExpired()) {
|
||||
result.setRejected();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRerunNeeded(pass)) {
|
||||
runDone(new Runnable() {
|
||||
@@ -1362,6 +1409,9 @@ public class AbstractTreeUi {
|
||||
}
|
||||
}
|
||||
}, pass);
|
||||
if (!wasRun) {
|
||||
result.setRejected();
|
||||
}
|
||||
}
|
||||
else {
|
||||
processRunnable.run().notify(result);
|
||||
@@ -1371,25 +1421,22 @@ public class AbstractTreeUi {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void yieldAndRun(final Runnable runnable, final TreeUpdatePass pass) {
|
||||
private boolean yieldAndRun(final Runnable runnable, final TreeUpdatePass pass) {
|
||||
if (validateReleaseRequested()) return false;
|
||||
|
||||
myYeildingPasses.add(pass);
|
||||
myYeildingNow = true;
|
||||
yield(new Runnable() {
|
||||
public void run() {
|
||||
if (isReleased()) {
|
||||
return;
|
||||
}
|
||||
|
||||
runOnYieldingDone(new Runnable() {
|
||||
public void run() {
|
||||
if (isReleased()) {
|
||||
return;
|
||||
}
|
||||
executeYieldingRequest(runnable, pass);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isYeildingNow() {
|
||||
@@ -1433,6 +1480,11 @@ public class AbstractTreeUi {
|
||||
if (isReleased()) return;
|
||||
|
||||
if (isReady()) {
|
||||
if (isReleaseRequested()) {
|
||||
releaseNow();
|
||||
return;
|
||||
}
|
||||
|
||||
if (myTree.isShowing() || myUpdateIfInactive) {
|
||||
myInitialized.setDone();
|
||||
}
|
||||
@@ -1785,6 +1837,8 @@ public class AbstractTreeUi {
|
||||
private boolean queueBackgroundUpdate(final UpdateInfo updateInfo, final DefaultMutableTreeNode node) {
|
||||
assertIsDispatchThread();
|
||||
|
||||
if (validateReleaseRequested()) return false;
|
||||
|
||||
final Object oldElementFromDescriptor = getElementFromDescriptor(updateInfo.getDescriptor());
|
||||
|
||||
UpdateInfo loaded = getLoadedInBackground(oldElementFromDescriptor);
|
||||
@@ -1804,10 +1858,6 @@ public class AbstractTreeUi {
|
||||
final Ref<Object> elementFromDescriptor = new Ref<Object>();
|
||||
Runnable buildRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (isReleased()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!updateInfo.isDescriptorIsUpToDate()) {
|
||||
update(updateInfo.getDescriptor(), true);
|
||||
}
|
||||
@@ -1834,7 +1884,6 @@ public class AbstractTreeUi {
|
||||
final DefaultMutableTreeNode[] nodeToProcessActions = new DefaultMutableTreeNode[1];
|
||||
Runnable updateRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (isReleased()) return;
|
||||
if (children.get() == null) return;
|
||||
|
||||
if (isRerunNeeded(updateInfo.getPass())) {
|
||||
@@ -2418,37 +2467,27 @@ public class AbstractTreeUi {
|
||||
protected void queueToBackground(@NotNull final Runnable bgBuildAction,
|
||||
@Nullable final Runnable edtPostRunnable,
|
||||
@Nullable final Runnable finalizeEdtRunnable) {
|
||||
if (validateReleaseRequested()) return;
|
||||
|
||||
registerWorkerTask(bgBuildAction);
|
||||
|
||||
final Runnable pooledThreadWithProgressRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (isReleased()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final AbstractTreeBuilder builder = getBuilder();
|
||||
|
||||
builder.runBackgroundLoading(new Runnable() {
|
||||
public void run() {
|
||||
assertNotDispatchThread();
|
||||
|
||||
if (isReleased()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
bgBuildAction.run();
|
||||
|
||||
if (edtPostRunnable != null && !isReleased()) {
|
||||
if (edtPostRunnable != null) {
|
||||
builder.updateAfterLoadedInBackground(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
assertIsDispatchThread();
|
||||
|
||||
if (isReleased()) {
|
||||
return;
|
||||
}
|
||||
|
||||
edtPostRunnable.run();
|
||||
}
|
||||
finally {
|
||||
@@ -2475,8 +2514,6 @@ public class AbstractTreeUi {
|
||||
|
||||
Runnable pooledThreadRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (isReleased()) return;
|
||||
|
||||
try {
|
||||
if (myProgress != null) {
|
||||
ProgressManager.getInstance().runProcess(pooledThreadWithProgressRunnable, myProgress);
|
||||
@@ -2690,8 +2727,12 @@ public class AbstractTreeUi {
|
||||
return false;
|
||||
}
|
||||
|
||||
getUpdater().runAfterUpdate(runAfterUpdate);
|
||||
getUpdater().addSubtreeToUpdate(root);
|
||||
if (isReleaseRequested()) {
|
||||
processNodeActionsIfReady(root);
|
||||
} else {
|
||||
getUpdater().runAfterUpdate(runAfterUpdate);
|
||||
getUpdater().addSubtreeToUpdate(root);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3040,6 +3081,10 @@ public class AbstractTreeUi {
|
||||
public void run() {
|
||||
runDone(onDone);
|
||||
}
|
||||
}).doWhenRejected(new Runnable() {
|
||||
public void run() {
|
||||
runDone(onDone);
|
||||
}
|
||||
});
|
||||
|
||||
expandNext(element, 0, parentsOnly, checkIfInStructure, canSmartExpand, done);
|
||||
@@ -3078,7 +3123,6 @@ public class AbstractTreeUi {
|
||||
}
|
||||
|
||||
private void runDone(@Nullable Runnable done) {
|
||||
if (isReleased()) return;
|
||||
if (done == null) return;
|
||||
|
||||
if (isYeildingNow()) {
|
||||
@@ -3171,7 +3215,6 @@ public class AbstractTreeUi {
|
||||
|
||||
addNodeAction(element, new NodeAction() {
|
||||
public void onReady(final DefaultMutableTreeNode node) {
|
||||
|
||||
if (node.getChildCount() > 0 && !myTree.isExpanded(new TreePath(node.getPath()))) {
|
||||
if (!isAutoExpand(node)) {
|
||||
expand(node, canSmartExpand);
|
||||
@@ -3254,6 +3297,8 @@ public class AbstractTreeUi {
|
||||
}
|
||||
|
||||
public final boolean isNodeBeingBuilt(Object node) {
|
||||
if (isReleaseRequested()) return false;
|
||||
|
||||
return getParentBuiltNode(node) != null;
|
||||
}
|
||||
|
||||
@@ -3456,7 +3501,7 @@ public class AbstractTreeUi {
|
||||
|
||||
|
||||
private void cleanUpNow() {
|
||||
if (isReleased()) return;
|
||||
if (isReleaseRequested()) return;
|
||||
|
||||
final UpdaterTreeState state = new UpdaterTreeState(this);
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ public class AbstractTreeUpdater implements Disposable, Activatable {
|
||||
private final MergingUpdateQueue myUpdateQueue;
|
||||
|
||||
private long myUpdateCount;
|
||||
private boolean myReleaseRequested;
|
||||
|
||||
public AbstractTreeUpdater(AbstractTreeBuilder treeBuilder) {
|
||||
myTreeBuilder = treeBuilder;
|
||||
@@ -96,13 +97,10 @@ public class AbstractTreeUpdater implements Disposable, Activatable {
|
||||
}
|
||||
|
||||
public synchronized void addSubtreeToUpdate(@NotNull TreeUpdatePass toAdd) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("addSubtreeToUpdate:" + toAdd.getNode());
|
||||
}
|
||||
if (myReleaseRequested) return;
|
||||
|
||||
assert !toAdd.isExpired();
|
||||
|
||||
|
||||
|
||||
final AbstractTreeUi ui = myTreeBuilder.getUi();
|
||||
|
||||
if (ui.isUpdatingNow(toAdd.getNode())) {
|
||||
@@ -363,4 +361,12 @@ public class AbstractTreeUpdater implements Disposable, Activatable {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void requestRelease() {
|
||||
myReleaseRequested = true;
|
||||
|
||||
myNodeQueue.clear();
|
||||
myUpdateQueue.cancelAllUpdates();
|
||||
myUpdateQueue.deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user