Kotlinx.coroutines: Confuse at "Coroutine contexts can be combined using + operator"

Created on 10 Oct 2017  路  8Comments  路  Source: Kotlin/kotlinx.coroutines

Well, a lot of questions about the + operator for context.

I can use commonPool + job(or coroutineContext) or job(or coroutineContext) + commonPool do the same thing and canceling a launch with calling cancel on job(or coroutineContext), however, when I use newSingleThreadContext, there's a difference between newSingleThreadContext + job(or coroutineContext) and job(or coroutineContext) + newSingleThreadContext . Only the first one can be canceled by job(or coroutineContext) like commonPool case.

Is it really not consistent of + operator? need some tips on this topic.

Have some codes which are ready for the combination of all these dispatchers or context.

fun logln(msg: String) = println("[${Thread.currentThread().name}: ] $msg")
fun combineContext() = launch(newSingleThreadContext("worker-parent")) {
    logln("Evaluation the combination of contexts")
    logln("echo parent")
    val job = Job() //Only for fun, it can abort all launches and make child not child of parent.
    launch(  //CommonPool
            newSingleThreadContext("worker-child 0") + coroutineContext  //+ job // 
    ) {
        delay(3, TimeUnit.SECONDS)
        launch(  //CommonPool
                newSingleThreadContext("worker-child 1") + coroutineContext //+ job
        ) {
            delay(3, TimeUnit.SECONDS)
            launch( //CommonPool
                    newSingleThreadContext("worker-child 2") + coroutineContext //+ job
            ) {
                delay(3, TimeUnit.SECONDS)
                logln("echo child 3")
            }
            logln("echo child 2")
        }
        logln("echo child 1")
    }
    //job.cancel() 
    //coroutineContext.cancel() 
}

Most helpful comment

All 8 comments

Coroutine context behaves like a map of context elements. You can run this code to get some intuition:

fun main(args: Array<String>) {
    println(mapOf(1 to "A") + mapOf(2 to "B")) // {1=A, 2=B}
    println(mapOf(1 to "A") + mapOf(1 to "B")) // {1=B}
    println(mapOf(1 to "B") + mapOf(1 to "A")) // {1=A}  
}

Does it help?

so, ok, might be a little improved. that means....

launch(a+b+c....) {...},

i.e The right ones will only overwrite the same or shared properties that the left ones also have, am I right?

Yes. Elements to the right of + overwrite elements with they same _key_ to the left. Just like with maps. Context is conceptually a map.

ok, got it.

The last Q: cancellation on coroutine.

launch(a+b+c....) {...},

because I've tried job+ newSingleThreadContext and newSingleThreadContext + job.
the job can cancel only at 2nd case, the 1.st case brings nothing, however, the job can cancel for case like CommonPool + job and job + CommonPool,

any magic ?

@elizarov now, all in , got it, thx

Note, that the logic of newSingleThreadContext is being change in the last release. See #149 for details

@elizarov so well, this change can put down my confuse now.

coroutineContext + newSingleThreadContext("worker-child 0") //+ coroutineContext

works same putting parent left or right, it solves confuse and logic-natural like other cases.

Was this page helpful?
0 / 5 - 0 ratings