Skip to content

Instantly share code, notes, and snippets.

@pmhsfelix
Last active November 17, 2018 16:50
Show Gist options
  • Save pmhsfelix/b99088cae33321d336760ce99279866a to your computer and use it in GitHub Desktop.
Save pmhsfelix/b99088cae33321d336760ce99279866a to your computer and use it in GitHub Desktop.
Making sense of coroutine scopes

The following code ...

@Test
fun nested_coroutines5() {
    log.info("start")
    val res = runBlocking {
        launch {
            launch {
                completeAfter(2500)
            }
            completeAfter(2000)
        }
        GlobalScope.launch {
            completeAfter(3000)
        }
        val d1 = async {
            completeAfter(500)
            1
        }
        val d2 = async {
            completeAfter(1000)
            2
        }
        log.info("before await")
        val sum = d1.await() + d2.await()
        log.info("after await, before return")
        sum
    }
    log.info("end")
}

produces

5 [main] INFO ScopeTests2 - start
82 [main @coroutine#1] INFO ScopeTests2 - before await
591 [main @coroutine#4] INFO ScopeTests2 - completing
1087 [main @coroutine#5] INFO ScopeTests2 - completing
1088 [main @coroutine#1] INFO ScopeTests2 - after await, before return
2089 [main @coroutine#2] INFO ScopeTests2 - completing
2590 [main @coroutine#6] INFO ScopeTests2 - completing
2591 [main] INFO ScopeTests2 - end

Notice

  • The "before await" is reached rather quickly, since launching the inner coroutines doesn't block
  • The "after await, before return" is logged at ~1000, after d1 and d2 complete
  • However, "end" is only logged at ~2500, after the first child launch also completes
  • That is, the coroutine is only completed when
    • Its sequential flow is completed
    • Its child coroutines are completed
  • Note that the coroutines that takes 3000 ms is not waited for because it isn't a child coroutine. Tt was created using GlobalScope, so it detached from the parent-child tree.
coroutine#1 (completes after max(max(2000ms, 2500ms), 500ms, 1000ms))
    coroutine#2 (completes after max(2000ms, 2500ms)
        coroutine#6 (completes after 2500ms)
    coroutine#3 (not a child from coroutine1)
    coroutine#4 (completes after 500ms)
    coroutine#5 (completes after 1000ms)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment