remove all mentions of transaction merging since this term can be understood in different ways; require a parent disposable

This commit is contained in:
peter
2016-04-11 18:32:17 +02:00
parent ff1b55aab3
commit 421d2909bf
10 changed files with 32 additions and 39 deletions
@@ -277,7 +277,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
TransactionGuard guard = TransactionGuard.getInstance();
TransactionId id = guard.getContextTransaction();
DumbService.getInstance(project).smartInvokeLater(
() -> TransactionGuard.getInstance().submitMergeableTransaction(project, id, () -> {
() -> TransactionGuard.getInstance().submitTransaction(project, id, () -> {
if (DumbService.isDumb(project)) {
restartAnalysis(project, scope);
} else {
@@ -40,7 +40,7 @@ import org.jetbrains.annotations.Nullable;
* Sometimes transactions need to be processed as soon as possible, even if another transaction is already running. Example:
* outer transaction has shown a dialog with a modal progress that performs a write action inside (which requires a transaction)
* and waits for it to be finished. For such cases, a context transaction id
* should be supplied to the nested transaction via {@link #submitMergeableTransaction(Disposable, TransactionId, Runnable)}.
* should be supplied to the nested transaction via {@link #submitTransaction(Disposable, TransactionId, Runnable)}.
*
* <p><h1>FAQ</h1></p>
*
@@ -69,7 +69,7 @@ import org.jetbrains.annotations.Nullable;
*
* Q: I've got <b>"Write access is allowed from model transactions only"</b> exception, what do I do?<br/>
* A: You're likely inside an "invokeLater"-like call. Please consider replacing it with {@link #submitTransaction(Disposable, Runnable)} or
* {@link #submitMergeableTransaction(Disposable, TransactionId, Runnable)}
* {@link #submitTransaction(Disposable, TransactionId, Runnable)}
* <p/>
*
* Q: What's the difference between transactions and read/write actions and commands ({@link com.intellij.openapi.command.CommandProcessor})?<br/>
@@ -88,19 +88,12 @@ public abstract class TransactionGuard {
return ServiceManager.getService(TransactionGuard.class);
}
/**
* Same as {@link #submitTransaction(Disposable, Runnable)}, but without any parent disposable.
*/
public static void submitTransaction(@NotNull Runnable transaction) {
submitTransaction(ApplicationManager.getApplication(), transaction);
}
/**
* Ensures that some code will be run in a transaction. It's guaranteed that no other transactions can run at the same time,
* except for the ones started from within this runnable. The code will be run on Swing thread immediately
* or after other queued transactions (if any) have been completed.<p/>
*
* For more advanced version, see {@link #submitMergeableTransaction(Disposable, TransactionId, Runnable)}.
* For more advanced version, see {@link #submitTransaction(Disposable, TransactionId, Runnable)}.
*
* @param parentDisposable an object whose disposing (via {@link com.intellij.openapi.util.Disposer} makes this transaction invalid,
* and so it won't be run after it has been disposed
@@ -108,7 +101,7 @@ public abstract class TransactionGuard {
*/
public static void submitTransaction(@NotNull Disposable parentDisposable, @NotNull Runnable transaction) {
TransactionGuard guard = getInstance();
guard.submitMergeableTransaction(parentDisposable, guard.getContextTransaction(), transaction);
guard.submitTransaction(parentDisposable, guard.getContextTransaction(), transaction);
}
/**
@@ -120,27 +113,27 @@ public abstract class TransactionGuard {
/**
* Schedules a transaction and waits for it to be completed. Fails if invoked on UI thread inside an incompatible transaction,
* or inside a read action on non-UI thread.
* @see #submitMergeableTransaction(Disposable, TransactionId, Runnable)
* @see #submitTransaction(Disposable, TransactionId, Runnable)
* @throws ProcessCanceledException if current thread is interrupted
*/
public abstract void submitTransactionAndWait(@NotNull Runnable transaction) throws ProcessCanceledException;
/**
* Executes the given runnable inside a transaction as soon as possible on the UI thread. The runnable is executed either when there's
* no active transaction running, or when the running transaction has the same (or compatible) id as {@code mergeInto}. If the id of
* no active transaction running, or when the running transaction has the same (or compatible) id as {@code expectedContext}. If the id of
* the current transaction is passed, the transaction is executed immediately. Otherwise adds the runnable to a queue,
* to execute after all transactions scheduled before this one are finished.
* @param parentDisposable an object whose disposing (via {@link com.intellij.openapi.util.Disposer} makes this transaction invalid,
* and so it won't be run after it has been disposed.
* @param mergeInto an optional id of another transaction, to allow execution inside that transaction if it's still running
* @param expectedContext an optional id of another transaction, to allow execution inside that transaction if it's still running
* @param transaction code to execute inside a transaction.
* @see #getContextTransaction()
*/
public abstract void submitMergeableTransaction(@NotNull Disposable parentDisposable, @Nullable TransactionId mergeInto, @NotNull Runnable transaction);
public abstract void submitTransaction(@NotNull Disposable parentDisposable, @Nullable TransactionId expectedContext, @NotNull Runnable transaction);
/**
* @return the id of the currently running transaction for using in {@link #submitMergeableTransaction(Disposable, TransactionId, Runnable)},
* or null if there's no transaction running or merging is not allowed in the callee context (e.g. from invokeLater).
* @return the id of the currently running transaction for using in {@link #submitTransaction(Disposable, TransactionId, Runnable)},
* or null if there's no transaction running or transaction nesting is not allowed in the callee context (e.g. from invokeLater).
*/
public abstract TransactionId getContextTransaction();
}
@@ -5,7 +5,7 @@ import com.intellij.openapi.Disposable;
/**
* A unique object identifying each running transaction. Can be retrieved from {@link TransactionGuard#getContextTransaction()}
* while inside a transaction, and used to merge other transactions into it via
* {@link TransactionGuard#submitMergeableTransaction(Disposable, TransactionId, Runnable)}.
* {@link TransactionGuard#submitTransaction(Disposable, TransactionId, Runnable)}.
*
* @author peter
* @since 2016.2
@@ -110,8 +110,8 @@ public class TransactionGuardImpl extends TransactionGuard {
}
@Override
public void submitMergeableTransaction(@NotNull Disposable parentDisposable, @Nullable TransactionId mergeInto, @NotNull Runnable _transaction) {
final TransactionIdImpl expectedId = (TransactionIdImpl)mergeInto;
public void submitTransaction(@NotNull Disposable parentDisposable, @Nullable TransactionId expectedContext, @NotNull Runnable _transaction) {
final TransactionIdImpl expectedId = (TransactionIdImpl)expectedContext;
final Transaction transaction = new Transaction(_transaction, expectedId, parentDisposable);
final Application app = ApplicationManager.getApplication();
final boolean isDispatchThread = app.isDispatchThread();
@@ -146,7 +146,7 @@ public class TransactionGuardImpl extends TransactionGuard {
return false;
}
return transaction.mergeInto != null && currentId.myStartCounter <= transaction.mergeInto.myStartCounter;
return transaction.expectedContext != null && currentId.myStartCounter <= transaction.expectedContext.myStartCounter;
}
@Override
@@ -167,7 +167,7 @@ public class TransactionGuardImpl extends TransactionGuard {
final Semaphore semaphore = new Semaphore();
semaphore.down();
final Throwable[] exception = {null};
submitMergeableTransaction(Disposer.newDisposable("never disposed"), getContextTransaction(), new Runnable() {
submitTransaction(Disposer.newDisposable("never disposed"), getContextTransaction(), new Runnable() {
@Override
public void run() {
try {
@@ -239,7 +239,7 @@ public class TransactionGuardImpl extends TransactionGuard {
app.invokeLater(new Runnable() {
@Override
public void run() {
submitMergeableTransaction(parentDisposable, id, transaction);
submitTransaction(parentDisposable, id, transaction);
}
});
}
@@ -291,12 +291,12 @@ public class TransactionGuardImpl extends TransactionGuard {
private static class Transaction {
@NotNull final Runnable runnable;
@Nullable final TransactionIdImpl mergeInto;
@Nullable final TransactionIdImpl expectedContext;
@NotNull final Disposable parentDisposable;
Transaction(@NotNull Runnable runnable, @Nullable TransactionIdImpl mergeInto, @NotNull Disposable parentDisposable) {
Transaction(@NotNull Runnable runnable, @Nullable TransactionIdImpl expectedContext, @NotNull Disposable parentDisposable) {
this.runnable = runnable;
this.mergeInto = mergeInto;
this.expectedContext = expectedContext;
this.parentDisposable = parentDisposable;
}
}
@@ -429,7 +429,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
myApplication.invokeLater(new Runnable() {
@Override
public void run() {
guard.submitMergeableTransaction(finalProject, transaction, finalFinishRunnable);
guard.submitTransaction(finalProject, transaction, finalFinishRunnable);
}
}, task.myCreationModalityState);
}
@@ -197,7 +197,7 @@ public class AutoPopupController implements Disposable {
TransactionId id = guard.getContextTransaction();
final PsiDocumentManager pdm = PsiDocumentManager.getInstance(project);
pdm.performLaterWhenAllCommitted(() -> {
guard.submitMergeableTransaction(project, id, () -> {
guard.submitTransaction(project, id, () -> {
if (pdm.hasUncommitedDocuments()) {
// no luck, will try later
runTransactionWithEverythingCommitted(project, runnable);
@@ -67,7 +67,7 @@ public class SaveAndSyncHandlerImpl extends SaveAndSyncHandler implements Dispos
myIdleListener = () -> {
if (mySettings.isAutoSaveIfInactive() && canSyncOrSave()) {
TransactionGuard.submitTransaction(() -> ((FileDocumentManagerImpl)fileDocumentManager).saveAllDocuments(false));
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> ((FileDocumentManagerImpl)fileDocumentManager).saveAllDocuments(false));
}
};
IdeEventQueue.getInstance().addIdleListener(myIdleListener, mySettings.getInactiveTimeout() * 1000);
@@ -89,7 +89,7 @@ public class SaveAndSyncHandlerImpl extends SaveAndSyncHandler implements Dispos
@Override
public void onFrameDeactivated() {
LOG.debug("save(): enter");
TransactionGuard.submitTransaction(() -> {
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> {
if (canSyncOrSave()) {
saveProjectsAndDocuments();
}
@@ -546,7 +546,7 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica
//todo remove invokeLater when transactions are executed in "any" modality state
//noinspection SSBasedInspection
SwingUtilities.invokeLater(
() -> TransactionGuard.getInstance().submitMergeableTransaction(app, myDumbStartTransaction, () -> {
() -> TransactionGuard.getInstance().submitTransaction(app, myDumbStartTransaction, () -> {
try {
runnable.run();
} finally {
@@ -77,7 +77,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
Application app = ApplicationManager.getApplication();
// invokeLater might be not necessary once transactions are enforced
app.invokeLater(
() -> TransactionGuard.getInstance().submitMergeableTransaction(app, transaction, session::fireEvents),
() -> TransactionGuard.getInstance().submitTransaction(app, transaction, session::fireEvents),
modality);
}
});
@@ -135,7 +135,7 @@ class TransactionTest extends LightPlatformTestCase {
public void "test do not merge transactions with null id"() {
TransactionGuard.submitTransaction testRootDisposable, {
log << '1'
guard.submitMergeableTransaction testRootDisposable, (TransactionId)null, { log << '2' }
guard.submitTransaction testRootDisposable, (TransactionId)null, { log << '2' }
UIUtil.dispatchAllInvocationEvents()
assert log == ['1']
}
@@ -149,16 +149,16 @@ class TransactionTest extends LightPlatformTestCase {
log << '1'
def id = guard.contextTransaction
SwingUtilities.invokeLater {
guard.submitMergeableTransaction testRootDisposable, id, { log << '4' }
guard.submitTransaction testRootDisposable, id, { log << '4' }
}
guard.submitMergeableTransaction testRootDisposable, id, {
guard.submitTransaction testRootDisposable, id, {
UIUtil.dispatchAllInvocationEvents()
log << '2'
UIUtil.dispatchAllInvocationEvents()
guard.submitMergeableTransaction testRootDisposable, id, { log << '5' }
guard.submitTransaction testRootDisposable, id, { log << '5' }
def nestedId = guard.contextTransaction
SwingUtilities.invokeLater {
guard.submitMergeableTransaction testRootDisposable, nestedId, { log << '3' }
guard.submitTransaction testRootDisposable, nestedId, { log << '3' }
assert log == ['1', '2']
}
UIUtil.dispatchAllInvocationEvents()
@@ -178,7 +178,7 @@ class TransactionTest extends LightPlatformTestCase {
id = guard.contextTransaction
}
SwingUtilities.invokeLater {
guard.submitMergeableTransaction testRootDisposable, id, { log << '3' }
guard.submitTransaction testRootDisposable, id, { log << '3' }
}
UIUtil.dispatchAllInvocationEvents()
assert log == ['1', '2', '3']