mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
[threading] IJPL-148438: Move handling of listeners to ThreadingSupport
GitOrigin-RevId: ca68876b52ec298efbfa01b43fd730b8d2502d0d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
099e00a013
commit
6180423383
@@ -50,26 +50,6 @@ interface ThreadingSupport {
|
||||
@ApiStatus.Internal
|
||||
fun <T> runUnlockingIntendedWrite(action: () -> T): T
|
||||
|
||||
/**
|
||||
* Set a [ReadActionListener].
|
||||
*
|
||||
* Only one listener can be set. It is error to set second listener.
|
||||
*
|
||||
* @param listener the listener to set
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
fun setReadActionListener(listener: ReadActionListener)
|
||||
|
||||
/**
|
||||
* Removes a [ReadActionListener].
|
||||
*
|
||||
* It is error to remove listener which was not set early.
|
||||
*
|
||||
* @param listener the listener to remove
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
fun removeReadActionListener(listener: ReadActionListener)
|
||||
|
||||
@RequiresBlockingContext
|
||||
fun <T> runReadAction(clazz: Class<*>, action: () -> T): T
|
||||
|
||||
@@ -97,39 +77,50 @@ interface ThreadingSupport {
|
||||
/**
|
||||
* Adds a [WriteActionListener].
|
||||
*
|
||||
* Only one listener can be set. It is error to set second listener.
|
||||
*
|
||||
* @param listener the listener to set
|
||||
*/
|
||||
fun setWriteActionListener(listener: WriteActionListener)
|
||||
fun addWriteActionListener(listener: WriteActionListener)
|
||||
|
||||
/**
|
||||
* Removes a [WriteActionListener].
|
||||
*
|
||||
* It is error to remove listener which was not added early.
|
||||
*
|
||||
* @param listener the listener to remove
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
fun removeWriteActionListener(listener: WriteActionListener)
|
||||
|
||||
/**
|
||||
* Adds a [WriteIntentReadActionListener].
|
||||
*
|
||||
* Only one listener can be set. It is an error to set the second listener.
|
||||
*
|
||||
* @param listener the listener to set
|
||||
*/
|
||||
fun setWriteIntentReadActionListener(listener: WriteIntentReadActionListener)
|
||||
fun addWriteIntentReadActionListener(listener: WriteIntentReadActionListener)
|
||||
|
||||
/**
|
||||
* Removes a [WriteIntentReadActionListener].
|
||||
*
|
||||
* It is an error to remove the listener which was not set early.
|
||||
* It is an error to remove the listener which was not added early.
|
||||
*
|
||||
* @param listener the listener to remove
|
||||
*/
|
||||
fun removeWriteIntentReadActionListener(listener: WriteIntentReadActionListener)
|
||||
|
||||
/**
|
||||
* Removes a [WriteActionListener].
|
||||
* Set a [ReadActionListener].
|
||||
*
|
||||
* It is error to remove listener which was not set early.
|
||||
* @param listener the listener to set
|
||||
*/
|
||||
fun addReadActionListener(listener: ReadActionListener)
|
||||
|
||||
/**
|
||||
* Removes a [ReadActionListener].
|
||||
*
|
||||
* @param listener the listener to remove
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
fun removeWriteActionListener(listener: WriteActionListener)
|
||||
fun removeReadActionListener(listener: ReadActionListener)
|
||||
|
||||
@RequiresBlockingContext
|
||||
fun <T> runWriteAction(clazz: Class<*>, action: () -> T): T
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.application.*
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.Cancellation
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.platform.locking.impl.listeners.ErrorHandler
|
||||
import com.intellij.platform.locking.impl.listeners.LegacyProgressIndicatorProvider
|
||||
import com.intellij.platform.locking.impl.listeners.LockAcquisitionListener
|
||||
import com.intellij.util.ReflectionUtil
|
||||
@@ -16,6 +17,7 @@ import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.internal.intellij.IntellijCoroutines
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.util.*
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.Result
|
||||
@@ -194,13 +196,16 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
*/
|
||||
private val statesOfWIThread: ThreadLocal<MutableList<ComputationState>?> = ThreadLocal.withInitial { null }
|
||||
|
||||
private var myReadActionListener: ReadActionListener? = null
|
||||
private var myWriteActionListener: WriteActionListener? = null
|
||||
private var myWriteIntentActionListener: WriteIntentReadActionListener? = null
|
||||
private val readActionListeners: CopyOnWriteArrayList<ReadActionListener> = CopyOnWriteArrayList()
|
||||
private val myWriteActionListeners: CopyOnWriteArrayList<WriteActionListener> = CopyOnWriteArrayList()
|
||||
private val myWriteIntentActionListeners: CopyOnWriteArrayList<WriteIntentReadActionListener> = CopyOnWriteArrayList()
|
||||
private var myLockAcquisitionListener: LockAcquisitionListener? = null
|
||||
private var myWriteLockReacquisitionListener: WriteLockReacquisitionListener? = null
|
||||
private var myLegacyProgressIndicatorProvider: LegacyProgressIndicatorProvider? = null
|
||||
|
||||
@Volatile
|
||||
private var errorHandler: ErrorHandler? = null
|
||||
|
||||
private val myWriteActionsStack = Collections.synchronizedList(ArrayList<Class<*>>())
|
||||
private var myWriteStackBase = 0
|
||||
|
||||
@@ -250,6 +255,62 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
*/
|
||||
private val pendingWriteActionFollowup: MutableList<Runnable> = ArrayList()
|
||||
|
||||
private inline fun <T> List<T>.traverse(action: (T) -> Unit) {
|
||||
var index = 0
|
||||
while (index < size) {
|
||||
try {
|
||||
action(this[index++])
|
||||
}
|
||||
catch (_: CancellationException) {
|
||||
// ignored
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
try {
|
||||
errorHandler?.handleError(e)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
// swallowing error :(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <T> List<T>.traverseBackwards(action: (T) -> Unit) {
|
||||
var index = lastIndex
|
||||
while (index >= 0) {
|
||||
try {
|
||||
action(this[index--])
|
||||
}
|
||||
catch (_: CancellationException) {
|
||||
// ignored
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
try {
|
||||
errorHandler?.handleError(e)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
// swallowing error :(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shallow clone of [CopyOnWriteArrayList] that wraps the underlying array.
|
||||
* I swear that I will not modify the array further
|
||||
*/
|
||||
private fun <T> CopyOnWriteArrayList<T>.doClone(): List<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return clone() as List<T>
|
||||
}
|
||||
|
||||
fun setErrorHandler(handler: ErrorHandler) {
|
||||
errorHandler = handler
|
||||
}
|
||||
|
||||
fun removeErrorHandler() {
|
||||
errorHandler = null
|
||||
}
|
||||
|
||||
/**
|
||||
* The locking state that is shared by all computations belonging to the same level.
|
||||
@@ -581,8 +642,8 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
}
|
||||
|
||||
fun <T> doRunWriteIntentReadAction(computation: () -> T): T {
|
||||
val listener = myWriteIntentActionListener
|
||||
fireBeforeWriteIntentReadActionStart(listener, computation.javaClass)
|
||||
val frozenListeners = myWriteIntentActionListeners.doClone()
|
||||
fireBeforeWriteIntentReadActionStart(frozenListeners, computation.javaClass)
|
||||
val currentReadState = myTopmostReadAction.get()
|
||||
myTopmostReadAction.set(false)
|
||||
val currentWriteIntentState = myWriteIntentAcquired.get()
|
||||
@@ -601,11 +662,11 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
is ParallelizablePermit.WriteIntent, is ParallelizablePermit.Write -> {}
|
||||
}
|
||||
try {
|
||||
fireWriteIntentActionStarted(listener, computation.javaClass)
|
||||
fireWriteIntentActionStarted(frozenListeners, computation.javaClass)
|
||||
return computation()
|
||||
}
|
||||
finally {
|
||||
fireWriteIntentActionFinished(listener, computation.javaClass)
|
||||
fireWriteIntentActionFinished(frozenListeners, computation.javaClass)
|
||||
if (permitToRelease != null) {
|
||||
/**
|
||||
* The permit to release can be changed because of [releaseTheAcquiredWriteIntentLockThenExecuteActionAndTakeWriteIntentLockBack] inside
|
||||
@@ -618,7 +679,7 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
finally {
|
||||
myWriteIntentAcquired.set(currentWriteIntentState)
|
||||
myTopmostReadAction.set(currentReadState)
|
||||
afterWriteIntentReadActionFinished(listener, computation.javaClass)
|
||||
afterWriteIntentReadActionFinished(frozenListeners, computation.javaClass)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,17 +699,15 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
override fun setReadActionListener(listener: ReadActionListener) {
|
||||
if (myReadActionListener != null)
|
||||
error("ReadActionListener already registered")
|
||||
myReadActionListener = listener
|
||||
override fun addReadActionListener(listener: ReadActionListener) {
|
||||
readActionListeners.add(listener)
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
override fun removeReadActionListener(listener: ReadActionListener) {
|
||||
if (myReadActionListener != listener)
|
||||
error("ReadActionListener is not registered")
|
||||
myReadActionListener = null
|
||||
check(readActionListeners.remove(listener)) {
|
||||
"ReadActionListener $listener is not registered"
|
||||
}
|
||||
}
|
||||
|
||||
private fun smartAcquireReadPermit(state: ComputationState): ReadPermit {
|
||||
@@ -657,7 +716,9 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
return permit
|
||||
}
|
||||
|
||||
myReadActionListener?.fastPathAcquisitionFailed()
|
||||
readActionListeners.forEach {
|
||||
it.fastPathAcquisitionFailed()
|
||||
}
|
||||
|
||||
// Check for cancellation
|
||||
val indicator = myLegacyProgressIndicatorProvider?.obtainProgressIndicator()
|
||||
@@ -698,8 +759,8 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
override fun <T> runReadAction(clazz: Class<*>, action: () -> T): T {
|
||||
handleLockAccess("read lock")
|
||||
|
||||
val listener = myReadActionListener
|
||||
fireBeforeReadActionStart(listener, clazz)
|
||||
val frozenListeners = readActionListeners.doClone()
|
||||
fireBeforeReadActionStart(frozenListeners, clazz)
|
||||
|
||||
val currentReadState = myTopmostReadAction.get()
|
||||
myTopmostReadAction.set(true)
|
||||
@@ -719,27 +780,27 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
myReadActionsInThread.set(myReadActionsInThread.get() + 1)
|
||||
|
||||
try {
|
||||
fireReadActionStarted(listener, clazz)
|
||||
fireReadActionStarted(frozenListeners, clazz)
|
||||
val rv = action()
|
||||
return rv
|
||||
}
|
||||
finally {
|
||||
fireReadActionFinished(listener, clazz)
|
||||
fireReadActionFinished(frozenListeners, clazz)
|
||||
|
||||
myReadActionsInThread.set(myReadActionsInThread.get() - 1)
|
||||
if (readPermitToRelease != null) {
|
||||
computationState.releaseReadPermit(readPermitToRelease)
|
||||
}
|
||||
myTopmostReadAction.set(currentReadState)
|
||||
fireAfterReadActionFinished(listener, clazz)
|
||||
fireAfterReadActionFinished(frozenListeners, clazz)
|
||||
}
|
||||
}
|
||||
|
||||
override fun tryRunReadAction(action: Runnable): Boolean {
|
||||
handleLockAccess("fail-fast read lock")
|
||||
|
||||
val listener = myReadActionListener
|
||||
fireBeforeReadActionStart(listener, action.javaClass)
|
||||
val frozenListeners = readActionListeners.doClone()
|
||||
fireBeforeReadActionStart(frozenListeners, action.javaClass)
|
||||
|
||||
val currentReadState = myTopmostReadAction.get()
|
||||
myTopmostReadAction.set(true)
|
||||
@@ -761,12 +822,12 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
myReadActionsInThread.set(myReadActionsInThread.get() + 1)
|
||||
|
||||
try {
|
||||
fireReadActionStarted(listener, action.javaClass)
|
||||
fireReadActionStarted(frozenListeners, action.javaClass)
|
||||
action.run()
|
||||
return true
|
||||
}
|
||||
finally {
|
||||
fireReadActionFinished(listener, action.javaClass)
|
||||
fireReadActionFinished(frozenListeners, action.javaClass)
|
||||
|
||||
myReadActionsInThread.set(myReadActionsInThread.get() - 1)
|
||||
if (readPermitToRelease != null) {
|
||||
@@ -776,7 +837,7 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
}
|
||||
finally {
|
||||
myTopmostReadAction.set(currentReadState)
|
||||
fireAfterReadActionFinished(listener, action.javaClass)
|
||||
fireAfterReadActionFinished(frozenListeners, action.javaClass)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -786,30 +847,26 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
override fun setWriteActionListener(listener: WriteActionListener) {
|
||||
if (myWriteActionListener != null)
|
||||
error("WriteActionListener already registered")
|
||||
myWriteActionListener = listener
|
||||
override fun addWriteActionListener(listener: WriteActionListener) {
|
||||
myWriteActionListeners.add(listener)
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
override fun setWriteIntentReadActionListener(listener: WriteIntentReadActionListener) {
|
||||
if (myWriteIntentActionListener != null)
|
||||
error("WriteIntentReadActionListener already registered")
|
||||
myWriteIntentActionListener = listener
|
||||
override fun addWriteIntentReadActionListener(listener: WriteIntentReadActionListener) {
|
||||
myWriteIntentActionListeners.add(listener)
|
||||
}
|
||||
|
||||
override fun removeWriteIntentReadActionListener(listener: WriteIntentReadActionListener) {
|
||||
if (myWriteIntentActionListener != listener)
|
||||
error("WriteIntentReadActionListener is not registered")
|
||||
myWriteIntentActionListener = null
|
||||
check(myWriteIntentActionListeners.remove(listener)) {
|
||||
"WriteIntentReadActionListener $listener is not registered"
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
override fun removeWriteActionListener(listener: WriteActionListener) {
|
||||
if (myWriteActionListener != listener)
|
||||
error("WriteActionListener is not registered")
|
||||
myWriteActionListener = null
|
||||
check(myWriteActionListeners.remove(listener)) {
|
||||
"WriteActionListener $listener is not registered"
|
||||
}
|
||||
}
|
||||
|
||||
fun setLockAcquisitionListener(listener: LockAcquisitionListener) {
|
||||
@@ -884,7 +941,7 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
* This is needed for code that temporarily releases the write lock.
|
||||
* Since we still want to preserve the atomicity of write action, we pre-acquire the write-intent lock before write.
|
||||
*/
|
||||
private data class PreparatoryWriteIntent(val permit: Permit, val needRelease: Boolean, val state: ComputationState, val listener: WriteActionListener?) {
|
||||
private data class PreparatoryWriteIntent(val permit: Permit, val needRelease: Boolean, val state: ComputationState, val listeners: List<WriteActionListener>) {
|
||||
fun release() {
|
||||
if (!(needRelease && permit is WriteIntentPermit)) {
|
||||
return
|
||||
@@ -894,7 +951,7 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
}
|
||||
|
||||
private fun prepareWriteIntentAcquiredBeforeWrite(computationState: ComputationState, clazz: Class<*>): PreparatoryWriteIntent {
|
||||
val listener = myWriteActionListener
|
||||
val frozenListeners = myWriteActionListeners.doClone()
|
||||
// Read permit is incompatible
|
||||
check(computationState.getThisThreadPermit() !is ParallelizablePermit.Read) { "WriteAction can not be called from ReadAction" }
|
||||
|
||||
@@ -910,7 +967,7 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
startPendingWriteAction(computationState)
|
||||
|
||||
if (myWriteActionsStack.isEmpty()) {
|
||||
fireBeforeWriteActionStart(listener, clazz)
|
||||
fireBeforeWriteActionStart(frozenListeners, clazz)
|
||||
}
|
||||
|
||||
val permit = computationState.getThisThreadPermit()
|
||||
@@ -919,18 +976,18 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
when (permit) {
|
||||
null -> {
|
||||
val writeIntent = computationState.acquireWriteIntentPermit()
|
||||
return PreparatoryWriteIntent(writeIntent, true, computationState, listener)
|
||||
return PreparatoryWriteIntent(writeIntent, true, computationState, frozenListeners)
|
||||
}
|
||||
is ParallelizablePermit.Read -> {
|
||||
error("WriteAction can not be called from ReadAction")
|
||||
}
|
||||
is ParallelizablePermit.WriteIntent -> {
|
||||
checkWriteFromRead("Write", "Write Intent")
|
||||
return PreparatoryWriteIntent(permit.writeIntentPermit, false, computationState, listener)
|
||||
return PreparatoryWriteIntent(permit.writeIntentPermit, false, computationState, frozenListeners)
|
||||
}
|
||||
is ParallelizablePermit.Write -> {
|
||||
checkWriteFromRead("Write", "Write")
|
||||
return PreparatoryWriteIntent(permit.writePermit, false, computationState, listener)
|
||||
return PreparatoryWriteIntent(permit.writePermit, false, computationState, frozenListeners)
|
||||
}
|
||||
}
|
||||
} catch (e : Throwable) {
|
||||
@@ -965,9 +1022,9 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
|
||||
|
||||
myWriteActionsStack.add(clazz)
|
||||
fireWriteActionStarted(preparatoryWriteIntent.listener, clazz)
|
||||
fireWriteActionStarted(preparatoryWriteIntent.listeners, clazz)
|
||||
|
||||
return WriteLockInitResult(shouldRelease, currentReadState, preparatoryWriteIntent.listener, state, clazz, this)
|
||||
return WriteLockInitResult(shouldRelease, currentReadState, preparatoryWriteIntent.listeners, state, clazz, this)
|
||||
}
|
||||
|
||||
private fun startPendingWriteAction(state: ComputationState) {
|
||||
@@ -983,13 +1040,13 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
private data class WriteLockInitResult(
|
||||
val shouldRelease: Boolean,
|
||||
val currentReadState: Boolean,
|
||||
val listener: WriteActionListener?,
|
||||
val listeners: List<WriteActionListener>,
|
||||
val state: ComputationState,
|
||||
val clazz: Class<*>,
|
||||
val support: NestedLocksThreadingSupport,
|
||||
) {
|
||||
fun release() {
|
||||
support.fireWriteActionFinished(listener, clazz)
|
||||
support.fireWriteActionFinished(listeners, clazz)
|
||||
support.myWriteActionsStack.removeLast()
|
||||
if (shouldRelease) {
|
||||
support.myWriteAcquired = null
|
||||
@@ -997,7 +1054,7 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
}
|
||||
support.myTopmostReadAction.set(currentReadState)
|
||||
if (shouldRelease) {
|
||||
support.fireAfterWriteActionFinished(listener, clazz)
|
||||
support.fireAfterWriteActionFinished(listeners, clazz)
|
||||
support.drainWriteActionFollowups()
|
||||
}
|
||||
}
|
||||
@@ -1098,7 +1155,7 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
if (currentPermit is ReadPermit || currentPermit is WriteIntentPermit) {
|
||||
return { }
|
||||
}
|
||||
val capturedListener = myReadActionListener
|
||||
val capturedListener = readActionListeners
|
||||
val capturedPermit = run {
|
||||
fireBeforeReadActionStart(capturedListener, javaClass)
|
||||
val p = computationState.acquireReadPermit()
|
||||
@@ -1167,99 +1224,76 @@ class NestedLocksThreadingSupport : ThreadingSupport {
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireBeforeReadActionStart(listener: ReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.beforeReadActionStart(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireBeforeReadActionStart(list: List<ReadActionListener>, clazz: Class<*>) {
|
||||
list.traverse {
|
||||
it.beforeReadActionStart(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireReadActionStarted(listener: ReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.readActionStarted(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireReadActionStarted(list: List<ReadActionListener>, clazz: Class<*>) {
|
||||
list.traverse {
|
||||
it.readActionStarted(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireReadActionFinished(listener: ReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.readActionFinished(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireReadActionFinished(list: List<ReadActionListener>, clazz: Class<*>) {
|
||||
list.traverseBackwards {
|
||||
it.readActionFinished(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireAfterReadActionFinished(listener: ReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.afterReadActionFinished(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireAfterReadActionFinished(list: List<ReadActionListener>, clazz: Class<*>) {
|
||||
list.traverseBackwards {
|
||||
it.afterReadActionFinished(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireBeforeWriteActionStart(listener: WriteActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.beforeWriteActionStart(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireBeforeWriteActionStart(listeners: List<WriteActionListener>, clazz: Class<*>) {
|
||||
listeners.traverse {
|
||||
it.beforeWriteActionStart(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireWriteActionStarted(listener: WriteActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.writeActionStarted(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireWriteActionStarted(listeners: List<WriteActionListener>, clazz: Class<*>) {
|
||||
listeners.traverse {
|
||||
it.writeActionStarted(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireWriteActionFinished(listener: WriteActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.writeActionFinished(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireWriteActionFinished(listeners: List<WriteActionListener>, clazz: Class<*>) {
|
||||
listeners.traverseBackwards {
|
||||
it.writeActionFinished(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireAfterWriteActionFinished(listener: WriteActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.afterWriteActionFinished(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireAfterWriteActionFinished(listeners: List<WriteActionListener>, clazz: Class<*>) {
|
||||
listeners.traverseBackwards {
|
||||
it.afterWriteActionFinished(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireBeforeWriteIntentReadActionStart(listener: WriteIntentReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.beforeWriteIntentReadActionStart(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun fireBeforeWriteIntentReadActionStart(listeners: List<WriteIntentReadActionListener>, clazz: Class<*>) {
|
||||
listeners.traverse {
|
||||
it.beforeWriteIntentReadActionStart(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireWriteIntentActionStarted(listener: WriteIntentReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.writeIntentReadActionStarted(clazz)
|
||||
private fun fireWriteIntentActionStarted(listeners: List<WriteIntentReadActionListener>, clazz: Class<*>) {
|
||||
listeners.traverse {
|
||||
it.writeIntentReadActionStarted(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
|
||||
}
|
||||
|
||||
private fun fireWriteIntentActionFinished(listeners: List<WriteIntentReadActionListener>, clazz: Class<*>) {
|
||||
listeners.traverseBackwards {
|
||||
it.writeIntentReadActionFinished(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fireWriteIntentActionFinished(listener: WriteIntentReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.writeIntentReadActionFinished(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun afterWriteIntentReadActionFinished(listener: WriteIntentReadActionListener?, clazz: Class<*>) {
|
||||
try {
|
||||
listener?.afterWriteIntentReadActionFinished(clazz)
|
||||
}
|
||||
catch (_: Throwable) {
|
||||
private fun afterWriteIntentReadActionFinished(listeners: List<WriteIntentReadActionListener>, clazz: Class<*>) {
|
||||
listeners.traverseBackwards {
|
||||
it.afterWriteIntentReadActionFinished(clazz)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
9
platform/locking.impl/src/listeners/ErrorHandler.kt
Normal file
9
platform/locking.impl/src/listeners/ErrorHandler.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.locking.impl.listeners
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
fun interface ErrorHandler {
|
||||
fun handleError(error: Throwable)
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import com.intellij.openapi.application.ex.ApplicationUtil;
|
||||
import com.intellij.openapi.client.ClientAwareComponentManager;
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore;
|
||||
import com.intellij.openapi.diagnostic.Attachment;
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.*;
|
||||
@@ -46,6 +45,7 @@ import com.intellij.platform.diagnostic.telemetry.TelemetryManager;
|
||||
import com.intellij.platform.diagnostic.telemetry.helpers.TraceKt;
|
||||
import com.intellij.platform.locking.impl.IntelliJLockingUtil;
|
||||
import com.intellij.platform.locking.impl.NestedLocksThreadingSupport;
|
||||
import com.intellij.platform.locking.impl.listeners.ErrorHandler;
|
||||
import com.intellij.platform.locking.impl.listeners.LegacyProgressIndicatorProvider;
|
||||
import com.intellij.platform.locking.impl.listeners.LockAcquisitionListener;
|
||||
import com.intellij.psi.util.ReadActionCache;
|
||||
@@ -55,7 +55,6 @@ import com.intellij.util.concurrency.*;
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||
import com.intellij.util.concurrency.annotations.RequiresWriteLock;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.DisposableWrapperList;
|
||||
import com.intellij.util.messages.Topic;
|
||||
import com.intellij.util.ui.EDT;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
@@ -70,13 +69,13 @@ import org.jetbrains.annotations.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -103,8 +102,47 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
private final ModalityInvokator myInvokator = new ModalityInvokatorImpl();
|
||||
|
||||
private final EventDispatcher<ApplicationListener> myDispatcher = EventDispatcher.create(ApplicationListener.class);
|
||||
private final WriteActionListener appListenerDispatcherWrapper = new WriteActionListener() {
|
||||
@Override
|
||||
public void beforeWriteActionStart(@NotNull Class<?> action) {
|
||||
ActivityTracker.getInstance().inc();
|
||||
myDispatcher.getMulticaster().beforeWriteActionStart(action);
|
||||
}
|
||||
|
||||
private final LockDispatchListener myLockDispatcherListener = new LockDispatchListener();
|
||||
@Override
|
||||
public void writeActionStarted(@NotNull Class<?> action) {
|
||||
myDispatcher.getMulticaster().writeActionStarted(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeActionFinished(@NotNull Class<?> action) {
|
||||
myDispatcher.getMulticaster().writeActionFinished(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterWriteActionFinished(@NotNull Class<?> action) {
|
||||
otelMonitor.get().writeActionExecuted();
|
||||
myDispatcher.getMulticaster().afterWriteActionFinished(action);
|
||||
}
|
||||
};
|
||||
|
||||
private final ReadActionListener customReadActionListener = new ReadActionListener() {
|
||||
@Override
|
||||
public void readActionFinished(@NotNull Class<?> action) {
|
||||
myReadActionCacheImpl.clear();
|
||||
otelMonitor.get().readActionExecuted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastPathAcquisitionFailed() {
|
||||
// Impatient reader not in non-cancellable session will not wait
|
||||
if (myImpatientReader.get() && !Cancellation.isInNonCancelableSection()) {
|
||||
throw ApplicationUtil.CannotRunReadActionException.create();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static final ErrorHandler lockingErrorHandler = (error) -> getLogger().error(error);
|
||||
|
||||
private final boolean myTestModeFlag;
|
||||
private final boolean myHeadlessMode;
|
||||
@@ -390,12 +428,10 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
getThreadingSupport().removeReadActionListener(myLockDispatcherListener);
|
||||
getThreadingSupport().removeWriteActionListener(myLockDispatcherListener);
|
||||
getThreadingSupport().removeWriteIntentReadActionListener(myLockDispatcherListener);
|
||||
lock.removeLockAcquisitionListener(myLockDispatcherListener);
|
||||
getThreadingSupport().removeWriteLockReacquisitionListener(myLockDispatcherListener);
|
||||
lock.removeErrorHandler();
|
||||
lock.removeLegacyIndicatorProvider(myLegacyIndicatorProvider);
|
||||
lock.removeWriteActionListener(appListenerDispatcherWrapper);
|
||||
lock.removeReadActionListener(customReadActionListener);
|
||||
|
||||
//noinspection deprecation
|
||||
myDispatcher.getMulticaster().applicationExiting();
|
||||
@@ -940,7 +976,7 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
|
||||
private boolean canExit(boolean restart) {
|
||||
for (ApplicationListener applicationListener : myDispatcher.getListeners()) {
|
||||
if (restart && !applicationListener.canRestartApplication()
|
||||
if (restart && !applicationListener.canRestartApplication()
|
||||
|| !restart && !applicationListener.canExitApplication()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1268,23 +1304,6 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
myDispatcher.removeListener(l);
|
||||
}
|
||||
|
||||
private void fireBeforeWriteActionStart(@NotNull Class<?> action) {
|
||||
myDispatcher.getMulticaster().beforeWriteActionStart(action);
|
||||
}
|
||||
|
||||
private void fireWriteActionStarted(@NotNull Class<?> action) {
|
||||
myDispatcher.getMulticaster().writeActionStarted(action);
|
||||
}
|
||||
|
||||
private void fireWriteActionFinished(@NotNull Class<?> action) {
|
||||
myDispatcher.getMulticaster().writeActionFinished(action);
|
||||
}
|
||||
|
||||
private void fireAfterWriteActionFinished(@NotNull Class<?> action) {
|
||||
myDispatcher.getMulticaster().afterWriteActionFinished(action);
|
||||
otelMonitor.get().writeActionExecuted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveSettings() {
|
||||
if (mySaveAllowed) {
|
||||
@@ -1324,10 +1343,10 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
+ (isHeadlessEnvironment() ? " (headless)" : "")
|
||||
+ (isCommandLine() ? " (command line)" : "")
|
||||
+ (writeActionPending || writeActionInProgress || writeAccessAllowed ? " (WA" +
|
||||
(writeActionPending ? " pending" : "") +
|
||||
(writeActionInProgress ? " inProgress" : "") +
|
||||
(writeAccessAllowed ? " allowed" : "") +
|
||||
")" : "")
|
||||
(writeActionPending ? " pending" : "") +
|
||||
(writeActionInProgress ? " inProgress" : "") +
|
||||
(writeAccessAllowed ? " allowed" : "") +
|
||||
")" : "")
|
||||
+ (isReadAccessAllowed() ? " (RA allowed)" : "")
|
||||
+ (isInImpatientReader() ? " (impatient reader)" : "")
|
||||
+ (isExitInProgress() ? " (exit in progress)" : "")
|
||||
@@ -1382,12 +1401,10 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
return true;
|
||||
}, app.getCoroutineScope());
|
||||
|
||||
app.lock.setReadActionListener(app.myLockDispatcherListener);
|
||||
app.lock.setWriteActionListener(app.myLockDispatcherListener);
|
||||
app.lock.setWriteIntentReadActionListener(app.myLockDispatcherListener);
|
||||
app.lock.setLockAcquisitionListener(app.myLockDispatcherListener);
|
||||
app.lock.setWriteLockReacquisitionListener(app.myLockDispatcherListener);
|
||||
app.lock.addReadActionListener(app.customReadActionListener);
|
||||
app.lock.addWriteActionListener(app.appListenerDispatcherWrapper);
|
||||
app.lock.setLegacyIndicatorProvider(myLegacyIndicatorProvider);
|
||||
app.lock.setErrorHandler(lockingErrorHandler);
|
||||
if (ThreadingRuntimeFlagsKt.getInstallSuvorovProgress()) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
SuvorovProgress.INSTANCE.init(app);
|
||||
@@ -1417,21 +1434,25 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
|
||||
@Override
|
||||
public void addWriteActionListener(@NotNull WriteActionListener listener, @NotNull Disposable parentDisposable) {
|
||||
myLockDispatcherListener.addWriteActionListener(listener, parentDisposable);
|
||||
lock.addWriteActionListener(listener);
|
||||
Disposer.register(parentDisposable, () -> lock.removeWriteActionListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addReadActionListener(@NotNull ReadActionListener listener, @NotNull Disposable parentDisposable) {
|
||||
myLockDispatcherListener.addReadActionListener(listener, parentDisposable);
|
||||
lock.addReadActionListener(listener);
|
||||
Disposer.register(parentDisposable, () -> lock.removeReadActionListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWriteIntentReadActionListener(@NotNull WriteIntentReadActionListener listener, @NotNull Disposable parentDisposable) {
|
||||
myLockDispatcherListener.addWriteIntentReadActionListener(listener, parentDisposable);
|
||||
lock.addWriteIntentReadActionListener(listener);
|
||||
Disposer.register(parentDisposable, () -> lock.removeWriteIntentReadActionListener(listener));
|
||||
}
|
||||
|
||||
public void addLockAcquisitionListener(@NotNull LockAcquisitionListener listener, @NotNull Disposable parentDisposable) {
|
||||
myLockDispatcherListener.addLockAcquisitionListener(listener, parentDisposable);
|
||||
lock.setLockAcquisitionListener(listener);
|
||||
Disposer.register(parentDisposable, () -> lock.removeLockAcquisitionListener(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1456,168 +1477,10 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
|
||||
@Override
|
||||
public void addSuspendingWriteActionListener(@NotNull WriteLockReacquisitionListener listener, @NotNull Disposable parentDisposable) {
|
||||
myLockDispatcherListener.addSuspendingWriteActionListener(listener, parentDisposable);
|
||||
lock.setWriteLockReacquisitionListener(listener);
|
||||
Disposer.register(parentDisposable, () -> lock.removeWriteLockReacquisitionListener(listener));
|
||||
}
|
||||
|
||||
/**
|
||||
* inner class by intention
|
||||
*/
|
||||
private class LockDispatchListener
|
||||
implements ReadActionListener, WriteActionListener, WriteIntentReadActionListener, LockAcquisitionListener,
|
||||
WriteLockReacquisitionListener {
|
||||
|
||||
private final DisposableWrapperList<WriteActionListener> myWriteActionListeners = new DisposableWrapperList<>();
|
||||
|
||||
private final DisposableWrapperList<ReadActionListener> myReadActionListeners = new DisposableWrapperList<>();
|
||||
|
||||
private final DisposableWrapperList<WriteIntentReadActionListener> myWriteIntentReadActionListeners =
|
||||
new DisposableWrapperList<>();
|
||||
|
||||
private final DisposableWrapperList<LockAcquisitionListener> myLockAcquisitionListeners =
|
||||
new DisposableWrapperList<>();
|
||||
|
||||
private final DisposableWrapperList<WriteLockReacquisitionListener> myWriteLockReacquisitionListeners =
|
||||
new DisposableWrapperList<>();
|
||||
|
||||
public void addWriteActionListener(WriteActionListener listener, Disposable disposable) {
|
||||
addListener(myWriteActionListeners, listener, disposable);
|
||||
}
|
||||
|
||||
public void addReadActionListener(ReadActionListener listener, Disposable disposable) {
|
||||
addListener(myReadActionListeners, listener, disposable);
|
||||
}
|
||||
|
||||
public void addWriteIntentReadActionListener(WriteIntentReadActionListener listener, Disposable disposable) {
|
||||
addListener(myWriteIntentReadActionListeners, listener, disposable);
|
||||
}
|
||||
|
||||
public void addSuspendingWriteActionListener(WriteLockReacquisitionListener listener, Disposable disposable) {
|
||||
addListener(myWriteLockReacquisitionListeners, listener, disposable);
|
||||
}
|
||||
|
||||
public void addLockAcquisitionListener(LockAcquisitionListener listener, Disposable disposable) {
|
||||
addListener(myLockAcquisitionListeners, listener, disposable);
|
||||
}
|
||||
|
||||
private static <T extends EventListener> void addListener(DisposableWrapperList<T> list, T listener, Disposable disposable) {
|
||||
list.add(listener, disposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeActionFinished(@NotNull Class<?> action) {
|
||||
ApplicationImpl.this.fireWriteActionFinished(action);
|
||||
invokeListeners(myWriteActionListeners, WriteActionListener::writeActionFinished, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterWriteActionFinished(@NotNull Class<?> action) {
|
||||
ApplicationImpl.this.fireAfterWriteActionFinished(action);
|
||||
invokeListeners(myWriteActionListeners, WriteActionListener::afterWriteActionFinished, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeWriteLockAcquired() {
|
||||
invokeListeners(myLockAcquisitionListeners, LockAcquisitionListener::beforeWriteLockAcquired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterWriteLockAcquired() {
|
||||
invokeListeners(myLockAcquisitionListeners, LockAcquisitionListener::afterWriteLockAcquired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeIntentReadActionStarted(@NotNull Class<?> action) {
|
||||
invokeListeners(myWriteIntentReadActionListeners, WriteIntentReadActionListener::writeIntentReadActionStarted, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeIntentReadActionFinished(@NotNull Class<?> action) {
|
||||
invokeListeners(myWriteIntentReadActionListeners, WriteIntentReadActionListener::writeIntentReadActionFinished, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeWriteIntentReadActionStart(@NotNull Class<?> action) {
|
||||
invokeListeners(myWriteIntentReadActionListeners, WriteIntentReadActionListener::beforeWriteIntentReadActionStart, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterWriteIntentReadActionFinished(@NotNull Class<?> action) {
|
||||
invokeListeners(myWriteIntentReadActionListeners, WriteIntentReadActionListener::afterWriteIntentReadActionFinished, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeWriteLockReacquired() {
|
||||
invokeListeners(myWriteLockReacquisitionListeners, WriteLockReacquisitionListener::beforeWriteLockReacquired);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void readActionStarted(@NotNull Class<?> action) {
|
||||
invokeListeners(myReadActionListeners, ReadActionListener::readActionStarted, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastPathAcquisitionFailed() {
|
||||
// Impatient reader not in non-cancellable session will not wait
|
||||
if (myImpatientReader.get() && !Cancellation.isInNonCancelableSection()) {
|
||||
throw ApplicationUtil.CannotRunReadActionException.create();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeReadActionStart(@NotNull Class<?> action) {
|
||||
invokeListeners(myReadActionListeners, ReadActionListener::beforeReadActionStart, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterReadActionFinished(@NotNull Class<?> action) {
|
||||
invokeListeners(myReadActionListeners, ReadActionListener::afterReadActionFinished, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readActionFinished(@NotNull Class<?> action) {
|
||||
myReadActionCacheImpl.clear();
|
||||
invokeListeners(myReadActionListeners, ReadActionListener::readActionFinished, action);
|
||||
otelMonitor.get().readActionExecuted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeWriteActionStart(@NotNull Class<?> action) {
|
||||
ActivityTracker.getInstance().inc();
|
||||
ApplicationImpl.this.fireBeforeWriteActionStart(action);
|
||||
invokeListeners(myWriteActionListeners, WriteActionListener::beforeWriteActionStart, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeActionStarted(@NotNull Class<?> action) {
|
||||
ApplicationImpl.this.fireWriteActionStarted(action);
|
||||
invokeListeners(myWriteActionListeners, WriteActionListener::writeActionStarted, action);
|
||||
}
|
||||
|
||||
private static <T extends EventListener> void invokeListeners(List<T> listeners, BiConsumer<T, Class<?>> applier, Class<?> arg) {
|
||||
invokeListeners(listeners, (listener) -> applier.accept(listener, arg));
|
||||
}
|
||||
|
||||
private static <T extends EventListener> void invokeListeners(List<T> listeners, Consumer<T> applier) {
|
||||
List<Throwable> exceptions = new SmartList<>();
|
||||
for (T listener : listeners) {
|
||||
try {
|
||||
applier.accept(listener);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
exceptions.add(t);
|
||||
}
|
||||
}
|
||||
for (Throwable exception : exceptions) {
|
||||
if (exception instanceof CancellationException || exception instanceof ControlFlowException) {
|
||||
continue;
|
||||
}
|
||||
getLogger().error(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public kotlin.Pair<CoroutineContext, AccessToken> getLockStateAsCoroutineContext(CoroutineContext baseContext, boolean shared) {
|
||||
var pair = getThreadingSupport().getPermitAsContextElement(baseContext, shared);
|
||||
@@ -1635,7 +1498,7 @@ public final class ApplicationImpl extends ClientAwareComponentManager implement
|
||||
}
|
||||
|
||||
public @NotNull ThreadingSupport getThreadingSupport() {
|
||||
return IntelliJLockingUtil.getGlobalThreadingSupport();
|
||||
return lock;
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread(generateAssertion = false)
|
||||
|
||||
Reference in New Issue
Block a user