You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A way to share (for example) a ListenableFuture among several consumers is to convert it to a Deferred and call await() on that.
There are a few things that bother me about this.
future.await() behaves differently from future.asDeferred().await(): one cancels the computation when await() is cancelled, the other one doesn't. It's inconsistent, and not in a way that's unavoidable when translating concepts across ecosystems: if Future.get gets interrupted, the whole computation doesn't get aborted, so this seems like kotlinx.coroutines invention.
Why do these two operations that behave significantly differently share the same name? The data structure that is used is orthogonal to whether it's single-shot. If the second kind of await() was called something different (for example, consume()), we could
For things that currently only support consuming, support the non-obvious step of first converting it to Deferred.
For things that currently only support awaiting, have what acts as a limited version of intersections of coroutine scopes. The latter is a wider issue than just cancelling an operation if one of two parents gets cancelled, but the idea of having a Deferred fail if either the only consumer fails or the component computing the value does seems like a notable special case.
val future = foo()
something() // can throw
future.await() // .consume()
If await() is never called, the computation leaks.
This leads to another problem that I think is worth considering: future.asDeferred() does not allow integrating into structured concurrency. If it did, then this problem would be avoided using this cleaner API:
val future = foo().asDeferred(currentCoroutineContext().job)
future.await()
The IDE inspection would then be limited to suggesting to pass something to asDeferred when it's called in a suspend context.
The text was updated successfully, but these errors were encountered:
In
kotlinx.coroutines
, we have two types of functions calledawait()
:await()
independently: this is the case for JS Promise, Deferred, the reactive integrations, andcom.google.android.gms.tasks.Task
by default.await()
is cancelled, the entity gets cancelled: this is the idea behind bidirectional cancellation in https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.future/await.html and https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-guava/kotlinx.coroutines.guava/await.html, andcom.google.android.gms.tasks.Task
if you pass a cancellation token.A way to share (for example) a
ListenableFuture
among several consumers is to convert it to aDeferred
and callawait()
on that.There are a few things that bother me about this.
future.await()
behaves differently fromfuture.asDeferred().await()
: one cancels the computation whenawait()
is cancelled, the other one doesn't. It's inconsistent, and not in a way that's unavoidable when translating concepts across ecosystems: ifFuture.get
gets interrupted, the whole computation doesn't get aborted, so this seems likekotlinx.coroutines
invention.await()
was called something different (for example,consume()
), we couldDeferred
.Deferred
fail if either the only consumer fails or the component computing the value does seems like a notable special case.https://youtrack.jetbrains.com/issue/KTIJ-17464/Warn-on-unstructured-no-CoroutineScope-protection-gap-between-getting-a-future-and-await-call-on-it also mentions that for the consuming
await()
, this pattern is incorrect:If
await()
is never called, the computation leaks.This leads to another problem that I think is worth considering:
future.asDeferred()
does not allow integrating into structured concurrency. If it did, then this problem would be avoided using this cleaner API:The IDE inspection would then be limited to suggesting to pass something to
asDeferred
when it's called in asuspend
context.The text was updated successfully, but these errors were encountered: