IJPL-149317 Disable Write Intent Lock for runnables executed on EDT

1. Add a flag to disable write intent lock for coroutines and misc actions. Disable by default.
2. Use this flag.
3. Add an explicit wrapper for write intent lock.

GitOrigin-RevId: 7e8ca603b4e4d7d9d10bce3baeaacf0fa37fad62
This commit is contained in:
Lev Serebryakov
2024-08-09 15:22:24 +02:00
committed by intellij-monorepo-bot
parent 4852703ee9
commit f8542025fa
4 changed files with 34 additions and 1 deletions

View File

@@ -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

View File

@@ -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()

View File

@@ -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 <T> 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 <T> 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

View File

@@ -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)
}
}