Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 0 additions & 178 deletions chronos/internal/asyncfutures.nim
Original file line number Diff line number Diff line change
Expand Up @@ -696,46 +696,6 @@ proc asyncCheck*[T](future: Future[T]) {.
else:
cb(nil)

proc asyncDiscard*[T](future: Future[T]) {.
deprecated: "Use asyncSpawn or `discard await`".} = discard
## `asyncDiscard` will discard the outcome of the operation - unlike `discard`
## it also throws away exceptions! Use `asyncSpawn` if you're sure your
## code doesn't raise exceptions, or `discard await` to ignore successful
## outcomes

proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] {.
deprecated: "Use allFutures[T](varargs[Future[T]])".} =
## Returns a future which will complete once both ``fut1`` and ``fut2``
## finish.
##
## If cancelled, ``fut1`` and ``fut2`` futures WILL NOT BE cancelled.
var retFuture = newFuture[void]("chronos.`and`")
proc cb(data: pointer) =
if not(retFuture.finished()):
if fut1.finished() and fut2.finished():
if cast[pointer](fut1) == data:
if fut1.failed():
retFuture.fail(fut1.error)
else:
retFuture.complete()
else:
if fut2.failed():
retFuture.fail(fut2.error)
else:
retFuture.complete()
fut1.addCallback(cb)
fut2.addCallback(cb)

proc cancellation(udata: pointer) =
# On cancel we remove all our callbacks only.
if not(fut1.finished()):
fut1.removeCallback(cb)
if not(fut2.finished()):
fut2.removeCallback(cb)

retFuture.cancelCallback = cancellation
return retFuture

template orImpl*[T, Y](fut1: Future[T], fut2: Future[Y]): untyped =
var cb: proc(udata: pointer) {.gcsafe, raises: [].}
cb = proc(udata: pointer) {.gcsafe, raises: [].} =
Expand Down Expand Up @@ -793,144 +753,6 @@ proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
var retFuture = newFuture[void]("chronos.or()")
orImpl(fut1, fut2)


proc all*[T](futs: varargs[Future[T]]): auto {.
deprecated: "Use allFutures(varargs[Future[T]])".} =
## Returns a future which will complete once all futures in ``futs`` finish.
## If the argument is empty, the returned future completes immediately.
##
## If the awaited futures are not ``Future[void]``, the returned future
## will hold the values of all awaited futures in a sequence.
##
## If the awaited futures *are* ``Future[void]``, this proc returns
## ``Future[void]``.
##
## Note, that if one of the futures in ``futs`` will fail, result of ``all()``
## will also be failed with error from failed future.
##
## TODO: This procedure has bug on handling cancelled futures from ``futs``.
## So if future from ``futs`` list become cancelled, what must be returned?
## You can't cancel result ``retFuture`` because in such way infinite
## recursion will happen.
let totalFutures = len(futs)
var completedFutures = 0

# Because we can't capture varargs[T] in closures we need to create copy.
var nfuts = @futs

when T is void:
var retFuture = newFuture[void]("chronos.all(void)")
proc cb(udata: pointer) =
if not(retFuture.finished()):
inc(completedFutures)
if completedFutures == totalFutures:
for nfut in nfuts:
if nfut.failed():
retFuture.fail(nfut.error)
break
if not(retFuture.failed()):
retFuture.complete()

for fut in nfuts:
fut.addCallback(cb)

if len(nfuts) == 0:
retFuture.complete()

return retFuture
else:
var retFuture = newFuture[seq[T]]("chronos.all(T)")
var retValues = newSeq[T](totalFutures)

proc cb(udata: pointer) =
if not(retFuture.finished()):
inc(completedFutures)
if completedFutures == totalFutures:
for k, nfut in nfuts:
if nfut.failed():
retFuture.fail(nfut.error)
break
else:
retValues[k] = nfut.value
if not(retFuture.failed()):
retFuture.complete(retValues)

for fut in nfuts:
fut.addCallback(cb)

if len(nfuts) == 0:
retFuture.complete(retValues)

return retFuture

proc oneIndex*[T](futs: varargs[Future[T]]): Future[int] {.
deprecated: "Use one[T](varargs[Future[T]])".} =
## Returns a future which will complete once one of the futures in ``futs``
## complete.
##
## If the argument is empty, the returned future FAILS immediately.
##
## Returned future will hold index of completed/failed future in ``futs``
## argument.
var nfuts = @futs
var retFuture = newFuture[int]("chronos.oneIndex(T)")

proc cb(udata: pointer) =
var res = -1
if not(retFuture.finished()):
var rfut = cast[FutureBase](udata)
for i in 0..<len(nfuts):
if cast[FutureBase](nfuts[i]) != rfut:
nfuts[i].removeCallback(cb)
else:
res = i
retFuture.complete(res)

for fut in nfuts:
fut.addCallback(cb)

if len(nfuts) == 0:
retFuture.fail(newException(ValueError, "Empty Future[T] list"))

return retFuture

proc oneValue*[T](futs: varargs[Future[T]]): Future[T] {.
deprecated: "Use one[T](varargs[Future[T]])".} =
## Returns a future which will finish once one of the futures in ``futs``
## finish.
##
## If the argument is empty, returned future FAILS immediately.
##
## Returned future will hold value of completed ``futs`` future, or error
## if future was failed.
var nfuts = @futs
var retFuture = newFuture[T]("chronos.oneValue(T)")

proc cb(udata: pointer) =
var resFut: Future[T]
if not(retFuture.finished()):
var rfut = cast[FutureBase](udata)
for i in 0..<len(nfuts):
if cast[FutureBase](nfuts[i]) != rfut:
nfuts[i].removeCallback(cb)
else:
resFut = nfuts[i]
if resFut.failed():
retFuture.fail(resFut.error)
else:
when T is void:
retFuture.complete()
else:
retFuture.complete(resFut.read())

for fut in nfuts:
fut.addCallback(cb)

if len(nfuts) == 0:
retFuture.fail(newException(ValueError, "Empty Future[T] list"))

return retFuture

proc cancelSoon(future: FutureBase, aftercb: CallbackFunc, udata: pointer,
loc: ptr SrcLoc) {.raises: [].} =
## Perform cancellation ``future`` and call ``aftercb`` callback when
Expand Down