Strict Future value / error access
Strict future access is now always enabled, making it a panic to access value/error when the Future is still pending - `read` and `readError` raise catchable exceptions instead which may be preferable to use. * remove `chronosStrictFutureAccess` enabling its functionality by default * disallow setting a cancellation callback on a non-pending future
This commit is contained in:
parent
1306170255
commit
e1c26a9cc9
|
@ -4,10 +4,6 @@
|
||||||
## in transition periods leading up to a breaking release that starts enforcing
|
## in transition periods leading up to a breaking release that starts enforcing
|
||||||
## them and removes the option.
|
## them and removes the option.
|
||||||
##
|
##
|
||||||
## `chronosPreviewV4` is a preview flag to enable v4 semantics - in particular,
|
|
||||||
## it enables strict exception checking and disables parts of the deprecated
|
|
||||||
## API and other changes being prepared for the upcoming release
|
|
||||||
##
|
|
||||||
## `chronosDebug` can be defined to enable several debugging helpers that come
|
## `chronosDebug` can be defined to enable several debugging helpers that come
|
||||||
## with a runtime cost - it is recommeneded to not enable these in production
|
## with a runtime cost - it is recommeneded to not enable these in production
|
||||||
## code.
|
## code.
|
||||||
|
@ -26,8 +22,6 @@ const
|
||||||
##
|
##
|
||||||
## `Exception` handling may be removed in future chronos versions.
|
## `Exception` handling may be removed in future chronos versions.
|
||||||
|
|
||||||
chronosStrictFutureAccess* {.booldefine.}: bool = defined(chronosPreviewV4)
|
|
||||||
|
|
||||||
chronosStackTrace* {.booldefine.}: bool = defined(chronosDebug)
|
chronosStackTrace* {.booldefine.}: bool = defined(chronosDebug)
|
||||||
## Include stack traces in futures for creation and completion points
|
## Include stack traces in futures for creation and completion points
|
||||||
|
|
||||||
|
|
|
@ -209,31 +209,27 @@ func value*[T: not void](future: Future[T]): lent T =
|
||||||
##
|
##
|
||||||
## See `read` for a version that raises a catchable error when future
|
## See `read` for a version that raises a catchable error when future
|
||||||
## has not completed.
|
## has not completed.
|
||||||
when chronosStrictFutureAccess:
|
if not future.completed():
|
||||||
if not future.completed():
|
raiseFutureDefect("Future not completed while accessing value", future)
|
||||||
raiseFutureDefect("Future not completed while accessing value", future)
|
|
||||||
|
|
||||||
future.internalValue
|
future.internalValue
|
||||||
|
|
||||||
func value*(future: Future[void]) =
|
func value*(future: Future[void]) =
|
||||||
## Return the value in a completed future - raises Defect when
|
## Raises Defect when `fut.completed()` is `false`.
|
||||||
## `fut.completed()` is `false`.
|
|
||||||
##
|
##
|
||||||
## See `read` for a version that raises a catchable error when future
|
## See `read` for a version that raises a catchable error when future
|
||||||
## has not completed.
|
## has not completed.
|
||||||
when chronosStrictFutureAccess:
|
if not future.completed():
|
||||||
if not future.completed():
|
raiseFutureDefect("Future not completed while accessing value", future)
|
||||||
raiseFutureDefect("Future not completed while accessing value", future)
|
|
||||||
|
|
||||||
func error*(future: FutureBase): ref CatchableError =
|
func error*(future: FutureBase): ref CatchableError =
|
||||||
## Return the error of `future`, or `nil` if future did not fail.
|
## Return the error of `future`, or `nil` if future did not fail.
|
||||||
##
|
##
|
||||||
## See `readError` for a version that raises a catchable error when the
|
## See `readError` for a version that raises a catchable error when the
|
||||||
## future has not failed.
|
## future has not failed.
|
||||||
when chronosStrictFutureAccess:
|
if not future.failed() and not future.cancelled():
|
||||||
if not future.failed() and not future.cancelled():
|
raiseFutureDefect(
|
||||||
raiseFutureDefect(
|
"Future not failed/cancelled while accessing error", future)
|
||||||
"Future not failed/cancelled while accessing error", future)
|
|
||||||
|
|
||||||
future.internalError
|
future.internalError
|
||||||
|
|
||||||
|
|
|
@ -283,10 +283,9 @@ proc tryCancel(future: FutureBase, loc: ptr SrcLoc): bool =
|
||||||
if not(isNil(future.internalChild)):
|
if not(isNil(future.internalChild)):
|
||||||
# If you hit this assertion, you should have used the `CancelledError`
|
# If you hit this assertion, you should have used the `CancelledError`
|
||||||
# mechanism and/or use a regular `addCallback`
|
# mechanism and/or use a regular `addCallback`
|
||||||
when chronosStrictFutureAccess:
|
doAssert future.internalCancelcb.isNil,
|
||||||
doAssert future.internalCancelcb.isNil,
|
"futures returned from `{.async.}` functions must not use " &
|
||||||
"futures returned from `{.async.}` functions must not use " &
|
"`cancelCallback`"
|
||||||
"`cancelCallback`"
|
|
||||||
tryCancel(future.internalChild, loc)
|
tryCancel(future.internalChild, loc)
|
||||||
else:
|
else:
|
||||||
if not(isNil(future.internalCancelcb)):
|
if not(isNil(future.internalCancelcb)):
|
||||||
|
@ -353,9 +352,9 @@ proc `cancelCallback=`*(future: FutureBase, cb: CallbackFunc) =
|
||||||
## This callback will be called immediately as ``future.cancel()`` invoked and
|
## This callback will be called immediately as ``future.cancel()`` invoked and
|
||||||
## must be set before future is finished.
|
## must be set before future is finished.
|
||||||
|
|
||||||
when chronosStrictFutureAccess:
|
doAssert not future.finished(),
|
||||||
doAssert not future.finished(),
|
"cancellation callback must be set before finishing the future"
|
||||||
"cancellation callback must be set before finishing the future"
|
|
||||||
future.internalCancelcb = cb
|
future.internalCancelcb = cb
|
||||||
|
|
||||||
{.push stackTrace: off.}
|
{.push stackTrace: off.}
|
||||||
|
|
Loading…
Reference in New Issue