make submitTransactionAndWait more convenient

This commit is contained in:
peter
2016-03-09 21:02:11 +01:00
parent 67c2d10ef3
commit c7a844e7db
2 changed files with 31 additions and 7 deletions
@@ -17,6 +17,8 @@ package com.intellij.openapi.application;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull;
/**
@@ -96,14 +98,27 @@ public abstract class TransactionGuard {
}
/**
* Schedules a transaction and waits for it to be completed. Only allowed to be invoked on non-UI thread and outside read action.
* 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(TransactionKind, Runnable)
* @param kind
* @param transaction
* @throws ProcessCanceledException if current thread is interrupted
*/
public abstract void submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull Runnable transaction) throws ProcessCanceledException;
/**
* Same as {@link #submitTransactionAndWait(TransactionKind, Runnable)}, but returns a value computed by the transaction.
*/
public <T> T submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull final Computable<T> transaction) throws ProcessCanceledException {
final Ref<T> result = Ref.create();
submitTransactionAndWait(kind, new Runnable() {
@Override
public void run() {
result.set(transaction.compute());
}
});
return result.get();
}
/**
* A synchronous version of {@link #submitMergeableTransaction(TransactionKind, Runnable)}.
* @return a token object for this transaction. Call {@link AccessToken#finish()} (inside finally) when the transaction is complete.
@@ -48,7 +48,6 @@ public class TransactionGuardImpl extends TransactionGuard {
// please assign exceptions that occur here to Peter
LOG.error("Nested transactions are not allowed, see FAQ in TransactionGuard class javadoc. Transaction start trace is in attachment. Kind is " + kind,
new Attachment("trace.txt", myTransactionStartTrace));
//throw new IllegalStateException("Nested transactions are not allowed");
}
myTransactionStartTrace = DebugUtil.currentStackTrace();
return new AccessToken() {
@@ -99,7 +98,7 @@ public class TransactionGuardImpl extends TransactionGuard {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (!isInsideTransaction() || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
if (canRunTransactionNow(kind)) {
runSyncTransaction(kind, transaction);
}
else {
@@ -118,6 +117,10 @@ public class TransactionGuardImpl extends TransactionGuard {
}
}
protected boolean canRunTransactionNow(@NotNull TransactionKind kind) {
return !isInsideTransaction() || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind);
}
@Override
@NotNull
public AccessToken acceptNestedTransactions(TransactionKind... kinds) {
@@ -144,9 +147,15 @@ public class TransactionGuardImpl extends TransactionGuard {
@Override
public void submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull final Runnable transaction) throws ProcessCanceledException {
Application app = ApplicationManager.getApplication();
assert !app.isDispatchThread() : "submitTransactionAndWait should not be invoked on dispatch thread";
assert !app.isReadAccessAllowed() : "submitTransactionAndWait should not be invoked from a read action";
if (app.isDispatchThread()) {
if (!canRunTransactionNow(kind)) {
throw new AssertionError("Cannot run submitTransactionAndWait from another transaction, kind " + kind + " is not allowed");
}
runSyncTransaction(kind, transaction);
return;
}
assert !app.isReadAccessAllowed() : "submitTransactionAndWait should not be invoked from a read action";
final Semaphore semaphore = new Semaphore();
semaphore.down();
final Throwable[] exception = {null};