mirror of
https://github.com/status-im/nim-chronos.git
synced 2025-03-04 04:40:54 +00:00
commit
df8d0da251
@ -1,5 +1,5 @@
|
|||||||
packageName = "chronos"
|
packageName = "chronos"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
author = "Status Research & Development GmbH"
|
author = "Status Research & Development GmbH"
|
||||||
description = "Chronos"
|
description = "Chronos"
|
||||||
license = "Apache License 2.0 or MIT"
|
license = "Apache License 2.0 or MIT"
|
||||||
@ -25,8 +25,8 @@ task test, "Run all tests":
|
|||||||
for cmd in @[
|
for cmd in @[
|
||||||
"nim c -r -d:useSysAssert -d:useGcAssert tests/" & tfile,
|
"nim c -r -d:useSysAssert -d:useGcAssert tests/" & tfile,
|
||||||
"nim c -r tests/" & tfile,
|
"nim c -r tests/" & tfile,
|
||||||
"nim c -r --gc:markAndSweep tests/" & tfile,
|
#"nim c -r --gc:markAndSweep tests/" & tfile,
|
||||||
"nim c -r -d:release tests/" & tfile,
|
"nim c -r -d:release tests/" & tfile
|
||||||
]:
|
]:
|
||||||
echo "\n" & cmd
|
echo "\n" & cmd
|
||||||
exec cmd
|
exec cmd
|
||||||
|
@ -46,10 +46,9 @@ type
|
|||||||
FutureError* = object of Exception
|
FutureError* = object of Exception
|
||||||
cause*: FutureBase
|
cause*: FutureBase
|
||||||
|
|
||||||
{.deprecated: [PFutureBase: FutureBase, PFuture: Future].}
|
|
||||||
|
|
||||||
when not defined(release):
|
when not defined(release):
|
||||||
var currentID = 0
|
var currentID* {.threadvar.}: int
|
||||||
|
currentID = 0
|
||||||
|
|
||||||
# ZAH: This seems unnecessary. Isn't it easy to introduce a seperate
|
# ZAH: This seems unnecessary. Isn't it easy to introduce a seperate
|
||||||
# module for the dispatcher type, so it can be directly referenced here?
|
# module for the dispatcher type, so it can be directly referenced here?
|
||||||
@ -145,7 +144,7 @@ proc complete*[T](future: Future[T], val: T) =
|
|||||||
## Completes ``future`` with value ``val``.
|
## Completes ``future`` with value ``val``.
|
||||||
#doAssert(not future.finished, "Future already finished, cannot finish twice.")
|
#doAssert(not future.finished, "Future already finished, cannot finish twice.")
|
||||||
checkFinished(future)
|
checkFinished(future)
|
||||||
doAssert(future.error == nil)
|
doAssert(isNil(future.error))
|
||||||
future.value = val
|
future.value = val
|
||||||
future.finished = true
|
future.finished = true
|
||||||
future.callbacks.call()
|
future.callbacks.call()
|
||||||
@ -154,7 +153,7 @@ proc complete*(future: Future[void]) =
|
|||||||
## Completes a void ``future``.
|
## Completes a void ``future``.
|
||||||
#doAssert(not future.finished, "Future already finished, cannot finish twice.")
|
#doAssert(not future.finished, "Future already finished, cannot finish twice.")
|
||||||
checkFinished(future)
|
checkFinished(future)
|
||||||
doAssert(future.error == nil)
|
doAssert(isNil(future.error))
|
||||||
future.finished = true
|
future.finished = true
|
||||||
future.callbacks.call()
|
future.callbacks.call()
|
||||||
|
|
||||||
@ -162,7 +161,7 @@ proc complete*[T](future: FutureVar[T]) =
|
|||||||
## Completes a ``FutureVar``.
|
## Completes a ``FutureVar``.
|
||||||
template fut: untyped = Future[T](future)
|
template fut: untyped = Future[T](future)
|
||||||
checkFinished(fut)
|
checkFinished(fut)
|
||||||
doAssert(fut.error == nil)
|
doAssert(isNil(fut.error))
|
||||||
fut.finished = true
|
fut.finished = true
|
||||||
fut.callbacks.call()
|
fut.callbacks.call()
|
||||||
|
|
||||||
@ -172,7 +171,7 @@ proc complete*[T](future: FutureVar[T], val: T) =
|
|||||||
## Any previously stored value will be overwritten.
|
## Any previously stored value will be overwritten.
|
||||||
template fut: untyped = Future[T](future)
|
template fut: untyped = Future[T](future)
|
||||||
checkFinished(fut)
|
checkFinished(fut)
|
||||||
doAssert(fut.error.isNil())
|
doAssert(isNil(fut.error))
|
||||||
fut.finished = true
|
fut.finished = true
|
||||||
fut.value = val
|
fut.value = val
|
||||||
fut.callbacks.call()
|
fut.callbacks.call()
|
||||||
@ -198,7 +197,7 @@ proc addCallback*(future: FutureBase, cb: CallbackFunc, udata: pointer = nil) =
|
|||||||
## Adds the callbacks proc to be called when the future completes.
|
## Adds the callbacks proc to be called when the future completes.
|
||||||
##
|
##
|
||||||
## If future has already completed then ``cb`` will be called immediately.
|
## If future has already completed then ``cb`` will be called immediately.
|
||||||
doAssert cb != nil
|
doAssert(not isNil(cb))
|
||||||
if future.finished:
|
if future.finished:
|
||||||
# ZAH: it seems that the Future needs to know its associated Dispatcher
|
# ZAH: it seems that the Future needs to know its associated Dispatcher
|
||||||
callSoon(cb, udata)
|
callSoon(cb, udata)
|
||||||
@ -214,7 +213,7 @@ proc addCallback*[T](future: Future[T], cb: CallbackFunc) =
|
|||||||
|
|
||||||
proc removeCallback*(future: FutureBase, cb: CallbackFunc,
|
proc removeCallback*(future: FutureBase, cb: CallbackFunc,
|
||||||
udata: pointer = nil) =
|
udata: pointer = nil) =
|
||||||
doAssert cb != nil
|
doAssert(not isNil(cb))
|
||||||
let acb = AsyncCallback(function: cb, udata: udata)
|
let acb = AsyncCallback(function: cb, udata: udata)
|
||||||
future.callbacks.remove acb
|
future.callbacks.remove acb
|
||||||
|
|
||||||
@ -258,7 +257,7 @@ proc `$`*(entries: seq[StackTraceEntry]): string =
|
|||||||
# Find longest filename & line number combo for alignment purposes.
|
# Find longest filename & line number combo for alignment purposes.
|
||||||
var longestLeft = 0
|
var longestLeft = 0
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
if entry.procName.isNil: continue
|
if isNil(entry.procName): continue
|
||||||
|
|
||||||
let left = $entry.filename & $entry.line
|
let left = $entry.filename & $entry.line
|
||||||
if left.len > longestLeft:
|
if left.len > longestLeft:
|
||||||
@ -267,7 +266,7 @@ proc `$`*(entries: seq[StackTraceEntry]): string =
|
|||||||
var indent = 2
|
var indent = 2
|
||||||
# Format the entries.
|
# Format the entries.
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
if entry.procName.isNil:
|
if isNil(entry.procName):
|
||||||
if entry.line == -10:
|
if entry.line == -10:
|
||||||
result.add(spaces(indent) & "#[\n")
|
result.add(spaces(indent) & "#[\n")
|
||||||
indent.inc(2)
|
indent.inc(2)
|
||||||
@ -320,7 +319,7 @@ proc read*[T](future: Future[T] | FutureVar[T]): T =
|
|||||||
let fut = Future[T](future)
|
let fut = Future[T](future)
|
||||||
{.pop.}
|
{.pop.}
|
||||||
if fut.finished:
|
if fut.finished:
|
||||||
if fut.error != nil:
|
if not isNil(fut.error):
|
||||||
injectStacktrace(fut)
|
injectStacktrace(fut)
|
||||||
raise fut.error
|
raise fut.error
|
||||||
when T isnot void:
|
when T isnot void:
|
||||||
@ -334,7 +333,7 @@ proc readError*[T](future: Future[T]): ref Exception =
|
|||||||
##
|
##
|
||||||
## An ``ValueError`` exception will be thrown if no exception exists
|
## An ``ValueError`` exception will be thrown if no exception exists
|
||||||
## in the specified Future.
|
## in the specified Future.
|
||||||
if future.error != nil: return future.error
|
if not isNil(future.error): return future.error
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "No error in future.")
|
raise newException(ValueError, "No error in future.")
|
||||||
|
|
||||||
@ -356,20 +355,23 @@ proc finished*(future: FutureBase | FutureVar): bool =
|
|||||||
|
|
||||||
proc failed*(future: FutureBase): bool =
|
proc failed*(future: FutureBase): bool =
|
||||||
## Determines whether ``future`` completed with an error.
|
## Determines whether ``future`` completed with an error.
|
||||||
return future.error != nil
|
return (not isNil(future.error))
|
||||||
|
|
||||||
proc asyncCheck*[T](future: Future[T]) =
|
proc asyncCheck*[T](future: Future[T]) =
|
||||||
## Sets a callback on ``future`` which raises an exception if the future
|
## Sets a callback on ``future`` which raises an exception if the future
|
||||||
## finished with an error.
|
## finished with an error.
|
||||||
##
|
##
|
||||||
## This should be used instead of ``discard`` to discard void futures.
|
## This should be used instead of ``discard`` to discard void futures.
|
||||||
doAssert(not future.isNil, "Future is nil")
|
doAssert(not isNil(future), "Future is nil")
|
||||||
proc cb(data: pointer) =
|
proc cb(data: pointer) =
|
||||||
if future.failed:
|
if future.failed:
|
||||||
injectStacktrace(future)
|
injectStacktrace(future)
|
||||||
raise future.error
|
raise future.error
|
||||||
future.callback = cb
|
future.callback = cb
|
||||||
|
|
||||||
|
proc asyncDiscard*[T](future: Future[T]) = discard
|
||||||
|
## This is async workaround for discard ``Future[T]``.
|
||||||
|
|
||||||
# ZAH: The return type here could be a Future[(T, Y)]
|
# ZAH: The return type here could be a Future[(T, Y)]
|
||||||
proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
||||||
## Returns a future which will complete once both ``fut1`` and ``fut2``
|
## Returns a future which will complete once both ``fut1`` and ``fut2``
|
||||||
@ -413,64 +415,60 @@ proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
|||||||
fut2.callback = cb
|
fut2.callback = cb
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
# ZAH: The return type here could be a tuple
|
|
||||||
# This will enable waiting a heterogenous collection of futures.
|
|
||||||
proc all*[T](futs: varargs[Future[T]]): auto =
|
proc all*[T](futs: varargs[Future[T]]): auto =
|
||||||
## Returns a future which will complete once
|
## Returns a future which will complete once all futures in ``futs`` complete.
|
||||||
## all futures in ``futs`` complete.
|
|
||||||
## If the argument is empty, the returned future completes immediately.
|
## If the argument is empty, the returned future completes immediately.
|
||||||
##
|
##
|
||||||
## If the awaited futures are not ``Future[void]``, the returned future
|
## If the awaited futures are not ``Future[void]``, the returned future
|
||||||
## will hold the values of all awaited futures in a sequence.
|
## will hold the values of all awaited futures in a sequence.
|
||||||
##
|
##
|
||||||
## If the awaited futures *are* ``Future[void]``,
|
## If the awaited futures *are* ``Future[void]``, this proc returns
|
||||||
## this proc returns ``Future[void]``.
|
## ``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.
|
||||||
|
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:
|
when T is void:
|
||||||
var
|
var retFuture = newFuture[void]("asyncdispatch.all(void)")
|
||||||
retFuture = newFuture[void]("asyncdispatch.all")
|
for fut in nfuts:
|
||||||
completedFutures = 0
|
|
||||||
|
|
||||||
let totalFutures = len(futs)
|
|
||||||
|
|
||||||
for fut in futs:
|
|
||||||
fut.addCallback proc (data: pointer) =
|
fut.addCallback proc (data: pointer) =
|
||||||
var fut = cast[FutureBase](data)
|
|
||||||
inc(completedFutures)
|
inc(completedFutures)
|
||||||
if not retFuture.finished:
|
if not retFuture.finished:
|
||||||
if fut.failed:
|
if completedFutures == totalFutures:
|
||||||
retFuture.fail(fut.error)
|
for nfut in nfuts:
|
||||||
else:
|
if nfut.failed:
|
||||||
if completedFutures == totalFutures:
|
retFuture.fail(nfut.error)
|
||||||
|
break
|
||||||
|
if not retFuture.failed:
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
|
|
||||||
if totalFutures == 0:
|
if len(nfuts) == 0:
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
|
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
else:
|
else:
|
||||||
var
|
var retFuture = newFuture[seq[T]]("asyncdispatch.all(T)")
|
||||||
retFuture = newFuture[seq[T]]("asyncdispatch.all")
|
var retValues = newSeq[T](totalFutures)
|
||||||
retValues = newSeq[T](len(futs))
|
for fut in nfuts:
|
||||||
completedFutures = 0
|
fut.addCallback proc (data: pointer) =
|
||||||
|
inc(completedFutures)
|
||||||
|
if not retFuture.finished:
|
||||||
|
if completedFutures == totalFutures:
|
||||||
|
for k, nfut in nfuts:
|
||||||
|
if nfut.failed:
|
||||||
|
retFuture.fail(nfut.error)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
retValues[k] = nfut.read()
|
||||||
|
if not retFuture.failed:
|
||||||
|
retFuture.complete(retValues)
|
||||||
|
|
||||||
for i, fut in futs:
|
if len(nfuts) == 0:
|
||||||
proc setCallback(i: int) =
|
|
||||||
fut.addCallback proc (data: pointer) =
|
|
||||||
var fut = cast[Future[T]](data)
|
|
||||||
inc(completedFutures)
|
|
||||||
if not retFuture.finished:
|
|
||||||
if fut.failed:
|
|
||||||
retFuture.fail(fut.error)
|
|
||||||
else:
|
|
||||||
retValues[i] = fut.read()
|
|
||||||
if completedFutures == len(retValues):
|
|
||||||
retFuture.complete(retValues)
|
|
||||||
|
|
||||||
setCallback(i)
|
|
||||||
|
|
||||||
if retValues.len == 0:
|
|
||||||
retFuture.complete(retValues)
|
retFuture.complete(retValues)
|
||||||
|
|
||||||
return retFuture
|
return retFuture
|
||||||
|
@ -134,6 +134,404 @@ proc test4(): string =
|
|||||||
proc test5(): int =
|
proc test5(): int =
|
||||||
result = waitFor(testFuture4())
|
result = waitFor(testFuture4())
|
||||||
|
|
||||||
|
proc testAllVarargs(): int =
|
||||||
|
var completedFutures = 0
|
||||||
|
|
||||||
|
proc vlient1() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient2() {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient3() {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient4() {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient5() {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient1f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient2f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient3f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient4f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient5f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client1(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client2(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client3(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client4(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client5(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client1f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client2f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client3f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client4f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client5f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
waitFor(all(vlient1(), vlient2(), vlient3(), vlient4(), vlient5()))
|
||||||
|
# 5 completed futures = 5
|
||||||
|
result += completedFutures
|
||||||
|
completedFutures = 0
|
||||||
|
try:
|
||||||
|
waitFor(all(vlient1(), vlient1f(),
|
||||||
|
vlient2(), vlient2f(),
|
||||||
|
vlient3(), vlient3f(),
|
||||||
|
vlient4(), vlient4f(),
|
||||||
|
vlient5(), vlient5f()))
|
||||||
|
result -= 10000
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
# 10 completed futures = 10
|
||||||
|
result += completedFutures
|
||||||
|
|
||||||
|
completedFutures = 0
|
||||||
|
var res = waitFor(all(client1(), client2(), client3(), client4(), client5()))
|
||||||
|
for item in res:
|
||||||
|
result += item
|
||||||
|
# 5 completed futures + 5 values = 10
|
||||||
|
result += completedFutures
|
||||||
|
|
||||||
|
completedFutures = 0
|
||||||
|
try:
|
||||||
|
var res = waitFor(all(client1(), client1f(),
|
||||||
|
client2(), client2f(),
|
||||||
|
client3(), client3f(),
|
||||||
|
client4(), client4f(),
|
||||||
|
client5(), client5f()))
|
||||||
|
result -= 10000
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
# 10 completed futures = 10
|
||||||
|
result += completedFutures
|
||||||
|
|
||||||
|
proc testAllSeq(): int =
|
||||||
|
var completedFutures = 0
|
||||||
|
var vfutures = newSeq[Future[void]]()
|
||||||
|
var nfutures = newSeq[Future[int]]()
|
||||||
|
|
||||||
|
proc vlient1() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient2() {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient3() {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient4() {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient5() {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc vlient1f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient2f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient3f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient4f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc vlient5f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client1(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client2(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client3(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client4(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client5(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
result = 1
|
||||||
|
|
||||||
|
proc client1f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client2f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client3f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client4f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client5f(): Future[int] {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
vfutures.setLen(0)
|
||||||
|
for i in 0..<10:
|
||||||
|
vfutures.add(vlient1())
|
||||||
|
vfutures.add(vlient2())
|
||||||
|
vfutures.add(vlient3())
|
||||||
|
vfutures.add(vlient4())
|
||||||
|
vfutures.add(vlient5())
|
||||||
|
|
||||||
|
waitFor(all(vfutures))
|
||||||
|
# 5 * 10 completed futures = 50
|
||||||
|
result += completedFutures
|
||||||
|
|
||||||
|
completedFutures = 0
|
||||||
|
vfutures.setLen(0)
|
||||||
|
for i in 0..<10:
|
||||||
|
vfutures.add(vlient1())
|
||||||
|
vfutures.add(vlient1f())
|
||||||
|
vfutures.add(vlient2())
|
||||||
|
vfutures.add(vlient2f())
|
||||||
|
vfutures.add(vlient3())
|
||||||
|
vfutures.add(vlient3f())
|
||||||
|
vfutures.add(vlient4())
|
||||||
|
vfutures.add(vlient4f())
|
||||||
|
vfutures.add(vlient5())
|
||||||
|
vfutures.add(vlient5f())
|
||||||
|
|
||||||
|
try:
|
||||||
|
waitFor(all(vfutures))
|
||||||
|
result -= 10000
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
# 10 * 10 completed futures = 100
|
||||||
|
result += completedFutures
|
||||||
|
|
||||||
|
completedFutures = 0
|
||||||
|
nfutures.setLen(0)
|
||||||
|
for i in 0..<10:
|
||||||
|
nfutures.add(client1())
|
||||||
|
nfutures.add(client2())
|
||||||
|
nfutures.add(client3())
|
||||||
|
nfutures.add(client4())
|
||||||
|
nfutures.add(client5())
|
||||||
|
|
||||||
|
var res = waitFor(all(nfutures))
|
||||||
|
for i in 0..<len(nfutures):
|
||||||
|
result += res[i]
|
||||||
|
# 5 * 10 completed futures + 5 * 10 results = 100
|
||||||
|
result += completedFutures
|
||||||
|
|
||||||
|
completedFutures = 0
|
||||||
|
nfutures.setLen(0)
|
||||||
|
for i in 0..<10:
|
||||||
|
nfutures.add(client1())
|
||||||
|
nfutures.add(client1f())
|
||||||
|
nfutures.add(client2())
|
||||||
|
nfutures.add(client2f())
|
||||||
|
nfutures.add(client3())
|
||||||
|
nfutures.add(client3f())
|
||||||
|
nfutures.add(client4())
|
||||||
|
nfutures.add(client4f())
|
||||||
|
nfutures.add(client5())
|
||||||
|
nfutures.add(client5f())
|
||||||
|
|
||||||
|
try:
|
||||||
|
var results = waitFor(all(nfutures))
|
||||||
|
result -= 10000
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
|
||||||
|
# 10 * 10 completed futures + 0 * 10 results = 100
|
||||||
|
result += completedFutures
|
||||||
|
|
||||||
|
proc testAsyncDiscard(): int =
|
||||||
|
var completedFutures = 0
|
||||||
|
|
||||||
|
proc client1() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc client2() {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc client3() {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc client4() {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc client5() {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
|
||||||
|
proc client1f() {.async.} =
|
||||||
|
await sleepAsync(100)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client2f() {.async.} =
|
||||||
|
await sleepAsync(200)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client3f() {.async.} =
|
||||||
|
await sleepAsync(300)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client4f() {.async.} =
|
||||||
|
await sleepAsync(400)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
proc client5f() {.async.} =
|
||||||
|
await sleepAsync(500)
|
||||||
|
inc(completedFutures)
|
||||||
|
if true:
|
||||||
|
raise newException(ValueError, "")
|
||||||
|
|
||||||
|
asyncDiscard client1()
|
||||||
|
asyncDiscard client1f()
|
||||||
|
asyncDiscard client2()
|
||||||
|
asyncDiscard client2f()
|
||||||
|
asyncDiscard client3()
|
||||||
|
asyncDiscard client3f()
|
||||||
|
asyncDiscard client4()
|
||||||
|
asyncDiscard client4f()
|
||||||
|
asyncDiscard client5()
|
||||||
|
asyncDiscard client5f()
|
||||||
|
|
||||||
|
waitFor(sleepAsync(2000))
|
||||||
|
result = completedFutures
|
||||||
|
|
||||||
|
proc testAllZero(): bool =
|
||||||
|
var tseq = newSeq[Future[int]]()
|
||||||
|
var fut = all(tseq)
|
||||||
|
result = fut.finished
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
suite "Future[T] behavior test suite":
|
suite "Future[T] behavior test suite":
|
||||||
test "Async undefined behavior (#7758) test":
|
test "Async undefined behavior (#7758) test":
|
||||||
@ -146,3 +544,11 @@ when isMainModule:
|
|||||||
check test4() == "1245"
|
check test4() == "1245"
|
||||||
test "wait[T]() test":
|
test "wait[T]() test":
|
||||||
check test5() == 6
|
check test5() == 6
|
||||||
|
test "all[T](varargs) test":
|
||||||
|
check testAllVarargs() == 35
|
||||||
|
test "all[T](seq) test":
|
||||||
|
check testAllSeq() == 350
|
||||||
|
test "all[T](zero) test":
|
||||||
|
check testAllZero() == true
|
||||||
|
test "asyncDiscard() test":
|
||||||
|
check testAsyncDiscard() == 10
|
||||||
|
@ -49,4 +49,4 @@ when isMainModule:
|
|||||||
check (res >= 100) and (res <= 1000)
|
check (res >= 100) and (res <= 1000)
|
||||||
test $TimersCount & " timers with 1000ms timeout":
|
test $TimersCount & " timers with 1000ms timeout":
|
||||||
var res = waitFor(test(1000))
|
var res = waitFor(test(1000))
|
||||||
check (res >= 1000) and (res <= 2000)
|
check (res >= 1000) and (res <= 5000)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user