futures: lentify (#413)

sometimes avoid copies when reading from `Future`
This commit is contained in:
Jacek Sieka 2023-08-09 16:27:17 +02:00 committed by GitHub
parent 6c2ea67512
commit a7f708bea8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 10 deletions

View File

@ -451,19 +451,25 @@ proc internalCheckComplete*(fut: FutureBase) {.raises: [CatchableError].} =
injectStacktrace(fut.internalError)
raise fut.internalError
proc internalRead*[T](fut: Future[T]): T {.inline.} =
# For internal use only. Used in asyncmacro
when T isnot void:
return fut.internalValue
proc read*[T: not void](future: Future[T] ): lent T {.raises: [CatchableError].} =
## Retrieves the value of ``future``. Future must be finished otherwise
## this function will fail with a ``ValueError`` exception.
##
## If the result of the future is an error then that error will be raised.
if not future.finished():
# TODO: Make a custom exception type for this?
raise newException(ValueError, "Future still in progress.")
proc read*[T](future: Future[T] ): T {.raises: [CatchableError].} =
internalCheckComplete(future)
future.internalValue
proc read*(future: Future[void] ) {.raises: [CatchableError].} =
## Retrieves the value of ``future``. Future must be finished otherwise
## this function will fail with a ``ValueError`` exception.
##
## If the result of the future is an error then that error will be raised.
if future.finished():
internalCheckComplete(future)
internalRead(future)
else:
# TODO: Make a custom exception type for this?
raise newException(ValueError, "Future still in progress.")

View File

@ -309,7 +309,7 @@ template await*[T](f: Future[T]): untyped =
# `child` released by `futureContinue`
chronosInternalRetFuture.internalChild.internalCheckComplete()
when T isnot void:
cast[type(f)](chronosInternalRetFuture.internalChild).internalRead()
cast[type(f)](chronosInternalRetFuture.internalChild).value()
else:
unsupported "await is only available within {.async.}"

View File

@ -184,7 +184,7 @@ func completed*(future: FutureBase): bool {.inline.} =
func location*(future: FutureBase): array[LocationKind, ptr SrcLoc] =
future.internalLocation
func value*[T](future: Future[T]): T =
func value*[T: not void](future: Future[T]): lent T =
## Return the value in a completed future - raises Defect when
## `fut.completed()` is `false`.
##
@ -196,8 +196,19 @@ func value*[T](future: Future[T]): T =
msg: "Future not completed while accessing value",
cause: future)
when T isnot void:
future.internalValue
future.internalValue
func value*(future: Future[void]) =
## Return the value in a completed future - raises Defect when
## `fut.completed()` is `false`.
##
## See `read` for a version that raises an catchable error when future
## has not completed.
when chronosStrictFutureAccess:
if not future.completed():
raise (ref FutureDefect)(
msg: "Future not completed while accessing value",
cause: future)
func error*(future: FutureBase): ref CatchableError =
## Return the error of `future`, or `nil` if future did not fail.

View File

@ -1237,12 +1237,14 @@ suite "Future[T] behavior test suite":
fut2.complete() # LINE POSITION 4
fut3.complete() # LINE POSITION 6
{.push warning[Deprecated]: off.} # testing backwards compatibility interface
let loc10 = fut1.location[0]
let loc11 = fut1.location[1]
let loc20 = fut2.location[0]
let loc21 = fut2.location[1]
let loc30 = fut3.location[0]
let loc31 = fut3.location[1]
{.pop.}
proc chk(loc: ptr SrcLoc, file: string, line: int,
procedure: string): bool =