Add asynchronous specific exception AsyncError.
Add AsyncTimeoutError. Add wait[T]() procedure and tests. Bump version to 2.0.2.
This commit is contained in:
parent
c9ab35dabc
commit
32bbbb051c
|
@ -1,5 +1,5 @@
|
|||
packageName = "asyncdispatch2"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
author = "Status Research & Development GmbH"
|
||||
description = "Asyncdispatch2"
|
||||
license = "Apache License 2.0 or MIT"
|
||||
|
|
|
@ -166,6 +166,11 @@ export asyncfutures2
|
|||
# TODO: Check if yielded future is nil and throw a more meaningful exception
|
||||
|
||||
type
|
||||
AsyncError* = object of Exception
|
||||
## Generic async exception
|
||||
AsyncTimeoutError* = object of AsyncError
|
||||
## Timeout exception
|
||||
|
||||
TimerCallback* = object
|
||||
finishAt*: uint64
|
||||
function*: AsyncCallback
|
||||
|
@ -639,6 +644,39 @@ proc withTimeout*[T](fut: Future[T], timeout: int): Future[bool] =
|
|||
fut.addCallback(continuation)
|
||||
return retFuture
|
||||
|
||||
proc wait*[T](fut: Future[T], timeout = -1): Future[T] =
|
||||
## Returns a future which will complete once future ``fut`` completes
|
||||
## or if timeout of ``timeout`` milliseconds has been expired.
|
||||
##
|
||||
## If ``timeout`` is ``-1``, then result future will be completed only
|
||||
## when ``fut`` become completed.
|
||||
var retFuture = newFuture[T]("asyncdispatch.wait")
|
||||
proc continuation(udata: pointer) {.gcsafe.} =
|
||||
if not retFuture.finished:
|
||||
if isNil(udata):
|
||||
fut.removeCallback(continuation)
|
||||
retFuture.fail(newException(AsyncTimeoutError, ""))
|
||||
else:
|
||||
if not retFuture.finished:
|
||||
if fut.failed:
|
||||
retFuture.fail(fut.error)
|
||||
else:
|
||||
retFuture.complete(fut.read())
|
||||
if timeout == -1:
|
||||
retFuture = fut
|
||||
elif timeout == 0:
|
||||
if fut.finished:
|
||||
if fut.failed:
|
||||
retFuture.fail(fut.error)
|
||||
else:
|
||||
retFuture.complete(fut.read())
|
||||
else:
|
||||
retFuture.fail(newException(AsyncTimeoutError, ""))
|
||||
else:
|
||||
addTimer(fastEpochTime() + uint64(timeout), continuation, nil)
|
||||
fut.addCallback(continuation)
|
||||
return retFuture
|
||||
|
||||
include asyncmacro2
|
||||
|
||||
proc callSoon(cbproc: CallbackFunc, data: pointer = nil) =
|
||||
|
|
|
@ -82,7 +82,7 @@ else:
|
|||
loopFuture*: Future[void] # Server's main Future
|
||||
|
||||
type
|
||||
TransportError* = object of Exception
|
||||
TransportError* = object of AsyncError
|
||||
## Transport's specific exception
|
||||
TransportOsError* = object of TransportError
|
||||
## Transport's OS specific exception
|
||||
|
|
|
@ -18,6 +18,67 @@ proc testFuture2(): Future[int] {.async.} =
|
|||
proc testFuture3(): Future[int] {.async.} =
|
||||
result = await testFuture2()
|
||||
|
||||
proc testFuture4(): Future[int] {.async.} =
|
||||
## Test for not immediately completed future and timeout = -1
|
||||
result = 0
|
||||
try:
|
||||
var res = await wait(testFuture1(), -1)
|
||||
result = 1
|
||||
except:
|
||||
result = 0
|
||||
|
||||
if result == 0:
|
||||
return
|
||||
|
||||
## Test for immediately completed future and timeout = -1
|
||||
result = 0
|
||||
try:
|
||||
var res = await wait(testFuture2(), -1)
|
||||
result = 1
|
||||
except:
|
||||
result = 0
|
||||
|
||||
if result == 0:
|
||||
return
|
||||
|
||||
## Test for not immediately completed future and timeout = 0
|
||||
result = 0
|
||||
try:
|
||||
var res = await wait(testFuture1(), 0)
|
||||
except AsyncTimeoutError:
|
||||
result = 1
|
||||
|
||||
if result == 0:
|
||||
return
|
||||
|
||||
## Test for immediately completed future and timeout = 0
|
||||
result = 0
|
||||
try:
|
||||
var res = await wait(testFuture2(), 0)
|
||||
result = 1
|
||||
except:
|
||||
result = 0
|
||||
|
||||
if result == 0:
|
||||
return
|
||||
|
||||
## Test for future which cannot be completed in timeout period
|
||||
result = 0
|
||||
try:
|
||||
var res = await wait(testFuture1(), 50)
|
||||
except AsyncTimeoutError:
|
||||
result = 1
|
||||
|
||||
if result == 0:
|
||||
return
|
||||
|
||||
## Test for future which will be completed before timeout exceeded.
|
||||
try:
|
||||
var res = await wait(testFuture1(), 150)
|
||||
result = 1
|
||||
except:
|
||||
result = 0
|
||||
|
||||
proc test1(): bool =
|
||||
var fut = testFuture1()
|
||||
poll()
|
||||
|
@ -70,6 +131,11 @@ proc test4(): string =
|
|||
if fut.finished:
|
||||
result = testResult
|
||||
|
||||
proc test5(): bool =
|
||||
var res = waitFor(testFuture4())
|
||||
if res == 1:
|
||||
result = true
|
||||
|
||||
when isMainModule:
|
||||
suite "Future[T] behavior test suite":
|
||||
test "Async undefined behavior (#7758) test":
|
||||
|
@ -80,3 +146,5 @@ when isMainModule:
|
|||
check test3() == "12345"
|
||||
test "Future[T] callbacks not changing order after removeCallback()":
|
||||
check test4() == "1245"
|
||||
test "wait[T]() test":
|
||||
check test5() == true
|
||||
|
|
Loading…
Reference in New Issue