docs: PLAN-RACE — make_variant + inline-if-return done; GAP 1 (tuple cursor index) is the last blocker
This commit is contained in:
@@ -81,13 +81,32 @@ Prereqs DONE (each committed + adversarially reviewed + suite-green):
|
||||
end-to-end** (proven by `examples/comptime/0649-comptime-typecall-composition.sx`: reflect a named
|
||||
tuple of `*Box(..)` handles → mint a tagged-union with the tuple's labels, projecting `*Box(A)`→`A`).
|
||||
|
||||
**All comptime prerequisites are now in place — the rest is pure-sx library work in sched.sx.**
|
||||
- **`return` inside `inline if` fixed** (`84c2ae4f`) — the natural early-return-per-arm pattern (a
|
||||
`return` in an `inline if`/comptime-`case` branch inside an `inline for`) no longer drops the
|
||||
function's trailing statements. Lets `race` build the winner variant with a clean
|
||||
`inline if i == { case 0: … else: … }` per-arm form.
|
||||
- **`make_variant($E, idx, payload)`** added to `modules/std/meta.sx` (`1c26944e`) — the WRITE side of
|
||||
the metatype triad: construct a minted tagged-union value by variant INDEX (the winner is chosen at
|
||||
runtime; its label can't be a literal). Pure sx (writes the i64 tag@0 + payload@8). Verified for
|
||||
complex payloads (struct / string / 40-byte struct). **This resolves the variant-construction gap.**
|
||||
|
||||
**NEXT (step 2–4): the actual `race` in `library/modules/std/sched.sx`.**
|
||||
**ONE remaining blocker for the runtime: GAP 1 — comptime-cursor indexing of a named-tuple VALUE.**
|
||||
`race(tasks: $T)` must read the i-th task `*Task(T_i)` with its concrete type where `i` is the
|
||||
`inline for` cursor. Today `tasks[i]` → *"cannot index a value of type '(…)'"* and
|
||||
`field_value(tasks, i)` returns a **void** Any (tuple field-VALUE reflection is unimplemented — the
|
||||
0195 family covered count/name/type but not value). Fix options: (a) make `tasks[i]` work with a
|
||||
comptime cursor on a named-tuple value (mirror packs' `xs[i]`), or (b) implement `field_value` for
|
||||
tuples + recover the concrete type via `field_type(T, i)`. (a) is cleaner for `race` (direct typed
|
||||
access). This is the last thing between here and the pure-sx runtime.
|
||||
|
||||
**THEN (pure-sx, unblocked once GAP 1 lands): the runtime in `sched.sx`.**
|
||||
- `RaceResult :: ($T) -> Type` over `*Task(..)` (the 0649 shape, with `Task` instead of `Box`).
|
||||
- `race :: ufcs (self: *Scheduler, tasks: $T) -> RaceResult(T)`: suspend the caller until the FIRST
|
||||
task is `.ready`; build the winner variant (construct the minted union by the winning index/label —
|
||||
watch for a possible variant-construction-by-dynamic-index gap); then `cancel` + `wait`-join every
|
||||
loser before returning (structured). Reuses `suspend_self`/`wake` + `Task.cancel`/`wait`.
|
||||
- Lock with a 2/3-task example (deterministic winner via `sleep` ordering, asserting losers cancelled).
|
||||
task is `.ready` (register caller as waiter on all pending; on wake DEREGISTER from all to avoid a
|
||||
double-wake of the merge — the queue-corruption hazard `wake` guards); winner = first ready;
|
||||
build it with `make_variant` in the matching `inline for` arm; then `cancel` + JOIN every loser
|
||||
(needs a `Task.finished` flag set at the end of the `go` body so the joiner distinguishes a
|
||||
finished worker from a merely-flagged-cancelled one, checked before parking like `wait` checks
|
||||
`.ready`). Reuses `suspend_self`/`wake`.
|
||||
- Lock with a 2/3-task example (deterministic winner via `sleep` ordering; assert losers cancelled).
|
||||
- Validate byte-identical on aarch64-macOS host AND aarch64-linux container; full `zig build test`.
|
||||
|
||||
Reference in New Issue
Block a user