Files
hakorune/docs/proposals/concurrency/boxes.md

78 lines
3.6 KiB
Markdown
Raw Normal View History

# Nyash Concurrency — Box Model (Proposal, docs-only)
Status: design-only during the featurepause. No runtime or spec changes. Implement after MiniVM baseline is stable.
Intent
- Bring Go-like CSP (goroutine/channels/select) into Nyash via “Everything is Box”.
- Keep semantics explicit, lifecycle safe (birth/fini), and observable. Phase-in from userland → runtime.
Scope (Phase0: userland MVP)
- RoutineBox: lightweight task wrapper over `nowait` (state, join/cancel, status).
- ChannelBox: bounded/unbounded queue + blocking/non-blocking ops + close semantics.
- SelectBox: multi-channel wait (first-ready) with simple fairness.
- RoutineScopeBox: structured concurrency; children are canceled on scope fini.
- Observability: JSONL trace toggled by `NYASH_CONC_TRACE=1`.
NonGoals (Phase0)
- M:N scheduler, OS-level park/unpark, net poller integration (deferred to Phase2 runtime work).
API Sketch (userland)
- RoutineBox
- birth(fn)
- start(): Void
- join(timeout_ms?: Int) -> Bool // true if joined; false on timeout
- cancel(): Void
- status() -> String // ready|running|done|canceled|error
- ChannelBox(capacity: Int=0)
- send(v): Void // blocks if full (Phase0: simulated park)
- try_send(v) -> Bool
- receive() -> Any // blocks if empty (Phase0: simulated park)
- try_receive() -> (Bool, Any?)
- receive_timeout(ms: Int) -> (Bool, Any?)
- close(): Void // further send fails; recv drains until empty then End
- SelectBox
- birth()
- when(ch: ChannelBox, handler: Fn): Void
- await() -> Bool // returns after one handler runs; false if none ready and no wait policy
- await_timeout(ms: Int) -> Bool
- RoutineScopeBox
- birth()
- spawn(fn) -> RoutineBox
- fini() // cancels pending routines and waits boundedly
Semantics
- Capacity:
- 0: rendezvous channel (send/recv rendezvous).
- N>0: bounded ring buffer.
- Close:
- close() marks channel as closed. send() after close -> error. receive() returns buffered items; when empty -> (false, End) style result; exact return shape defined per API.
- Blocking:
- Phase0 userland uses cooperative wait queues; no busy loops. try_* and timeout variants provided.
- Select fairness:
- If multiple ready, choose random/roundrobin. Starvation avoidance is a design requirement; precise algorithm can evolve.
- Types:
- `TypedChannelBox<T>` is a future extension; Phase0 uses runtime tags/guards documented in reference.
- Cancellation:
- RoutineScopeBox cancels children on fini; Channel waits should return (canceled) promptly.
Phases
- Phase0 (userland MVP / PyVM first)
- Implement the 4 boxes above with minimal queues/waits, plus trace hooks.
- Smokes: pingpong, bounded producer/consumer, twoway select, close semantics, scope cancel.
- Phase1 (park/unpark abstraction)
- Introduce `WaiterBox`/`CondBox` that map to efficient OS waits where available. Keep same APIs.
- Phase2 (runtime integration)
- Scheduler (M:N), GC and net poller integration, fairness and profiling. Keep Box APIs stable.
Observability
- `NYASH_CONC_TRACE=1` → JSONL events: spawn/join/cancel/send/recv/park/unpark/select/close with routine IDs, channel IDs, timestamps.
Safety & Diagnostics
- Deadlock hints: trace dependent waits; optional detector (dev only) can dump waitfor graph.
- API contracts explicitly define error return for misuse (send on closed, double close, etc.).
Deliverables (docsonly during the featurepause)
- This proposal (boxes & semantics).
- Reference page with blocking/close/select rules (see reference/concurrency/semantics.md).
- Test plan with named smokes and expected outputs.