feat: race over Futures via context.io.race (PLAN-IO-UNIFY Phase 4)
Re-home the proven first-wins race from sched.race(*Task) onto *Future handles
+ the Io protocol; the old Task-based race is REPLACED (ufcs overload-by-receiver
is rejected, and only 1821 used it).
- Protocol: add Io.current_park() -> ParkToken — the running fiber as a token,
captured WITHOUT parking — so race can register the SAME coordinator across N
futures' park slots, then park once via suspend_raw; any completion readies it.
Scheduler returns {self.current} (bails outside a fiber); CBlockingIo returns
{null} (race never parks there — futures are born .ready).
- race :: ufcs (io: Io, futures: $T) -> RaceResult(T), kept in sched.sx (it needs
meta.sx's make_enum/make_variant; pulling that into the io.sx prelude part-file
would cycle). Winner scan -> register/park/deregister -> make_variant the winner
-> Phase-3 cancel each still-.pending loser (no join). RaceResult reused
unchanged (*Future(R) projects field 0 'value' -> R).
- TRUE-cancel: parked losers stop at their next suspend (timers evicted by cancel's
wake), so race returns at WINNER-time, not slowest-loser-time.
- Adversarial review fixes: (1) an all-failing/all-cancelling racer set no longer
deadlock-aborts the scheduler — race bails loudly ('all futures settled without
a winner') when nothing is .ready and nothing is still .pending; (2) only
.pending losers are cancelled, so a loser that already .failed keeps its real
outcome label instead of being stomped to .canceled.
Re-point 1821 to context.io.async + context.io.race (winner a=111, losers
.canceled, completion log only 'task 1 @ 10ms', final clock 10ms — was 30 under
the old cooperative join). New 1826 locks the failing-loser case. Byte-identical
on aarch64-macOS + aarch64-linux. Suite 853/0; .ir churn is the current_park
vtable method.
This commit is contained in:
@@ -36,6 +36,30 @@ installed via `push Context { io = xx scheduler } { … s.run(); }` — exactly
|
||||
just with the scheduler now reachable as `context.io`.
|
||||
|
||||
## Status (2026-06-28)
|
||||
- **Phase 4 — `race` over Futures via `context.io.race`. DONE.** Re-homed the
|
||||
proven first-wins race from `sched.race(*Task)` onto `*Future` handles + the
|
||||
`Io` protocol; the old Task-based `race` is REPLACED (ufcs overload-by-receiver
|
||||
is rejected — "duplicate top-level decl" — and only 1821 used it).
|
||||
- **Protocol affordance:** added `Io.current_park() -> ParkToken` (the running
|
||||
fiber as a token, captured WITHOUT parking) so race can register the SAME
|
||||
coordinator across N futures' `park` slots, then park once via `suspend_raw`;
|
||||
any completion `ready`s it. Scheduler returns `{self.current}` (bails outside
|
||||
a fiber); CBlockingIo returns `{null}` (race never parks there — futures born
|
||||
`.ready`). The await comment already anticipated this fan-in.
|
||||
- **race** (`ufcs (io: Io, futures: $T) -> RaceResult(T)`, in sched.sx — it
|
||||
needs meta.sx's `make_enum`/`make_variant`, and pulling that into the io.sx
|
||||
prelude part-file would cycle): winner scan → register+park → deregister →
|
||||
`make_variant` the winner → Phase-3 `cancel` each loser (NO join). `RaceResult`
|
||||
reused unchanged (`*Future(R)` projects field 0 `value` → R).
|
||||
- **Winner-time return:** with true cancellation the parked losers stop at their
|
||||
next suspend (their timers evicted by cancel's wake), so race returns at the
|
||||
winner's virtual time, not the slowest loser's. 1821 re-pointed to
|
||||
`context.io.async` + `context.io.race`: `winner a=111`, losers `.canceled`,
|
||||
completion log ONLY `task 1 @ 10ms`, final clock `10ms` (was 30 under the old
|
||||
cooperative join). Byte-identical on aarch64-macOS + aarch64-linux. Suite
|
||||
853/0; `.ir` churn (current_park vtable method) regenerated, only 1821 stdout
|
||||
changed otherwise.
|
||||
|
||||
- **Phase 3 — TRUE cancellation via `suspend_raw -> !`. DONE.** A cancelled async
|
||||
worker now abandons its body at its next suspend instead of running to
|
||||
completion. Pieces:
|
||||
|
||||
Reference in New Issue
Block a user