Reentrancy causes event reordering and stack explosions, in addition to
leading to hard-to-debug scenarios.
Since none of chronos is actually tested under reentrant conditions (ie
that all features such as exceptions, cancellations, buffer operations,
timers etc work reliably when the loop is reentered), this is hard to
support over time and prevents useful optimizations - this PR simply
detects and disallows the behaviour to remove the uncertainty,
simplifying reasoning about the event loop in general.
Dedicated exceptions for `read` failures reduce the risk of mixing up
"user" exceptions with those of Future itself. The risk still exists, if
the user allows a chronos exception to bubble up explicitly.
Because `await` structurally guarantees that the Future is not `pending`
at the time of `read`, it does not raise this new exception.
* introduce `FuturePendingError` and `FutureCompletedError` when
`read`:ing a future of uncertain state
* fix `waitFor` / `read` to return `lent` values
* simplify code generation for `void`-returning async procs
* document `Raising` type helper
With these fixes, `transports`/`asyncsync` correctly propagate and document their raises information - generally, most transport functions (send etc) raise `TransportError` and `CancelledError` - `closeWait` is special in that it generally doesn't fail.
This PR introduces the syntax `Future[void].Raises([types])` to create the `InternalRaisesFuture` type with the correct encoding for the types - this allows it to be used in user code while retaining the possibility to change the internal representation down the line.
* introduce raising constraints on stream callbacks - these constraints now give a warning when called with a callback that can raise exceptions (raising callbacks would crash
* fix fail and its tests, which wasn't always given a good generic match
* work around nim bugs related to macro expansion of generic types
* make sure transports raise only `TransportError`-derived exceptions (and `CancelledError`)
* introduce user guide based on `mdbook`
* set up structure for adding simple `chronos` usage examples
* move most readme content to book
* ci deploys book and api guide automatically
* remove most of existing engine docs (obsolete)
* Fix waitFor() should not exit earlier last callback will be scheduled.
* Tune tests to use less memory.
* Fix `testutils`. There is no more last poll() needed.
* Update chronos/internal/asyncfutures.nim
---------
Co-authored-by: Jacek Sieka <jacek@status.im>
This PR replaces the global strict exception mode with an option to
handle `Exception` per function while at the same time enabling strict
exception checking globally by default as has been planned for v4.
`handleException` mode raises `AsyncExceptionError` to distinguish it
from `ValueError` which may originate from user code.
* remove obsolete 1.2 config options
Per discussion in
https://github.com/status-im/nim-chronos/pull/251#issuecomment-1559233139,
`async: (parameters..)` is introduced as a way to customize the async
transformation instead of relying on separate keywords (like
asyncraises).
Two parameters are available as of now:
`raises`: controls the exception effect tracking
`raw`: disables body transformation
Parameters are added to `async` as a tuple allowing more params to be
added easily in the future:
```nim:
proc f() {.async: (name: value, ...).}`
```
* introduce `asyncraises` to core future utilities
Similar to the introduction of `raises` into a codebase, `asyncraises`
needs to be introduced gradually across all functionality before
deriving benefit.
This is a first introduction along with utilities to manage raises lists
and transform them at compile time.
Several scenarios ensue:
* for trivial cases, adding `asyncraises` is enough and the framework
deduces the rest
* some functions "add" new asyncraises (similar to what `raise` does in
"normal" code) - for example `wait` may raise all exceptions of the
future passed to it and additionally a few of its own - this requires
extending the raises list
* som functions "remove" raises (similar to what `try/except` does) such
as `nocancel` with blocks cancellations and therefore reduce the raising
set
Both of the above cases are currently handled by a macro, but depending
on the situation lead to code organisation issues around return types
and pragma limitations - in particular, to keep `asyncraises`
backwards-compatibility, some code needs to exist in two versions which
somewhat complicates the implementation.
* add `asyncraises` versions for several `asyncfutures` utilities
* when assigning exceptions to a `Future` via `fail`, check at compile
time if possible and at runtime if not that the exception matches
constraints
* fix `waitFor` comments
* move async raises to separate module, implement `or`
* Introduce chronos/internals, move some code
This PR breaks the include dependencies between `asyncfutures2` and
`asyncmacros2` by moving the dispatcher and some other code to a new
module.
This step makes it easier to implement `asyncraises` support for future
utilities like `allFutures` etc avoiding the need to play tricks with
include order etc.
Future PR:s may further articulate the difference between "internal"
stuff subject to API breakage and regular public API intended for end
users (rather than advanced integrators).
* names
* windows fix