complete future only once in or (fixes #8982) (#9632)

* complete future only once in `or`

Analogous to `and`.
Credits to @k0zmo for proposing the solution.

* add test
This commit is contained in:
Miran
2018-11-09 23:45:17 +01:00
committed by Dominik Picheta
parent 8d850f7a69
commit 964b5dac7c
2 changed files with 36 additions and 2 deletions

View File

@@ -375,8 +375,9 @@ proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
## complete.
var retFuture = newFuture[void]("asyncdispatch.`or`")
proc cb[X](fut: Future[X]) =
if fut.failed: retFuture.fail(fut.error)
if not retFuture.finished: retFuture.complete()
if not retFuture.finished:
if fut.failed: retFuture.fail(fut.error)
else: retFuture.complete()
fut1.callback = cb[T]
fut2.callback = cb[Y]
return retFuture

33
tests/async/t8982.nim Normal file
View File

@@ -0,0 +1,33 @@
discard """
output: '''
timeout
runForever should throw ValueError, this is expected
'''
"""
import asyncdispatch
proc failingAwaitable(p: int) {.async.} =
await sleepAsync(500)
if p > 0:
raise newException(Exception, "my exception")
proc main() {.async.} =
let fut = failingAwaitable(1)
try:
await fut or sleepAsync(100)
if fut.finished:
echo "finished"
else:
echo "timeout"
except:
echo "failed"
# Previously this would raise "An attempt was made to complete a Future more than once."
try:
asyncCheck main()
runForever()
except ValueError:
echo "runForever should throw ValueError, this is expected"