# Things every Kotlin Developer should know about Coroutines. 

Part 1: CoroutineContext.

The `CoroutineContext` is the backbone of the coroutines library. Every coroutine you launch will have a context. However, given its nature and flexible API, it might prove pretty tricky to use it correctly.

In Part 1 of my series about coroutines, I will take a close look at the `CoroutineContext` and discuss the best practices on how to use it.

## CoroutineContext Under the Hood

To kick this article off, let's take a look at the declaration of `CoroutineContext`:

```kotlin
/**
 * Persistent context for the coroutine. 
 * It is an indexed set of [Element] instances.
 * An indexed set is a mix between a set and a map.
 * Every element in this set has a unique [Key].
 */
@SinceKotlin("1.3")
public interface CoroutineContext
```

As we can see from the KDoc, in broad terms, the `CoroutineContext` is just a `Map` that stores a set of `Element` objects that have a unique `Key`.

We can access those `Element`s using a `Key`, just as we would in a normal `Map`:

```kotlin
/**
  * Returns the element with the given [key] from this context or `null`.
  */
public operator fun <E : Element> get(key: Key<E>): E?
```

However, notice that the `Key` is typed. We will discuss that a bit later.

## CoroutineContext Elements

Since `CoroutineContext` is nothing more than a container, the most important part is its content.

An `Element` is anything a coroutine might need to run correctly. The most common examples would be:

- `Job` - a cancellable handle to a coroutine with a lifecycle;
- `CoroutineDispatcher`, `MainCoroutineDispatcher` - dispatchers for a coroutine to run on;
- `CoroutineId`, `CoroutineName`  - elements mainly used to debug coroutines;
- `CoroutineExceptionHandler` - an element that handles uncaught exceptions.

There are many more elements defined in the coroutines library, but these are the main ones that you would use in your code.

When it comes to the implementation of `Element`s, it is curious how the coroutines library uses typed `Key`s.

Here is how we would get a `Job` from the coroutine context, using a `Key`:

```kotlin
val job = coroutineContext[Job] 
```

As you can see, the `Key` is just the name of the `Element` we want to access. This is not a syntax you see often, but it is a perfectly valid Kotlin syntax nevertheless.

The `Key` for each `Element` is just a plain `companion object` of that element that implements `Key<Element>` interface, and therefore, we can use it as a `Key` for the given type.

Here is an example:

```kotlin
public interface Job : CoroutineContext.Element {
    /**
     * Key for [Job] instance in the coroutine context.
     */
    public companion object Key : CoroutineContext.Key<Job>
```

## Modifying a CoroutineContext

A `CoroutineContext` behaves like an immutable map - it doesn't have a `set` function. Therefore, you can read stored elements, but can't modify them directly:

```kotlin
// we can read the elements stored in a context by their Key
val job = coroutineContext[Job] 
// we cannot modify stored elements
coroutineContext[Job] = Job() <- compiler error
```

That doesn't mean, however, that we cannot modify a `CoroutineContext`. For that, it has dedicated functions, such as:

```kotlin
/**
  * Returns a context containing elements from this context 
  * and elements from  other [context].
  * The elements from this context with the same key 
  * as in the other one are dropped.
  */
public operator fun plus(context: CoroutineContext): CoroutineContext
```

```kotlin
/**
  * Returns a context containing elements from this context, 
  * but without an element with the specified [key].
  */
public fun minusKey(key: Key<*>): CoroutineContext
```

```kotlin
/**
 * Accumulates entries of this context starting with[initial] value
 * and applying[operation] from left to right to current accumulator value 
 * and each element of this context.
 */
public fun<R>fold(initial: R, operation:(R, Element)-> R): R
```

Out of the functions mentioned above, in most cases, you would only use the `plus` operator function, which uses the `fold` function under the hood.

If you have used coroutines before, the `plus` operator should be very familiar to you:

```kotlin
launch(Dispatchers.IO + CoroutineName("TestCoroutine")) {
    doStuff()
} 
```

Keep in mind that this `plus` is *not associative*. In other words, `context1` + `context2` is not the same as `context2` + `context1` since all the keys from the left context will be overwritten by the keys from the right context. Of course, It doesn't matter when combining two distinct `Element`s as in the example above, but when combining sets of `Element`s, this becomes an important consideration.

And yes, this example also means that every `Element` is also a `CoroutineContext` to allow for such a syntax:

```kotlin
/**
 * An element of the [CoroutineContext]. An element 
 * of the coroutine context is a singleton context by itself.
 */
public interface Element : CoroutineContext
```

Each `Element` by itself is a valid `CoroutineContext` that can be combined with other `Element`s and/or `CoroutineContext`s.

This also means that we can use the `get` syntax on any `Element`:

```kotlin
// nonsense, but api allows it
val job = Job()[Job]
```

That is not something that you would ever use in your code. Still, I find this example somewhat educational to illustrate the point above and the flexibility of coroutines API.

The rest of the `CoroutineContext`'s public API is realized with the help of extension functions and properties that access some functionality of an `Element`.

Here is an example of a property that checks whether or not a `CoroutineContext` is active:

```kotlin
public val CoroutineContext.isActive: Boolean
    get() = this[Job]?.isActive == true
```

We will not focus on these extensions for now, since in most cases, it would make sense to use similar functions on a `CoroutineScope`, but we will talk about it in Part 2 of this series.

## Best Practices and Recommendations

As you have seen, the `CoroutineContext` API is very flexible and allows us to add and combine different elements as we see fit.

However, *you should almost never do that*.

These flexible APIs are one of the reasons for the steep learning curve of the coroutines library. The thing is that *most of that flexibility is not meant for the end-user*. We will discuss why it is this way in one of the later parts of this series.

It is very easy to mess things up, especially when starting out using coroutines. So, to make things a bit easier, here are some recommendations on using the `CoroutineContext`.

First of all, the only elements you should ever consider manually adding to the context when launching a new coroutine are `CoroutineDispather` (or `MainCoroutineDispatcher`) and `CoroutineExceptionHandler`. In some specific debug cases, you can also use `CoroutineName`.

Here is an example of changing a dispatcher: 

```kotlin
fun main() {
    runBlocking {
        println("I am running on ${Thread.currentThread().name}")
        launch(Dispatchers.IO) {
            workOnIO() // this might be blocking
        }
    }
}

suspend fun workOnIO() {
    delay(100)
    println("Now I have switched to ${Thread.currentThread().name}")
}

Output:
I am running on main
Now I have switched to DefaultDispatcher-worker-1
```

> ***Important!*** `runBlocking` should never be used outside tests and examples like these. In production code, coroutines must have a proper scope. I am using it in this article for illustrational purposes only.
> 

One thing to keep in mind here is that `Dispatchers.IO` shares threads with `Dispatchers.Default`. Therefore we get this output.

Also notice that when we manage our dispatchers from the top-level coroutine, we might launch a suspending function that will block our thread. For example, if the `workOnIO` function instead of the non-blocking `delay()` called `Thread.sleep()`, or, more realistically, read from a huge file.

A coroutine will wait for a suspending function to finish regardless since *the execution of suspending functions is sequential*, but if we don't block the thread while waiting for a coroutine to resume, it is free to do other work.

With that in mind, there is one recommendation about dispatchers that [comes from Kotlin's project lead Roman Elizarov](https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761), who was the lead designer of coroutines library before that.

Here is an important excerpt:

> Suspending functions add a new dimension to code design. It was blocking/non-blocking without coroutines and now there is also suspending/non-suspending on top of that. To make everybody’s life simpler we use the following *convention*: **suspending functions do not block the caller thread**. The means to implement this convention are provided by the `withContext` function.
> 

With that convention in mind, here is how we could improve that code:

```kotlin
fun main() {
    runBlocking {
        launch {
            println("I am running on ${Thread.currentThread().name}")
            workOnIO()
        }
    }
}

suspend fun workOnIO() {
    withContext(Dispatchers.IO) {
        delay(100)
        println("Now I have switched to ${Thread.currentThread().name}")
    }
}

Output:
I am running on main
Now I have switched to DefaultDispatcher-worker-1
```
Function `workOnIO` might still block a thread, but not the thread we are calling it from. Also, by following this convention, you won't have to check every time what happens inside a suspending function and whether you need to switch threads for it.

When it comes to `CoroutineExceptionHandler`, we will talk about it in more detail when we get to exception handling in coroutines. For now, here is a simple example:

```kotlin
fun main() {
    val scope = CoroutineScope(Dispatchers.Default)
    val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
        println("I have caught: ${throwable.message}")
    }

    runBlocking {
        scope.launch(exceptionHandler) {
            println("I am running!")
            delay(100)
            error("A nasty exception!")
        }

        delay(200)
        println("I am OK!")
    }
}

Output:
I am running!
I have caught: A nasty exception!
I am OK!
```

Lastly, sometimes it might prove handy to identify your coroutines for debug purposes. You can do it using `CoroutineName` element:

```kotlin
fun main() {
    runBlocking {
        launch(CoroutineName("A")) {
            identify()
        }

        launch(CoroutineName("B")) {
            identify()
        }
    }
}

suspend fun identify() {
    val coroutineName = coroutineContext[CoroutineName]?.name
    println("I am called from: $coroutineName")
}

Output:
I am called from: A
I am called from: B
```

You can also use the `-Dkotlinx.coroutines.debug` JVM option to see the specified coroutine name in the logs.

You should rarely modify a `CoroutineContext` outside of these use cases unless you know what you are doing. Otherwise, it might break things you are not even aware of and result in hard-to-find bugs. Especially when introducing a new `Job` into the context - a topic we will discuss in a later article.

## Conclusion

If you stick to these recommendations, you won't have much trouble using the `CoroutineContext`. I could have just given you those and called it an article, but I believe it is crucial to understand the inner workings of the tools we use.

Next time, we will look into the `CoroutineScope`, which has more in common with the `CoroutineContext` than you might think.

See you next time,

*Your friend,*

*Max*
