Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the purpose of combining coroutine contexts in Kotlin?

https://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html#combining-context-elements

The official document says I can combine some coroutine contexts, but what's the purpose of doing so and what's the effect? Does that mean the coroutine's lifecycle is confined to both contexts?

like image 794
goodonion Avatar asked Mar 03 '20 08:03

goodonion


2 Answers

I think you are confusing CoroutineContext and CoroutineDispatcher (possibly also CoroutineScope). Dispatcher is only one kind of Context. Others can be eg. Job, CoroutineName, CoroutineExceptionHandler. You can combine multiple of these - eg. to set dispatcher and error handler - but only have one of each type.

It does not make sense to combine multiple dispatchers, the only the last one will be applied.

I found the talk Coroutines! Gotta catch 'em all! by Florina Muntenescu & Manuel Vivo from KotlinConf 2019 explaining some of this quite well.

like image 200
ferini Avatar answered Oct 12 '22 23:10

ferini


I can combine some coroutine contexts, but what's the purpose of doing so and what's the effect?

A coroutine context is basically an immutable map. When you combine two immutable maps, you get a map containing all the keys of the constituent maps. Obviously, if both maps contain a given key, the resulting map can't contain it twice. Instead the right-hand map takes precedence.

A slight twist on the map paradigm is that you don't put (key, value) pairs into a context, instead every value you put already has a key associated with it. That's why every context element is already a context itself.

For example, these are two full-blown contexts:

val ioCtx = Dispatchers.IO
val jobCtx = Job()

You can combine them:

val ioAndJob = ioCtx + jobCtx

You can access an element by key:

val job = ioAndJob[Job]

You can combine contexts with colliding keys:

val defaultAndJob = ioAndJob + Dispatchers.Default

Does that mean the coroutine's lifecycle is confined to both contexts?

A coroutine context doesn't confine a coroutine lifecycle. Some outside agency is required to cancel the job in the coroutine context. You have probably confused this with CoroutineScope which takes care of this concern. CoroutineScope is just an object with a single property, coroutineContext, but since coroutine builders such as launch or async take it as a receiver, it makes it easy to build a coroutine hierarchy that can be centrally cancelled.

like image 26
Marko Topolnik Avatar answered Oct 13 '22 00:10

Marko Topolnik