Add asynchronous specific exception AsyncError.

Add AsyncTimeoutError.
Add wait[T]() procedure and tests.
Bump version to 2.0.2.
This commit is contained in:
cheatfate 2018-07-20 11:58:01 +03:00
parent c9ab35dabc
commit 32bbbb051c
4 changed files with 108 additions and 2 deletions

View File

@ -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"

View File

@ -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) =

View File

@ -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

View File

@ -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