-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathTestDispatcher.kt
61 lines (53 loc) · 2.23 KB
/
TestDispatcher.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.test
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.jvm.*
/**
* A test dispatcher that can interface with a [TestCoroutineScheduler].
*
* The available implementations are:
* * [StandardTestDispatcher] is a dispatcher that places new tasks into a queue.
* * [UnconfinedTestDispatcher] is a dispatcher that behaves like [Dispatchers.Unconfined] while allowing to control
* the virtual time.
*/
@ExperimentalCoroutinesApi
public abstract class TestDispatcher internal constructor() : CoroutineDispatcher(), Delay {
/** The scheduler that this dispatcher is linked to. */
@ExperimentalCoroutinesApi
public abstract val scheduler: TestCoroutineScheduler
/** Notifies the dispatcher that it should process a single event marked with [marker] happening at time [time]. */
internal fun processEvent(time: Long, marker: Any) {
check(marker is Runnable)
marker.run()
}
/** @suppress */
override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
val timedRunnable = CancellableContinuationRunnable(continuation, this)
val handle = scheduler.registerEvent(
this,
timeMillis,
timedRunnable,
continuation.context,
::cancellableRunnableIsCancelled
)
continuation.disposeOnCancellation(handle)
}
/** @suppress */
override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle =
scheduler.registerEvent(this, timeMillis, block, context) { false }
}
/**
* This class exists to allow cleanup code to avoid throwing for cancelled continuations scheduled
* in the future.
*/
private class CancellableContinuationRunnable(
@JvmField val continuation: CancellableContinuation<Unit>,
private val dispatcher: CoroutineDispatcher
) : Runnable {
override fun run() = with(dispatcher) { with(continuation) { resumeUndispatched(Unit) } }
}
private fun cancellableRunnableIsCancelled(runnable: CancellableContinuationRunnable): Boolean =
!runnable.continuation.isActive