pub struct ProcessTable { /* private fields */ }Expand description
Process storage, genuinely slotmap::SlotMap-backed (SC-063). ProcessId
(u32) stays the crate-visible identity: v1 never frees/reuses a slot
(fork children get fresh ids from the same monotonic sequence; nothing
calls SlotMap::remove), so order_to_key[id as usize] is a stable,
densely-assigned ProcessId -> ProcessKey side index — the same “assigned
order equals registration order, for the lifetime of a run” invariant the
previous Vec-backed slice already relied on, preserved exactly across
this migration.
Implementations§
Source§impl ProcessTable
impl ProcessTable
pub fn new() -> Self
Sourcepub fn register(&mut self, compiled: Box<dyn CompiledProcess>) -> ProcessId
pub fn register(&mut self, compiled: Box<dyn CompiledProcess>) -> ProcessId
Registers a new process, assigning it the next ProcessId and
registration_order (monotonic, never reused — v1 never frees a slot,
matching Task 11’s documented assumption that ProcessId assignment
order equals registration_order for the lifetime of a run).
Signature unchanged by the slotmap migration — resume.rs (Task 12)
keeps compiling with no edit of its own.
Sourcepub fn count(&self) -> usize
pub fn count(&self) -> usize
How many ProcessIds were ever assigned: ids are dense, 0..count().
Sourcepub fn get(&self, id: ProcessId) -> Option<&ProcessDescriptor>
pub fn get(&self, id: ProcessId) -> Option<&ProcessDescriptor>
Shared-reference lookup (Task 11’s review fix) — lets ResumeDriver
reach a descriptor’s Mutex/AtomicBool fields through a shared
&ProcessTable, never requiring &mut access to the whole table.
Signature unchanged by the slotmap migration.
Sourcepub fn get_mut(&mut self, id: ProcessId) -> Option<&mut ProcessDescriptor>
pub fn get_mut(&mut self, id: ProcessId) -> Option<&mut ProcessDescriptor>
Mutable lookup — added by Task 12 (a minimal, same-track,
additive extension to this Task-11-owned file; recorded in
docs/CONTRACTS.md/this commit’s deviations, not a rewrite of
anything Task 11 shipped). handle_fork/on_child_done mutate
fork_children/fork_parent/fork_join_kind/fork_remaining/
fork_any_signaled directly — plain, non-Mutex fields per Task
11/D1a — which needs exclusive access to the whole table via
&mut ProcessTable. This does not reopen SC-061: Task 12’s review
fix note (resume.rs) already establishes this wave never calls
handle_fork/on_child_done concurrently with resume_for/start
(v1’s default SequentialController dispatches everything from one
thread; only the SC-061 stress test deliberately drives resume_for
from many, and never touches fork state).
Sourcepub fn set_region_id(&mut self, id: ProcessId, region_id: u32)
pub fn set_region_id(&mut self, id: ProcessId, region_id: u32)
Task 9 (A2-part2, CG-102). Sets id’s own region_id, called by
SchedulerControl::register_process (sched/control.rs) right after
register – a small, additive, same-track extension of this Task-
11-owned file (mirroring Task 12’s own get_mut precedent, recorded
there identically), rather than widening register’s own signature:
register’s direct callers (finals.rs, resume.rs, this file’s
own unit tests, fork-child minting) have no notion of region_id at
all and are unrelated to CG-102’s scheduler-dispatch scope, so
leaving register’s arity untouched keeps this a minimal, targeted
addition instead of churning every one of those call sites for a
field they’d only ever pass 0 for anyway (ProcessDescriptor::new
already defaults region_id to that same real v1 value).
Sourcepub fn set_reactive(&mut self, id: ProcessId)
pub fn set_reactive(&mut self, id: ProcessId)
Marks id as a Reactive-region process (ProcessDescriptor::reactive).
Sourcepub fn any_live_program_child(&self) -> bool
pub fn any_live_program_child(&self) -> bool
Whether any live fork child still belongs to a program thread (LRM 24.3).
Sourcepub fn is_reactive(&self, id: ProcessId) -> bool
pub fn is_reactive(&self, id: ProcessId) -> bool
Whether id runs in the Reactive region. false for an unknown id.
Sourcepub fn region_id(&self, id: ProcessId) -> u32
pub fn region_id(&self, id: ProcessId) -> u32
Task 9 (A2-part2, CG-102). region_id(&self, id: ProcessId) -> u32 – the plan’s own literal getter shape. Returns 0 (v1’s own
real, correct single-conservative-partition value, not a sentinel)
for an unknown id rather than panicking or returning Option: a
caller reaching this (e.g. dispatch_ready_set) only ever holds
ProcessIds this same Engine minted, so an unknown id here would
already indicate a bug in the caller’s own bookkeeping, not a
legitimate “no region_id set” state this getter needs to
distinguish.
Sourcepub fn remove(&mut self, id: ProcessId) -> Option<ProcessDescriptor>
pub fn remove(&mut self, id: ProcessId) -> Option<ProcessDescriptor>
Task 7 (B-sched wave, ledger SC-062): the SlotMap::remove
wrapper this file’s own module doc comment already promised (“…
stable… until eventually calls SlotMap::remove – a forward
reference to work that was never done” – now done). Removes id’s
descriptor and returns it; a later get/get_mut for the same id
returns None.
Deviation from the plan’s literal text (recorded here and in
docs/CONTRACTS.md): the plan additionally describes tombstoning
id’s own order_to_key side-index slot. That is unnecessary and
deliberately not done: slotmap::SlotMap::remove already bumps the
removed slot’s internal generation, so the same ProcessKey
value still sitting in order_to_key[id] no longer resolves via
self.slots.get/get_mut – this is the entire reason Task 11
required a genuine SlotMap (SC-063) rather than a Vec in the
first place. Adding a second, hand-maintained tombstone layer on
top of that would only be able to drift out of sync with the
SlotMap’s own source of truth; leaving order_to_key untouched
keeps exactly one source of truth for liveness, and a stale/reused
ProcessId still fails loudly via get’s existing Option return,
exactly as the plan’s own acceptance requires.