Asynchronous Programming With Coroutines
Asynchronous Programming With Coroutines
Version 1.9-rfc+0.1
Asynchronous programming
with coroutines
1
2CHAPTER 18. ASYNCHRONOUS PROGRAMMING WITH COROUTINES
18.2 Coroutines
A coroutine is a concept similar to a thread in traditional concurrent program-
ming, but based on cooperative multitasking, e.g., the switching between different
execution contexts is done by the coroutines themselves rather than the operating
system or a virtual machine.
In Kotlin, coroutines are used to implement suspending functions and can switch
contexts only at suspension points.
A call to a suspending function creates and starts a coroutine. As one can call a
suspending function only from another suspending function, we need a way to
bootstrap this process from a non-suspending context.
Note: this is required as most platforms are unaware of coroutines or
suspending functions, and do not provide a suspending entry point.
However, a Kotlin compiler may elect to provide a suspending entry
point on a specific platform.
One of the ways of starting suspending function from a non-suspending context
is via a coroutine builder: a non-suspending function which takes a suspending
18.3. IMPLEMENTATION DETAILS 3
function type argument (e.g., a suspending lambda literal) and handles the
coroutine lifecycle.
The implementation of coroutines is platform-dependent. Please refer to the
platform documentation for details.
18.3.1 kotlin.coroutines.Continuation<T>
Interface kotlin.coroutines.Continuation<T> is the main supertype of all
coroutines and represents the basis upon which the coroutine machinery is
implemented.
public interface Continuation<in T> {
public val context: CoroutineContext
public fun resumeWith(result: Result<T>)
}
Every suspending function is associated with a generated Continuation subtype,
which handles the suspension implementation; the function itself is adapted
to accept an additional continuation parameter to support the Continuation
Passing Style. The return type of the suspending function becomes the type
parameter T of the continuation.
CoroutineContext represents the context of the continuation and is an indexed
set from CoroutineContext.Key to CoroutineContext.Element (e.g., a special
kind of map). It is used to store coroutine-local information, and takes important
part in Continuation interception.
resumeWith function is used to propagate the results in between suspension
points: it is called with the result (or exception) of the last suspension point and
resumes the coroutine execution.
To avoid the need to explicitly create the Result<T> when calling resumeWith,
the coroutine implementation provides the following extension functions.
fun <T> Continuation<T>.resume(value: T)
fun <T> Continuation<T>.resumeWithException(exception: Throwable)
L0:
// result is expected to be `null` at this invocation
a = a()
label = 1
// 'this' is passed as a continuation
result = foo(a).await(this)
// return if await had suspended execution
if (result == COROUTINE_SUSPENDED)
return COROUTINE_SUSPENDED
L1:
// error handling
result.throwOnFailure()
// external code has resumed this coroutine
// passing the result of .await()
y = (Y) result
b()
label = 2
// 'this' is passed as a continuation
result = bar(a, y).await(this)
// return if await had suspended execution
if (result == COROUTINE_SUSPENDED)
return COROUTINE_SUSPENDED
L2:
// error handling
result.throwOnFailure()
// external code has resumed this coroutine
6CHAPTER 18. ASYNCHRONOUS PROGRAMMING WITH COROUTINES