Reputation: 32309
Does it make sense to have an operation like getOrElseComplete
that tries to complete a Promise
with a value but, if the Promise
is already completed, returns the existing completed value instead. Here's a sample implementation:
implicit class PromiseOps[T](promise: Promise[T]) {
def getOrElseComplete(value: Try[T]): Try[T] = {
val didComplete = promise.tryComplete(value)
if (didComplete) {
value
} else {
// The `tryComplete` returned `false`, which means the promise
// was already completed, so the following is safe (?)
promise.future.value.get
}
}
}
Is this safe to do? If not, why not? If so, is there a way to do this directly (eg. without relying on questionable things like _.value.get
) or why isn't there such a way in the standard library?
Upvotes: 2
Views: 109
Reputation: 10764
From your comments it seems to me that this is a valid solution for your problem but I also feel that a method like this doesn't belong in Promise
API because Promise
is supposed to be only a settable "backend" of its Future
.
I'd prefer to have a completely separate function which could look like this:
def getOrComplete[T](promise: Promise[T], value: Try[T]): Try[T] =
promise.future.value.getOrElse {
if (promise.tryComplete(value)) value
else getOrComplete(promise, value)
}
The recursive call may seem weird - it serves two purposes:
tryComplete
.value.get
on the Future
You might also want to pass value
as a by-name parameter to avoid evaluating it when the Promise
is already completed.
Upvotes: 2
Reputation: 12102
This operation does what it promises. It may make more sense to take value
by name, and don't try to complete if already completed, maybe something like
def getOrElseComplete(value: => Try[T]): Try[T] = {
if (!promise.completed) {
promise.tryComplete(value)
}
promise.future.value.get
}
It's kinda dodgy though. Sharing a promise and having multiple places where it might be completed sounds like a difficult to maintain design, and one has to ask what's happening with the other path that might still complete the Promise? Shouldn't something be cancelled there?
Upvotes: 1