Add asyncSpawn() procedure and tests. (#123)
Deprecated asyncDiscard() procedure. Bump version to 2.5.2.
This commit is contained in:
parent
e6d50b7736
commit
a5442edfc0
|
@ -1,5 +1,5 @@
|
|||
packageName = "chronos"
|
||||
version = "2.5.1"
|
||||
version = "2.5.2"
|
||||
author = "Status Research & Development GmbH"
|
||||
description = "Chronos"
|
||||
license = "Apache License 2.0 or MIT"
|
||||
|
|
|
@ -512,7 +512,48 @@ proc asyncCheck*[T](future: Future[T]) =
|
|||
raise future.error
|
||||
future.callback = cb
|
||||
|
||||
proc asyncDiscard*[T](future: Future[T]) = discard
|
||||
proc asyncSpawn*(future: Future[void]) =
|
||||
## Spawns a new concurrent async task.
|
||||
##
|
||||
## Tasks may not raise exceptions or be cancelled - a ``Defect`` will be
|
||||
## raised when this happens.
|
||||
##
|
||||
## This should be used instead of ``discard`` and ``asyncCheck`` when calling
|
||||
## an ``async`` procedure without ``await``, to ensure exceptions in the
|
||||
## returned future are not silently discarded.
|
||||
##
|
||||
## Note, that if passed ``future`` is already finished, it will be checked
|
||||
## and processed immediately.
|
||||
doAssert(not isNil(future), "Future is nil")
|
||||
|
||||
template getFutureLocation(): string =
|
||||
let loc = future.location[0]
|
||||
"[" & (
|
||||
if len(loc.procedure) == 0: "[unspecified]" else: $loc.procedure & "()"
|
||||
) & " at " & $loc.file & ":" & $(loc.line) & "]"
|
||||
|
||||
template getErrorMessage(): string =
|
||||
"Asynchronous task " & getFutureLocation() &
|
||||
" finished with an exception \"" & $future.error.name & "\"!"
|
||||
template getCancelMessage(): string =
|
||||
"Asynchronous task " & getFutureLocation() & " was cancelled!"
|
||||
|
||||
proc cb(data: pointer) =
|
||||
if future.failed():
|
||||
raise newException(FutureDefect, getErrorMessage())
|
||||
elif future.cancelled():
|
||||
raise newException(FutureDefect, getCancelMessage())
|
||||
|
||||
if not(future.finished()):
|
||||
# We adding completion callback only if ``future`` is not finished yet.
|
||||
future.addCallback(cb)
|
||||
else:
|
||||
if future.failed():
|
||||
raise newException(FutureDefect, getErrorMessage())
|
||||
elif future.cancelled():
|
||||
raise newException(FutureDefect, getCancelMessage())
|
||||
|
||||
proc asyncDiscard*[T](future: Future[T]) {.deprecated.} = discard
|
||||
## This is async workaround for discard ``Future[T]``.
|
||||
|
||||
proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] {.
|
||||
|
|
|
@ -969,6 +969,58 @@ suite "Future[T] behavior test suite":
|
|||
proc testCancellationRace(): bool =
|
||||
waitFor(testCancellationRaceAsync())
|
||||
|
||||
|
||||
proc testAsyncSpawnAsync(): Future[bool] {.async.} =
|
||||
|
||||
proc completeTask1() {.async.} =
|
||||
discard
|
||||
|
||||
proc completeTask2() {.async.} =
|
||||
await sleepAsync(100.milliseconds)
|
||||
|
||||
proc errorTask() {.async.} =
|
||||
if true:
|
||||
raise newException(ValueError, "")
|
||||
|
||||
proc cancelTask() {.async.} =
|
||||
await sleepAsync(10.seconds)
|
||||
|
||||
try:
|
||||
var fut1 = completeTask1()
|
||||
var fut2 = completeTask2()
|
||||
asyncSpawn fut1
|
||||
asyncSpawn fut2
|
||||
await sleepAsync(200.milliseconds)
|
||||
if not(fut1.finished()) or not(fut2.finished()):
|
||||
return false
|
||||
if fut1.failed() or fut1.cancelled() or fut2.failed() or fut2.cancelled():
|
||||
return false
|
||||
except:
|
||||
return false
|
||||
|
||||
try:
|
||||
asyncSpawn errorTask()
|
||||
return false
|
||||
except FutureDefect:
|
||||
discard
|
||||
except:
|
||||
return false
|
||||
|
||||
try:
|
||||
var fut = cancelTask()
|
||||
await cancelAndWait(fut)
|
||||
asyncSpawn fut
|
||||
return false
|
||||
except FutureDefect:
|
||||
discard
|
||||
except:
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
proc testAsyncSpawn(): bool =
|
||||
waitFor(testAsyncSpawnAsync())
|
||||
|
||||
test "Async undefined behavior (#7758) test":
|
||||
check test1() == true
|
||||
test "Immediately completed asynchronous procedure test":
|
||||
|
@ -1022,3 +1074,6 @@ suite "Future[T] behavior test suite":
|
|||
check testWithTimeout() == true
|
||||
test "Cancellation race test":
|
||||
check testCancellationRace() == true
|
||||
|
||||
test "asyncSpawn() test":
|
||||
check testAsyncSpawn() == true
|
||||
|
|
Loading…
Reference in New Issue