diff options
-rw-r--r-- | lib/pure/asyncdispatch.nim | 55 | ||||
-rw-r--r-- | tests/async/tasyncall.nim | 50 |
2 files changed, 89 insertions, 16 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 2c7aaf2bf..7d765ce75 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -355,27 +355,50 @@ proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] = fut2.callback = cb return retFuture -proc all*[A](futs: seq[Future[A]]): Future[seq[A]] = - ## Returns a future which will complete once all futures in ``futs`` - ## complete. +proc all*[T](futs: varargs[Future[T]]): auto = + ## Returns a future which will complete once + ## all futures in ``futs`` complete. + ## + ## If the awaited futures are not ``Future[void]``, the returned future + ## will hold the values of all awaited futures in a sequence. ## - ## The resulting future will hold the values of all awaited futures, - ## in the order they are passed. + ## If the awaited futures *are* ``Future[void]``, + ## this proc returns ``Future[void]``. - var - retFuture = newFuture[seq[A]]("asyncdispatch.all") - retValues = newSeq[A](len(futs)) - completedFutures = 0 + when T is void: + var + retFuture = newFuture[void]("asyncdispatch.all") + completedFutures = 0 - for i, fut in futs: - fut.callback = proc(f: Future[A]) = - retValues[i] = f.read() - inc(completedFutures) + let totalFutures = len(futs) - if completedFutures == len(futs): - retFuture.complete(retValues) + for fut in futs: + fut.callback = proc(f: Future[T]) = + inc(completedFutures) - return retFuture + if completedFutures == totalFutures: + retFuture.complete() + + return retFuture + + else: + var + retFuture = newFuture[seq[T]]("asyncdispatch.all") + retValues = newSeq[T](len(futs)) + completedFutures = 0 + + for i, fut in futs: + proc setCallback(i: int) = + fut.callback = proc(f: Future[T]) = + retValues[i] = f.read() + inc(completedFutures) + + if completedFutures == len(retValues): + retFuture.complete(retValues) + + setCallback(i) + + return retFuture type PDispatcherBase = ref object of RootRef diff --git a/tests/async/tasyncall.nim b/tests/async/tasyncall.nim new file mode 100644 index 000000000..971122ad9 --- /dev/null +++ b/tests/async/tasyncall.nim @@ -0,0 +1,50 @@ +discard """ + file: "tasyncall.nim" + exitcode: 0 +""" +import times, sequtils +import asyncdispatch + +const + taskCount = 10 + sleepDuration = 500 + +proc futureWithValue(x: int): Future[int] {.async.} = + await sleepAsync(sleepDuration) + return x + +proc futureWithoutValue() {.async.} = + await sleepAsync(1000) + +proc testFuturesWithValue(x: int): seq[int] = + var tasks = newSeq[Future[int]](taskCount) + + for i in 0..<taskCount: + tasks[i] = futureWithValue(x) + + result = waitFor all(tasks) + +proc testFuturesWithoutValues() = + var tasks = newSeq[Future[void]](taskCount) + + for i in 0..<taskCount: + tasks[i] = futureWithoutValue() + + waitFor all(tasks) + +block: + let + startTime = cpuTime() + results = testFuturesWithValue(42) + expected = repeat(42, taskCount) + execTime = cpuTime() - startTime + + doAssert execTime * 1000 < taskCount * sleepDuration + doAssert results == expected + +block: + let startTime = cpuTime() + testFuturesWithoutValues() + let execTime = cpuTime() - startTime + + doAssert execTime * 1000 < taskCount * sleepDuration |