Skip to content

DefaultDispatcher #136

Closed
Closed
@elizarov

Description

@elizarov

This is write-up on why kotlinx.coroutines needs a DefaultDispatcher and what it is.

The plan is to have a default value of context parameter for all coroutine builders that are defined in kotlinx.coroutines, so that instead of launch(someContext) { ... } we can just write launch { ... } unless we really care what context our coroutine runs in. Moreover, sometimes we only care about non-dispatch aspects of our coroutines and write launch(CoroutineName("foo")) { ... } which does not really work as of now (see #133). We need some clearly defined default dispatcher that would be used in this case.

This is especially important in light of our effort to bring kotlinx.coroutines into Kotlin/JS and Kotlin/Native code in such a way as writing common code with coroutines becomes possible. In common code we cannot write launch (CommonPool) { ... } since the CommonPool is defined only in Kotlin/JVM and is meaningless on other platforms due to different threading model. However, each platform can provide its own sensible default dispatcher.

We are going to define a top-level val in kotlinx.coroutines.experimental package:

val DefaultDispatcher: CoroutineDispatcher = ...

There are a few questions to be answered here :

  1. The type. We can use both CoroutineContext and CoroutineDispatcher as types of that variable. The latter is preferable, since it would clearly highlight that it provides default dispatching logic and would prevent some obvious mistakes like DefaultDispatcher + UI (it will get flagged as an error during compilation, because adding two dispatchers does not make sense, as the later overwrites the former).

  2. The name. DefaultDispatcher looks good, since it clearly explains the purpose and fits the type. TheCaptilazationOfTheName is choosen for consistency with other dispatcher names like UI and CommonPool, which are singletons. DefaultDispatcher is also a singleton, so it is named as such. Of course, there is some bike-shedding to be held on how it all shall be named (see also CoroutineDispatcher's names #41), but we'll skip that bike-shedding for now, since the name of DefaultDispatcher is not going to actually appear in the source of end-user applications.

  3. The value. For Kotlin/JVM we'll start with CommonPool as the value of DefaultDispatcher. It is absolutely non-ideal value, since CommonPool is ill suited for the tasks that do not have recursive fork-join structure and most typical coroutine benchmarks run approximately 2 times faster in a single-threaded dispatcher than in CommonPool. Moreover, with CommonPool we cannot efficiently support blocking operations without having to switch to a different thread (see IO thread pool for blocking calls #79). Ultimately, a totally new, engineered from group-up implementation will be needed, but we'll leave this implementation for later.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions