• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines.test.internal
6 
7 import kotlinx.coroutines.*
8 import kotlinx.coroutines.internal.*
9 import kotlin.coroutines.*
10 
11 /**
12  * The testable main dispatcher used by kotlinx-coroutines-test.
13  * It is a [MainCoroutineDispatcher] which delegates all actions to a settable delegate.
14  */
15 internal class TestMainDispatcher(private val mainFactory: MainDispatcherFactory) : MainCoroutineDispatcher(), Delay {
16     private var _delegate: CoroutineDispatcher? = null
17     private val delegate: CoroutineDispatcher get() {
<lambda>null18         _delegate?.let { return it }
<lambda>null19         mainFactory.tryCreateDispatcher(emptyList()).let {
20             // If we've failed to create a dispatcher, do no set _delegate
21             if (!isMissing()) {
22                 _delegate = it
23             }
24             return it
25         }
26     }
27 
28     @Suppress("INVISIBLE_MEMBER")
29     private val delay: Delay get() = delegate as? Delay ?: DefaultDelay
30 
31     override val immediate: MainCoroutineDispatcher
32         get() = (delegate as? MainCoroutineDispatcher)?.immediate ?: this
33 
dispatchnull34     override fun dispatch(context: CoroutineContext, block: Runnable) {
35         delegate.dispatch(context, block)
36     }
37 
38     @ExperimentalCoroutinesApi
isDispatchNeedednull39     override fun isDispatchNeeded(context: CoroutineContext): Boolean = delegate.isDispatchNeeded(context)
40 
41     override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
42         delay.scheduleResumeAfterDelay(timeMillis, continuation)
43     }
44 
delaynull45     override suspend fun delay(time: Long) {
46         delay.delay(time)
47     }
48 
invokeOnTimeoutnull49     override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
50         return delay.invokeOnTimeout(timeMillis, block)
51     }
52 
setDispatchernull53     public fun setDispatcher(dispatcher: CoroutineDispatcher) {
54         _delegate = dispatcher
55     }
56 
resetDispatchernull57     public fun resetDispatcher() {
58         _delegate = null
59     }
60 }
61 
62 internal class TestMainDispatcherFactory : MainDispatcherFactory {
63 
createDispatchernull64     override fun createDispatcher(allFactories: List<MainDispatcherFactory>): MainCoroutineDispatcher {
65         val originalFactory = allFactories.asSequence()
66             .filter { it !== this }
67             .maxBy { it.loadPriority } ?: MissingMainCoroutineDispatcherFactory
68         return TestMainDispatcher(originalFactory)
69     }
70 
71     /**
72      * [Int.MAX_VALUE] -- test dispatcher always wins no matter what factories are present in the classpath.
73      * By default all actions are delegated to the second-priority dispatcher, so that it won't be the issue.
74      */
75     override val loadPriority: Int
76         get() = Int.MAX_VALUE
77 }
78