mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
IJPL-162040 Store lock permits in context to allow lock inheritance between coroutines.
- Fix check for inheritance in case of Fleet or other coroutine framework. - Make tests stricter. - Mark new Application API as internal and experimental, as ot is needed only for this code and should not be used in other places. (cherry picked from commit 63798b6160ca5963499ae066db149d3b2af6017d) IJ-CR-147289 GitOrigin-RevId: 700746a8c9590945893ef389f2c86724eb8a83d5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ecb3e54b63
commit
c91c8b6702
@@ -1100,10 +1100,8 @@ com.intellij.openapi.application.Application
|
|||||||
- exit(Z,Z,Z,I):V
|
- exit(Z,Z,Z,I):V
|
||||||
- a:getDefaultModalityState():com.intellij.openapi.application.ModalityState
|
- a:getDefaultModalityState():com.intellij.openapi.application.ModalityState
|
||||||
- a:getIdleTime():J
|
- a:getIdleTime():J
|
||||||
- getLockStateAsCoroutineContext():kotlin.coroutines.CoroutineContext
|
|
||||||
- a:getModalityStateForComponent(java.awt.Component):com.intellij.openapi.application.ModalityState
|
- a:getModalityStateForComponent(java.awt.Component):com.intellij.openapi.application.ModalityState
|
||||||
- a:getStartTime():J
|
- a:getStartTime():J
|
||||||
- hasLockStateInContext(kotlin.coroutines.CoroutineContext):Z
|
|
||||||
- a:hasWriteAction(java.lang.Class):Z
|
- a:hasWriteAction(java.lang.Class):Z
|
||||||
- a:invokeAndWait(java.lang.Runnable):V
|
- a:invokeAndWait(java.lang.Runnable):V
|
||||||
- a:invokeAndWait(java.lang.Runnable,com.intellij.openapi.application.ModalityState):V
|
- a:invokeAndWait(java.lang.Runnable,com.intellij.openapi.application.ModalityState):V
|
||||||
|
|||||||
@@ -675,10 +675,14 @@ public interface Application extends ComponentManager {
|
|||||||
}
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
@ApiStatus.Internal
|
||||||
default CoroutineContext getLockStateAsCoroutineContext() {
|
default CoroutineContext getLockStateAsCoroutineContext() {
|
||||||
return EmptyCoroutineContext.INSTANCE;
|
return EmptyCoroutineContext.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
@ApiStatus.Internal
|
||||||
default boolean hasLockStateInContext(CoroutineContext context) {
|
default boolean hasLockStateInContext(CoroutineContext context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ internal class InternalReadAction<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isLockStoredInContext && application.isReadAccessAllowed && !application.isWriteIntentLockAcquired) {
|
if (isLockStoredInContext && application.hasLockStateInContext(currentCoroutineContext())) {
|
||||||
val unsatisfiedConstraint = findUnsatisfiedConstraint()
|
val unsatisfiedConstraint = findUnsatisfiedConstraint()
|
||||||
check(unsatisfiedConstraint == null) {
|
check(unsatisfiedConstraint == null) {
|
||||||
"Cannot suspend until constraints are satisfied while holding the read lock: $unsatisfiedConstraint"
|
"Cannot suspend until constraints are satisfied while holding the read lock: $unsatisfiedConstraint"
|
||||||
@@ -47,7 +47,7 @@ internal class InternalReadAction<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
check(isLockStoredInContext || !application.isReadAccessAllowed) {
|
check(!application.isReadAccessAllowed) {
|
||||||
"This thread unexpectedly holds the read lock"
|
"This thread unexpectedly holds the read lock"
|
||||||
}
|
}
|
||||||
readLoop()
|
readLoop()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.Disposer
|
|||||||
import com.intellij.testFramework.common.timeoutRunBlocking
|
import com.intellij.testFramework.common.timeoutRunBlocking
|
||||||
import com.intellij.util.concurrency.ImplicitBlockingContextTest
|
import com.intellij.util.concurrency.ImplicitBlockingContextTest
|
||||||
import com.intellij.util.concurrency.Semaphore
|
import com.intellij.util.concurrency.Semaphore
|
||||||
|
import com.intellij.util.concurrency.ThreadingAssertions
|
||||||
import com.intellij.util.concurrency.runWithImplicitBlockingContextEnabled
|
import com.intellij.util.concurrency.runWithImplicitBlockingContextEnabled
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.junit.jupiter.api.Assertions.*
|
import org.junit.jupiter.api.Assertions.*
|
||||||
@@ -156,8 +157,10 @@ abstract class SuspendingReadActionTest : CancellableReadActionTests() {
|
|||||||
@RepeatedTest(REPETITIONS)
|
@RepeatedTest(REPETITIONS)
|
||||||
fun `read action works if already obtained`(): Unit = timeoutRunBlocking {
|
fun `read action works if already obtained`(): Unit = timeoutRunBlocking {
|
||||||
cra {
|
cra {
|
||||||
|
assertTrue(ApplicationManager.getApplication().isReadAccessAllowed)
|
||||||
runBlockingCancellable {
|
runBlockingCancellable {
|
||||||
assertEquals(42, cra {
|
assertEquals(42, cra {
|
||||||
|
assertTrue(ApplicationManager.getApplication().isReadAccessAllowed)
|
||||||
42
|
42
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -387,6 +390,7 @@ class NonBlockingUndispatchedSuspendingReadActionTest : SuspendingReadActionTest
|
|||||||
override suspend fun awaitConstraint(): Unit = fail("must not be called")
|
override suspend fun awaitConstraint(): Unit = fail("must not be called")
|
||||||
}
|
}
|
||||||
cra {
|
cra {
|
||||||
|
assertTrue(ApplicationManager.getApplication().isReadAccessAllowed)
|
||||||
runBlockingCancellable {
|
runBlockingCancellable {
|
||||||
assertThrows<IllegalStateException> {
|
assertThrows<IllegalStateException> {
|
||||||
cra(unsatisfiableConstraint) {
|
cra(unsatisfiableConstraint) {
|
||||||
|
|||||||
Reference in New Issue
Block a user