create raceCancell

This commit is contained in:
Diego 2024-08-11 23:21:46 +02:00
parent cde5ed7e8c
commit c3114d2ed2
No known key found for this signature in database
GPG Key ID: C9DAC9BF68D1F806
2 changed files with 62 additions and 0 deletions

View File

@ -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))

View File

@ -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()])