Does a coroutine gets suspended or suspend function gets suspended?

I understand that withcontext does not create a coroutine but schedule the coroutine on a new dispatcher. Now the suspend function which called withcontext is running in the same coroutine as withcontext suspend lambda.

So coroutine never got suspended it’s the calling suspend function that got suspended. Is my understanding correct?

Not quite, withContext creates a new coroutine. The calling coroutine suspends until the the child coroutine finishes. This happens even if the exact same context is used and no dispatch is needed.

If you call delay from myDelay, is delay suspended or myDelay, or the method that called myDelay? The whole chain is suspended. It’s the whole coroutine, not a specific method invocation, that is suspended and resumed.

If a coroutine has suspended, it is not running anywhere else. A coroutine only ever has one “call stack”. It’s not technically a call stack, it’s a chain of callbacks, but it’s the same concept.

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        println("in sub coroutine ${Thread.currentThread().name}")
    }
    println("before coroutine in main ${Thread.currentThread().name}")
    withContext(Dispatchers.IO) {
        println("hello from coroutine ${Thread.currentThread().name}")
        delay(1500)
        println("hello from coutoutine after delay ${Thread.currentThread().name}")
    }
    println("after coroutine in main ${Thread.currentThread().name}")
}

Output of above code:

before coroutine in main main @coroutine#1
hello from coroutine DefaultDispatcher-worker-1 @coroutine#1
in sub coroutine main @coroutine#2
hello from coutoutine after delay DefaultDispatcher-worker-1 @coroutine#1
after coroutine in main main @coroutine#1

No new coroutine created by withContext, so what is getting suspended?

Sorry, forgot that the docs tends to talk about coroutines just as code paths that execute sequentially. I was talking about the actual coroutine classes used in the source code. Source code clearly creates coroutine instances: withContext

That name in the output comes from the CoroutineName in the CoroutineContext. It makes sense that only methods that create parallel coroutines would change the CoroutineName used. Logically it’s all the same sequence of work with methods like withContext or coroutineScope even if underneath it’s a separate coroutine instance with its own Job and everything.

1 Like

I suggest you a Coroutine overview.

An invocation to a suspending function may suspends the coroutine.

A suspension point — is a point during coroutine execution where the execution of the coroutine may be suspended.
Syntactically, a suspension point is an invocation of suspending function, but the actual suspension happens when the suspending function invokes the standard library primitive to suspend the execution.

1 Like

Yes will read it and hopefully it clears my doubts.

I went through above documentation, few things get cleared up but I think it needs few more readings from my side to understand it fully. Thanks for sharing a good read.