Skip to content

Commit 7eb4618

Browse files
qwwdfsadpablobaxter
authored andcommitted
Reduce reachable references of disposed invokeOnTimeout handle (Kotlin#3353)
* Reduce reachable references of disposed invokeOnTimeout handle Fixes Kotlin#3351
1 parent d8888df commit 7eb4618

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

kotlinx-coroutines-core/native/src/MultithreadedDispatchers.kt

+19-3
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,25 @@ internal class WorkerDispatcher(name: String) : CloseableCoroutineDispatcher(),
3535
}
3636

3737
override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle {
38-
// No API to cancel on timeout
39-
worker.executeAfter(timeMillis.toMicrosSafe()) { block.run() }
40-
return NonDisposableHandle
38+
// Workers don't have an API to cancel sent "executeAfter" block, but we are trying
39+
// to control the damage and reduce reachable objects by nulling out `block`
40+
// that may retain a lot of references, and leaving only an empty shell after a timely disposal
41+
// This is a class and not an object with `block` in a closure because that would defeat the purpose.
42+
class DisposableBlock(block: Runnable) : DisposableHandle, Function0<Unit> {
43+
private val disposableHolder = AtomicReference<Runnable?>(block)
44+
45+
override fun invoke() {
46+
disposableHolder.value?.run()
47+
}
48+
49+
override fun dispose() {
50+
disposableHolder.value = null
51+
}
52+
}
53+
54+
val disposableBlock = DisposableBlock(block)
55+
worker.executeAfter(timeMillis.toMicrosSafe(), disposableBlock)
56+
return disposableBlock
4157
}
4258

4359
override fun close() {

0 commit comments

Comments
 (0)