mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
datarace
This commit is contained in:
@@ -51,6 +51,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -127,19 +128,21 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
}
|
||||
|
||||
public boolean queueCommit(@NonNls @NotNull String reason, @NotNull Document document, @NotNull Project project, @Nullable DocumentEvent event) {
|
||||
log("queueCommit called", document, false, reason, event);
|
||||
assert !isDisposed : "already disposed";
|
||||
|
||||
if (!project.isInitialized()) return false;
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
|
||||
if (psiFile == null) return false;
|
||||
|
||||
doQueue(document, project, getCommitStage(document), reason, event);
|
||||
return true;
|
||||
boolean added = doQueue(document, project, getCommitStage(document), reason, event);
|
||||
log("doQueue called", document, false, added);
|
||||
return added;
|
||||
}
|
||||
|
||||
private void doQueue(@NotNull Document document, @NotNull Project project, CommitStage start, @NonNls @NotNull String reason, @Nullable DocumentEvent event) {
|
||||
private boolean doQueue(@NotNull Document document, @NotNull Project project, CommitStage start, @NonNls @NotNull String reason, @Nullable DocumentEvent event) {
|
||||
synchronized (documentsToCommit) {
|
||||
if (!changeCommitStage(document, start, CommitStage.QUEUED_TO_COMMIT, false)) return;
|
||||
if (!changeCommitStage(document, start, CommitStage.QUEUED_TO_COMMIT, false)) return false;
|
||||
|
||||
Object[] documentTasks = documentsToCommit.toArray();
|
||||
for (Object o : documentTasks) {
|
||||
@@ -148,28 +151,33 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
ProgressIndicator current = document.getUserData(COMMIT_PROGRESS);
|
||||
if (current == null) {
|
||||
// already queued, not started yet
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
current.cancel(); // will be re-queued
|
||||
// cancel current commit process to re-queue
|
||||
current.cancel();
|
||||
removeCommitFromQueue(document);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
ProgressIndicator indicator = new ProgressIndicatorBase();
|
||||
indicator.start();
|
||||
documentsToCommit.addLast(new CommitTask(document, project, indicator, reason, event));
|
||||
log("Queued", document, false, reason);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private final StringBuilder log = new StringBuilder();
|
||||
private void log(@NonNls String msg, Document document, boolean synchronously, @NonNls Object... args) {
|
||||
void log(@NonNls String msg, Document document, boolean synchronously, @NonNls Object... args) {
|
||||
if (true) return;
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
String s = msg + (synchronously ? " (sync)" : "") +
|
||||
String s = (SwingUtilities.isEventDispatchThread() ? " " : "") +
|
||||
msg + (synchronously ? " (sync)" : "") +
|
||||
(document == null ? "" : "; Document: " + System.identityHashCode(document) +
|
||||
"; stage: " + getCommitStage(document))
|
||||
+ "; my indic="+myProgressIndicator;
|
||||
+ "; my indic="+myProgressIndicator + " ||";
|
||||
|
||||
for (Object arg : args) {
|
||||
s += "; "+arg;
|
||||
@@ -204,11 +212,11 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
private static class CommitTask {
|
||||
private final Document document;
|
||||
private final Project project;
|
||||
// running = false means document was removed from the queue, should ignore.
|
||||
// canceled = true means commit was canceled, should reschedule for later.
|
||||
private final ProgressIndicator indicator; // progress to commit this doc under.
|
||||
private final String reason;
|
||||
@Nullable private final DocumentEvent event;
|
||||
// running = false means document was removed from the queue, should ignore.
|
||||
// canceled = true means commit was canceled, should reschedule for later.
|
||||
|
||||
private CommitTask(@NotNull Document document,
|
||||
@NotNull Project project,
|
||||
@@ -261,8 +269,11 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
|
||||
log("Pulled", document, false, indicator);
|
||||
|
||||
if (getCommitStage(document) != CommitStage.QUEUED_TO_COMMIT
|
||||
CommitStage commitStage = getCommitStage(document);
|
||||
if (commitStage != CommitStage.QUEUED_TO_COMMIT
|
||||
|| project.isDisposed() || !ArrayUtil.contains(document,PsiDocumentManager.getInstance(project).getUncommittedDocuments())) {
|
||||
log("Abandon and proceeding to next",document, false, commitStage, Arrays.asList(
|
||||
PsiDocumentManager.getInstance(project).getUncommittedDocuments()));
|
||||
continue;
|
||||
}
|
||||
if (indicator.isRunning()) {
|
||||
@@ -279,7 +290,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
try {
|
||||
finishRunnable = commit(document, project, null, indicator, false, task.reason, task.event);
|
||||
success = finishRunnable != null;
|
||||
log("Committed", document, false, finishRunnable, indicator);
|
||||
log("DCT.commit returned", document, false, finishRunnable, indicator);
|
||||
}
|
||||
finally {
|
||||
document.putUserData(COMMIT_PROGRESS, null);
|
||||
@@ -292,9 +303,8 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
}
|
||||
if (success) {
|
||||
UIUtil.invokeLaterIfNeeded(finishRunnable);
|
||||
log("Invoked later finishRunnable", document, false, success, finishRunnable, indicator);
|
||||
}
|
||||
|
||||
log("Invoked later", document, false, success, finishRunnable, indicator);
|
||||
}
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
@@ -313,8 +323,13 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
LOG.error(e);
|
||||
cancel(e);
|
||||
}
|
||||
if (!success && indicator.isRunning()) { // running means sync commit has not intervened
|
||||
doQueue(document, project, CommitStage.QUEUED_TO_COMMIT, "re-added on failure", null);
|
||||
synchronized (documentsToCommit) {
|
||||
if (!success && indicator.isRunning()) { // running means sync commit has not intervened
|
||||
// reset status for queue back successfully
|
||||
changeCommitStage(document, CommitStage.WAITING_FOR_PSI_APPLY, CommitStage.QUEUED_TO_COMMIT, false);
|
||||
changeCommitStage(document, CommitStage.COMMITTED, CommitStage.QUEUED_TO_COMMIT, false);
|
||||
doQueue(document, project, CommitStage.QUEUED_TO_COMMIT, "re-added on failure", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Throwable e) {
|
||||
@@ -344,8 +359,10 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().assertWriteAccessAllowed();
|
||||
setCommitStage(document, CommitStage.ABOUT_TO_BE_SYNC_COMMITTED, true);
|
||||
removeCommitFromQueue(document);
|
||||
synchronized (documentsToCommit) {
|
||||
setCommitStage(document, CommitStage.ABOUT_TO_BE_SYNC_COMMITTED, true);
|
||||
removeCommitFromQueue(document);
|
||||
}
|
||||
|
||||
ProgressIndicatorBase indicator = new ProgressIndicatorBase();
|
||||
indicator.start();
|
||||
@@ -463,14 +480,16 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
assert changed : "Before: " + before + "; after: " + getCommitStage(document);
|
||||
}
|
||||
}
|
||||
if (synchronously) {
|
||||
List<Document> unc = Arrays.asList(documentManager.getUncommittedDocuments());
|
||||
List<Document> unc = Arrays.asList(documentManager.getUncommittedDocuments());
|
||||
log("after call finish commit",document, synchronously, unc, success);
|
||||
if (synchronously || success) {
|
||||
assert !unc.contains(document) : unc;
|
||||
}
|
||||
if (!success) {
|
||||
// add document back to the queue
|
||||
log("Re-adding back", document, synchronously, success, documentManager.isCommitted(document), Arrays.asList(documentManager.getUncommittedDocuments()));
|
||||
queueCommit("Re-added back", document, project, null);
|
||||
boolean addedBack = queueCommit("Re-added back", document, project, null);
|
||||
assert addedBack;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -650,9 +669,9 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
}
|
||||
|
||||
private boolean changeCommitStage(@NotNull Document document,
|
||||
CommitStage expected,
|
||||
@NotNull CommitStage stage,
|
||||
boolean synchronously) {
|
||||
CommitStage expected,
|
||||
@NotNull CommitStage stage,
|
||||
boolean synchronously) {
|
||||
boolean replaced = ((UserDataHolderEx)document).replace(COMMIT_STAGE, expected, stage);
|
||||
log("Changed stage", document, synchronously, expected, stage, replaced);
|
||||
return replaced;
|
||||
|
||||
@@ -339,15 +339,15 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec
|
||||
}
|
||||
}
|
||||
finally {
|
||||
//myDocumentCommitThread.log("in PDI.finishDoc: ",document, synchronously, success, myUncommittedDocuments);
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: ",document, synchronously, success, myUncommittedDocuments);
|
||||
if (success) {
|
||||
myUncommittedDocuments.remove(document);
|
||||
//myDocumentCommitThread.log("in PDI.finishDoc: removed doc",document, synchronously, success, myUncommittedDocuments);
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: removed doc",document, synchronously, success, myUncommittedDocuments);
|
||||
((DocumentImpl)document).normalizeRangeMarkers();
|
||||
InjectedLanguageUtil.commitAllInjectedDocuments(document, myProject);
|
||||
}
|
||||
myIsCommitInProgress = false;
|
||||
//myDocumentCommitThread.log("in PDI.finishDoc: exit",document, synchronously, success, myUncommittedDocuments);
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: exit",document, synchronously, success, myUncommittedDocuments);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
|
||||
@@ -825,16 +825,6 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buffer = new StringBuilder("document: ");
|
||||
int linesNumber = getLineCount();
|
||||
for (int i = 0; i < linesNumber; i++) {
|
||||
buffer.append(i).append(":").append(getLineStartOffset(i)).append("-").append(getLineEndOffset(i)).append(";");
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private static class MyCharArray extends CharArray {
|
||||
public MyCharArray() {
|
||||
super(0);
|
||||
|
||||
Reference in New Issue
Block a user