Example - Async-Await
The nice thing about coroutines is that they allow expressing logically connected statements as uninterrupted code, even though control flow could be arbitrary. As such, one of their use-cases is implementing the Async/Await abstraction, normally available as a Scala macro library.
The basic idea is the following – there are two coroutine declarations.
One is called async
, and the other one is called await
.
The await
coroutine uses a helper object of type Cell[T]
,
which is used to obtain the value of the awaited future.
When await
is directly invoked,
it yields a tuple of a cell object and the future object.
After getting resumes,
await
returns the value x
from the Cell
object.
This is a design pattern worth remembering,
since it allows the owner of the coroutine instance
to pass some value back into the coroutine.
The async
coroutine is slightly more complicated.
It creates a promise p
, then returns its future.
Concurrently, in a future computation,
it executes the following loop:
it resumes the coroutine,
and completes the promise p
with the result
if the coroutine completed.
Otherwise, if the execution reached await
,
it uses the yielded future/cell pair to install a callback,
and repeats the loop after the future yielded by await
gets completed.
Effectively, this separates the computation segments
in the coroutine into a chain of asynchronous computations.
Note that, for the sake of simplicity, the example does not do any exception handling, but that is a straightforward extension. The code is shown below.