Ksenia
Ksenia

Reputation: 3753

Dispatchers used with CoroutineScope() factory function

I'm playing with coroutines and I've tried to run the following code:

private val myScope = CoroutineScope(CoroutineName("my own coroutine"))
fun destroy() {
    myScope.cancel()
}

fun main() {
    myScope.launch {
        println("I'm working in thread ${Thread.currentThread().name}")
    }
    destroy()
}

And surprisingly for me, the output that I've got was the following:

I'm working in thread DefaultDispatcher-worker-1 @my own coroutine#1

I'm wondering where did DefaultDispatcher come from... Because I didn't specify Dispatcher explicitly.

Upvotes: 1

Views: 351

Answers (1)

J.Grbo
J.Grbo

Reputation: 475

If you dig into the source you'll find out the following:

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
    val combined = coroutineContext + context
    val debug = if (DEBUG) combined + CoroutineId(COROUTINE_ID.incrementAndGet()) else combined
    return if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)
        debug + Dispatchers.Default else debug
}

Since you didn't pass a CoroutineDispatcher to the scope itself coroutineContext doesn't have it and you did not pass any CoroutineDispatcher to the launch, context is equal to EmptyCoroutineContext. If you're not debugging, debug equals to combined and combined is not holding the reference to Dispatchers.Default and combined[ContinuationInterceptor] is null, since CoroutineDispatcher inherits ContinuationInterceptor and none is provided, therefore the final returned context is equal to debug (CoroutineName + Job() (provided by CoroutineScope() method, since you didn't provide it yourself) + EmptyCoroutineContext] + Dispatchers.Default.

Upvotes: 1

Related Questions