Add allFinished() primitive. (#87)

* Add allCompleted() primitive.

* Rename it to allFinished().

* Fix allFinished Future's static name.
Use `mitems()` instead of `for`.
This commit is contained in:
Eugene Kabanov 2020-04-01 12:10:56 +03:00 committed by GitHub
parent 72b4f14427
commit cbd8e03823
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 37 additions and 0 deletions

View File

@ -701,6 +701,43 @@ proc allFutures*[T](futs: varargs[Future[T]]): Future[void] =
return retFuture
proc allFinished*[T](futs: varargs[Future[T]]): Future[seq[Future[T]]] =
## Returns a future which will complete only when all futures in ``futs``
## will be completed, failed or canceled.
##
## Returned sequence will hold all the Future[T] objects passed to
## ``allCompleted`` with the order preserved.
##
## If the argument is empty, the returned future COMPLETES immediately.
##
## On cancel all the awaited futures ``futs`` WILL NOT BE cancelled.
var retFuture = newFuture[seq[Future[T]]]("chronos.allFinished()")
let totalFutures = len(futs)
var completedFutures = 0
var nfuts = @futs
proc cb(udata: pointer) {.gcsafe.} =
if not(retFuture.finished()):
inc(completedFutures)
if completedFutures == totalFutures:
retFuture.complete(nfuts)
proc cancellation(udata: pointer) {.gcsafe.} =
# On cancel we remove all our callbacks only.
for fut in nfuts.mitems():
if not(fut.finished()):
fut.removeCallback(cb)
for fut in nfuts:
fut.addCallback(cb)
retFuture.cancelCallback = cancellation
if len(nfuts) == 0:
retFuture.complete(nfuts)
return retFuture
proc one*[T](futs: varargs[Future[T]]): Future[Future[T]] =
## Returns a future which will complete and return completed Future[T] inside,
## when one of the futures in ``futs`` will be completed, failed or canceled.