create raceCancell
This commit is contained in:
parent
cde5ed7e8c
commit
c3114d2ed2
|
@ -9,6 +9,7 @@
|
|||
|
||||
{.push raises: [].}
|
||||
|
||||
import sequtils
|
||||
import chronos
|
||||
|
||||
type AllFuturesFailedError* = object of CatchableError
|
||||
|
@ -31,3 +32,11 @@ proc anyCompleted*[T](futs: seq[Future[T]]): Future[Future[T]] {.async.} =
|
|||
|
||||
let index = requests.find(raceFut)
|
||||
requests.del(index)
|
||||
|
||||
proc raceCancel*[T](
|
||||
futs: seq[Future[T]]
|
||||
): Future[void] {.async: (raises: [ValueError, CancelledError]).} =
|
||||
try:
|
||||
discard await race(futs)
|
||||
finally:
|
||||
await noCancel allFutures(futs.filterIt(not it.finished).mapIt(it.cancelAndWait))
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
{.used.}
|
||||
|
||||
# Nim-Libp2p
|
||||
# Copyright (c) 2023 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
# at your option.
|
||||
# This file may not be copied, modified, or distributed except according to
|
||||
# those terms.
|
||||
|
||||
import ../helpers
|
||||
import ../../libp2p/utils/future
|
||||
|
||||
suite "Utils Future":
|
||||
|
||||
asyncTest "All Pending Tasks are canceled when returned future is canceled":
|
||||
proc longRunningTaskA() {.async.} =
|
||||
await sleepAsync(10.seconds)
|
||||
|
||||
proc longRunningTaskB() {.async.} =
|
||||
await sleepAsync(10.seconds)
|
||||
|
||||
let
|
||||
futureA = longRunningTaskA()
|
||||
futureB = longRunningTaskB()
|
||||
|
||||
# Both futures should be canceled when raceCancel is called
|
||||
await raceCancel(@[futureA, futureB]).cancelAndWait()
|
||||
check futureA.cancelled
|
||||
check futureB.cancelled
|
||||
|
||||
# Test where one task finishes immediately, leading to the cancellation of the pending task
|
||||
asyncTest "Cancel Pending Tasks When One Completes":
|
||||
proc quickTask() {.async.} =
|
||||
return
|
||||
|
||||
proc slowTask() {.async.} =
|
||||
await sleepAsync(10.seconds)
|
||||
|
||||
let
|
||||
futureQuick = quickTask()
|
||||
futureSlow = slowTask()
|
||||
|
||||
# The quick task finishes, so the slow task should be canceled
|
||||
await raceCancel(@[futureQuick, futureSlow])
|
||||
check futureQuick.finished
|
||||
check futureSlow.cancelled
|
||||
|
||||
asyncTest "raceCancel with AsyncEvent":
|
||||
let asyncEvent = newAsyncEvent()
|
||||
|
||||
await raceCancel(@[asyncEvent.wait()])
|
Loading…
Reference in New Issue