Files
hakorune/docs/reference/concurrency/semantics.md

3.0 KiB
Raw Permalink Blame History

Concurrency Semantics (docs-only; to guide MVP)

Status: reference for userland Phase0. No runtime changes during the featurepause.

Blocking & Non-Blocking

  • send(v) blocks when the buffer is full (capacity reached). Unblocks when a receiver takes an item.
  • receive() blocks when buffer is empty. Unblocks when a sender provides an item.
  • try_send(v) -> Bool: returns immediately; false if full or closed.
  • try_receive() -> (Bool, Any?): returns immediately; false if empty and not closed.
  • receive_timeout(ms) -> (Bool, Any?): returns false on timeout.

Implementation note (Phase0): no busy loop. Use cooperative queues; later replaced by OS-efficient wait.

Close Semantics

  • close() marks the channel closed. Further send is an error.
  • After close, receive continues to drain buffered items; once empty, returns a closed indicator (shape per API, e.g., (false, End)).
  • Double close is an error.

Select Semantics

  • when(channel, handler) registers selectable cases.
  • await() examines cases:
    • If one or more ready: choose one (random/roundrobin) and execute its handler atomically.
    • If none ready: Phase0 may block via a multi-wait helper or return false if non-blocking policy requested.
  • Fairness: no starvation requirement; Phase0 uses simple fairness; Phase2 integrates runtime help.

Structured Concurrency

  • RoutineScopeBox owns spawned routines.
  • On fini(): cancel pending children, bounded join, and ensure resource release.
  • Cancellation should unblock channel waits promptly.

Types & Safety

  • Phase0: runtime tag checks on ChannelBox send/receive are optional; document expected element type.
  • Future: TypedChannelBox<T> with static verification; falls back to runtime tags when needed.

Observability

  • Enable NYASH_CONC_TRACE=1 to emit JSONL events.
  • Event schema (recommendation):
    • Common: ts (ms), op (string), rid (routine id), cid (channel id, optional), ok (bool), scope (scope id, optional)
    • spawn/start/join/cancel: {op:"spawn", rid, ts}, {op:"join", rid, ok, ts}
    • send/recv: {op:"send", cid, size, cap, ts}, {op:"recv", cid, size, cap, ts}
    • park/unpark: {op:"park", rid, reason, ts}, {op:"unpark", rid, reason, ts}
    • select: {op:"select", cases:n, chosen:k, ts}
    • close: {op:"close", cid, ts}
  • Causality: producers must emit before consumers observe; timestamps monotonic per process.

Test Plan (smokes)

  • ping_pong.hako: two routines exchange N messages; assert order and count.
  • bounded_pc.hako: producer/consumer with capacity=1..N; ensure no busy-wait and correct totals.
  • select_two.hako: two channels; verify first-ready choice and distribution.
  • close_semantics.hako: send after close -> error; drain -> End; double close -> error.
  • scope_cancel.hako: RoutineScopeBox cancels children; parked receivers unblocked.

Migration Path

  • Phase0 userland boxes are kept while Phase2 runtime grows; API stable.
  • Replace cooperative wait with WaiterBox (Phase1) and runtime park/unpark later.