diff --git a/platform/ide-core/src/com/intellij/util/SingleAlarm.kt b/platform/ide-core/src/com/intellij/util/SingleAlarm.kt index 054e36991d6a..4a032e0143d1 100644 --- a/platform/ide-core/src/com/intellij/util/SingleAlarm.kt +++ b/platform/ide-core/src/com/intellij/util/SingleAlarm.kt @@ -46,6 +46,7 @@ class SingleAlarm @Internal constructor( ) : Disposable { // it is a supervisor coroutine scope private val taskCoroutineScope: CoroutineScope + private val taskContext: CoroutineContext private val LOCK = Any() @@ -241,11 +242,16 @@ class SingleAlarm @Internal constructor( } override fun dispose() { + isDisposed = true cancel() } - val isDisposed: Boolean - get() = !taskCoroutineScope.isActive + // SingleAlarm can be created without `parentDisposable`. + // So, we cannot create child scope. So, we cannot use `!taskCoroutineScope.isActive` to implement `isDisposed`. + @Volatile + var isDisposed: Boolean = false + get() = field || !taskCoroutineScope.isActive + private set val isEmpty: Boolean get() = synchronized(LOCK) { currentJob == null } diff --git a/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.kt b/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.kt index 9c5d5cbaf3c9..4942c8dc8e8d 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.kt @@ -9,6 +9,8 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.EDT import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.impl.LaterInvocator +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.use import com.intellij.testFramework.LoggedErrorProcessor import com.intellij.testFramework.assertions.Assertions.assertThat import com.intellij.testFramework.junit5.TestApplication @@ -29,6 +31,17 @@ import java.util.concurrent.atomic.AtomicInteger @TestApplication class AlarmTest { + @Test + fun `isDisposed is true if parentDisposable used`() { + val disposable = Disposer.newDisposable() + disposable.use { + @Suppress("DEPRECATION") + val alarm = SingleAlarm.pooledThreadSingleAlarm(delay = 100, parentDisposable = disposable) { } + Disposer.dispose(disposable) + assertThat(alarm.isDisposed).isTrue() + } + } + @Test fun `cancel request by task`(@TestDisposable disposable: Disposable): Unit = runBlocking(Dispatchers.EDT) { val alarm = Alarm(threadToUse = Alarm.ThreadToUse.SWING_THREAD, parentDisposable = disposable)