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

78 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.