diff --git a/platform/core-api/api-dump-unreviewed.txt b/platform/core-api/api-dump-unreviewed.txt index 28ffcc722893..e2f5e82fd294 100644 --- a/platform/core-api/api-dump-unreviewed.txt +++ b/platform/core-api/api-dump-unreviewed.txt @@ -1446,6 +1446,7 @@ f:com.intellij.openapi.application.CoroutinesKt - sf:smartReadAction(com.intellij.openapi.project.Project,kotlin.jvm.functions.Function0,kotlin.coroutines.Continuation):java.lang.Object - sf:smartReadActionBlocking(com.intellij.openapi.project.Project,kotlin.jvm.functions.Function0,kotlin.coroutines.Continuation):java.lang.Object - *sf:writeAction(kotlin.jvm.functions.Function0,kotlin.coroutines.Continuation):java.lang.Object +- *sf:writeIntentReadAction(kotlin.jvm.functions.Function0,kotlin.coroutines.Continuation):java.lang.Object com.intellij.openapi.application.DumbAwareSearchParameters - com.intellij.util.QueryParameters - a:getProject():com.intellij.openapi.project.Project diff --git a/platform/core-api/src/com/intellij/openapi/application/RuntimeFlags.kt b/platform/core-api/src/com/intellij/openapi/application/RuntimeFlags.kt index ddda700aa0fb..7db26725ab7c 100644 --- a/platform/core-api/src/com/intellij/openapi/application/RuntimeFlags.kt +++ b/platform/core-api/src/com/intellij/openapi/application/RuntimeFlags.kt @@ -4,6 +4,7 @@ package com.intellij.openapi.application import org.jetbrains.annotations.ApiStatus private const val ENABLE_NEW_LOCK_PROPERTY = "idea.enable.new.lock" +private const val COROUTINE_WIL_PROPERTY = "ide.coroutine.write.intent.lock" @get:ApiStatus.Internal val isNewLockEnabled: Boolean @@ -16,3 +17,11 @@ val isNewLockEnabled: Boolean @get:ApiStatus.Internal val isMessageBusThrowsWhenDisposed: Boolean = System.getProperty("ijpl.message.bus.throws.when.disposed", "true").toBoolean() + +/** + * - `false` means no implicit write intent lock for activities and coroutines + * - `true` means [IdeEventQueue] will wrap activities into write intent lock. + */ +@get:ApiStatus.Internal +val isCoroutineWILEnabled: Boolean = + System.getProperty(COROUTINE_WIL_PROPERTY, "true").toBoolean() diff --git a/platform/core-api/src/com/intellij/openapi/application/coroutines.kt b/platform/core-api/src/com/intellij/openapi/application/coroutines.kt index 0da6748d136d..29be5c33caee 100644 --- a/platform/core-api/src/com/intellij/openapi/application/coroutines.kt +++ b/platform/core-api/src/com/intellij/openapi/application/coroutines.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.progress.blockingContext import com.intellij.openapi.project.Project import com.intellij.openapi.util.Computable import com.intellij.openapi.util.IntellijInternalApi +import com.intellij.openapi.util.ThrowableComputable import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asContextElement @@ -241,6 +242,28 @@ suspend fun writeAction(action: () -> T): T { } } +/** + * Runs given [action] under [write intent read lock][com.intellij.openapi.application.Application.runWriteIntentReadAction]. + * + * Acquiring the write intent lock happens in blocking manner, + * i.e. [runWriteIntentReadAction][com.intellij.openapi.application.Application.runWriteIntentReadAction] call will block + * until all currently running write actions are finished. + * + * NB This function is an API stub. + * The implementation will change once running write actions would be allowed on other threads. + * This function exists to make it possible to use it in suspending contexts + * before the platform is ready to handle write actions differently. + * + * @see readAndWriteAction + * @see com.intellij.openapi.command.writeCommandAction + */ +@Experimental +suspend fun writeIntentReadAction(action: () -> T): T { + return blockingContext { + ApplicationManager.getApplication().runWriteIntentReadAction(ThrowableComputable(action)) + } +} + private fun readWriteActionSupport() = ApplicationManager.getApplication().getService(ReadWriteActionSupport::class.java) @Suppress("CONFLICTING_OVERLOADS") // KT-61878 diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.kt b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.kt index fc51c4aa1432..f5b1e290785a 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.kt +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.kt @@ -1042,7 +1042,7 @@ internal fun performActivity(e: AWTEvent, runnable: () -> Unit) { runnable() } else { - val runnableWithWIL = { WriteIntentReadAction.run(runnable) } + val runnableWithWIL = if (isCoroutineWILEnabled) { { WriteIntentReadAction.run(runnable) } } else { runnable } transactionGuard.performActivity(isInputEvent(e) || e is ItemEvent || e is FocusEvent, runnableWithWIL) } }