Skip to main content

Module lifecycle

Module lifecycle 

Source
Expand description

Flow lifecycle: monitors, links, registry, WAITING_SEND.

Byteflow coordinates exit in one place: finalize_flow (iterative work list — not recursion). The VM only produces FlowOutcome; the runtime revokes Caps, delivers DOWN, propagates links, and sweeps the registry.

FlowExitReason is an explicit argument to finalize, not inferred from the join string. A linked kill therefore reports Link on DOWN, not Fault.

§Identity vs address

TypeRole
FlowIdIdentity. Never reused. Host monitor / link take this.
CapIdAddress. 128-bit CSPRNG token. Bytecode uses Caps.

There is no generation on Caps: a dead flow’s Caps stop resolving (CapTable::revoke_flow bumps the epoch and sweeps every entry held by or targeting that flow). A guessed CapId never grants Send/Ask. LINK / MONITOR require those bits on the addressing Cap; ADMIN is a scheduler Cap, never a default spawn grant.

§Monitors (A ──monitor──> B)

Runtime::monitor(owner, target) or bytecode Fn::monitor(cap) creates a MonitorRef. When target exits, owner receives an Atomic Hop:

tag        = TAG_SYS_DOWN (0xFF01)
request_id = MonitorRef
sender     = target FlowId  (identity, not a Cap)
payload    = FlowExitReason as u64

Selective receive: receive_match_imm(TAG_SYS_DOWN).

Abnormal exit (Fault, Link, …) kills the peer (cooperative: parked flows are taken out of the mailbox; running flows see a kill signal at the next quantum). Normal (clean return / Exit) only drops the link.

§Registry

register_name(name, CapId) stores a Cap, never a FlowId. whereis returns that Cap. Finalize unregisters every name for the dead flow.

§Ask vs target death

An Ask / AskTimeout parked for a reply is indexed on the target. When that flow finalizes, the asker is taken off its mailbox and resumed with TAG_SYS_EXIT (Message::linked_exit: sender = dead FlowId, payload = FlowExitReason). This is not a hang and is distinct from AskTimeout writing Unit.

§WAITING_SEND

Bytecode Send / Ask against a full Reject inbox park the sender in the target mailbox. Each pop admits one waiter (no wake storm). Host Runtime::send still returns SendError::MailboxFull.

Mailbox::close runs before directory unregister so a sender that lost the Full/park race cannot park on a dead inbox (that would leak the flow).

§Kill

Runtime::kill(id) is cooperative: a parked receiver / WAITING_SEND finalizes immediately (FlowExitReason::Killed); a running flow dies at the next quantum.

§Supervisor strategies

Host Supervisor supports OneForOne, OneForAll, and RestForOne. Sibling abort uses FlowExitReason::Supervisor and an expected_shutdown flag so those exits do not start another cascade. Intensity still counts the triggering restart, not the sibling kills.

§Resource governor

RuntimeConfig::max_flows (0 = unlimited) is checked on every host and bytecode spawn. Over the cap → SpawnError::FlowLimit.

Each flow also carries a FlowQuota from RuntimeConfig::quota: remaining CPU (distinct from the scheduler quantum), heap charge, and spawn/send token buckets. Exhaustion fails closed (QuotaError). An ADMIN Cap can Runtime::admin_top_up_cpu.