Skip to content

3.1.0

@adam-zethraeus adam-zethraeus tagged this 06 Oct 21:03
Add three primitives that serve the tree-ownership contract directly, plus
an advisory query:

- Scope.withChild(name:_:) and Scope.withRoot(name:_:) bind a scope to a
  block. The scope is cancelled and drained before the call returns or
  rethrows, caller-task cancellation propagates into the block's subtree,
  and withRoot rethrows only the block's own error type.
- Scope.finish() closes a subtree without cancelling and awaits running
  work; Scope.close() is the synchronous form that is safe inside the
  subtree. A later cancel(), requestCancellation(), or dropped scope
  escalates a finishing subtree, and all waiting callers join the same
  completion.
- CompletingLifetimeHandle adds borrowing func wait() async. A scope
  releases a completing handle as soon as it finishes instead of retaining
  it until cancellation, and finish() awaits it rather than cancelling it.
  Plain handles remain retained until cancellation and are cancelled by
  finish() because their completion cannot be observed.
- Scope.isClosed reports whether a subtree is finishing or cancelling.

Internally each tree node is open, finishing, or cancelling. A finishing
node keeps its leaf registrations so escalation can reach them; the
original driver still resolves the single completion. Registrations run
cancel() at most once via Once, while wait() is never memoized so every
waiting caller records its ancestry for self-await detection, which now
also covers finish() and completing-handle callbacks.

Validated with swift test in debug and release on macOS (Swift 6.4) and
Linux (Swift 6.2.4), eight repeated debug runs, swift format lint, and
the compile fixtures in Scripts/check-api.py including new fixtures for
completing handles and non-throwing structured blocks.
Assets 2
Loading