diff --git a/chronos/asyncfutures2.nim b/chronos/asyncfutures2.nim index d170f08..d3954ba 100644 --- a/chronos/asyncfutures2.nim +++ b/chronos/asyncfutures2.nim @@ -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.") diff --git a/chronos/asyncmacro2.nim b/chronos/asyncmacro2.nim index 45146a3..8e74073 100644 --- a/chronos/asyncmacro2.nim +++ b/chronos/asyncmacro2.nim @@ -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.}" diff --git a/chronos/futures.nim b/chronos/futures.nim index edfae32..9b2667b 100644 --- a/chronos/futures.nim +++ b/chronos/futures.nim @@ -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. diff --git a/tests/testfut.nim b/tests/testfut.nim index af92354..a9fba05 100644 --- a/tests/testfut.nim +++ b/tests/testfut.nim @@ -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 =