pg: Phase 1 — identity & storage substrate (RFC 012)
Add a process-groups module (name -> multiset<Member>) sibling to the
registry, plus the cluster-shaped identity it is keyed on.
- NodeId/Incarnation u32 newtypes; Member { node, incarnation, pid } at
final (BEAM NEW_PID_EXT-shaped) layout.
- Config::node_id/incarnation builder setters beside wake_slot, defaulting
to a fixed single-node value; threaded through RuntimeInner::new.
- process_groups: RawMutex<ProcessGroups> on RuntimeInner, Leaf class,
mirroring the registry field.
- remove_where: the one dumb predicate-eviction primitive (no liveness wired
yet; first caller is the Phase 2 death hook).
- Public surface (join/leave/members/pick) in pre-liveness/pre-monitor form,
Pid-shaped; node/incarnation filled from runtime identity.
- Structural unit tests on synthetic members: idempotent join, multiset
semantics across groups, generation-distinct members, leave + empty-group
pruning, predicate sweep, incarnation-sweep shape.
This commit is contained in:
@@ -155,6 +155,8 @@ pub struct Config {
|
||||
stack_pool_cap: usize,
|
||||
max_actors: usize,
|
||||
wake_slot: bool,
|
||||
node_id: crate::pg::NodeId,
|
||||
incarnation: crate::pg::Incarnation,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -168,6 +170,8 @@ impl Config {
|
||||
stack_pool_cap: n * 4,
|
||||
max_actors: DEFAULT_MAX_ACTORS,
|
||||
wake_slot: false,
|
||||
node_id: crate::pg::DEFAULT_NODE_ID,
|
||||
incarnation: crate::pg::DEFAULT_INCARNATION,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +189,8 @@ impl Config {
|
||||
stack_pool_cap: max * 4,
|
||||
max_actors: DEFAULT_MAX_ACTORS,
|
||||
wake_slot: false,
|
||||
node_id: crate::pg::DEFAULT_NODE_ID,
|
||||
incarnation: crate::pg::DEFAULT_INCARNATION,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,6 +247,23 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
/// This runtime's node identity (RFC 012). Defaults to a fixed single-node
|
||||
/// value; clustering (RFC 010) will supply a real one. Threaded through pg
|
||||
/// storage/eviction so the process-group public API never changes to
|
||||
/// acquire it.
|
||||
pub fn node_id(mut self, id: impl Into<crate::pg::NodeId>) -> Self {
|
||||
self.node_id = id.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// This runtime's incarnation epoch (RFC 012) — the BEAM `Creation` analogue
|
||||
/// that separates a crashed node from its restart. Defaults to a fixed
|
||||
/// single-node value; constant for the life of a run.
|
||||
pub fn incarnation(mut self, inc: impl Into<crate::pg::Incarnation>) -> Self {
|
||||
self.incarnation = inc.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// The number of scheduler threads this config resolves to.
|
||||
pub fn resolved_thread_count(&self) -> usize {
|
||||
if let Some(e) = self.exact {
|
||||
@@ -265,6 +288,8 @@ impl Default for Config {
|
||||
stack_pool_cap: avail * 4,
|
||||
max_actors: DEFAULT_MAX_ACTORS,
|
||||
wake_slot: false,
|
||||
node_id: crate::pg::DEFAULT_NODE_ID,
|
||||
incarnation: crate::pg::DEFAULT_INCARNATION,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,6 +532,17 @@ pub(crate) struct RuntimeInner {
|
||||
/// with any other lock; liveness checks under it read only the atomic
|
||||
/// slot word.
|
||||
pub(crate) registry: RawMutex<crate::registry::Registry>,
|
||||
/// Runtime identity (RFC 012). Read-only after init — one node, one fixed
|
||||
/// incarnation until clustering (RFC 010) supplies real values. Carried
|
||||
/// like `wake_slot`; pg fills these into every `Member` so the public
|
||||
/// surface stays Pid-shaped.
|
||||
pub(crate) node_id: crate::pg::NodeId,
|
||||
pub(crate) incarnation: crate::pg::Incarnation,
|
||||
/// Process groups: `name -> multiset<Member>` (RFC 012). RawMutex Leaf,
|
||||
/// exactly like `registry`: never held with any other lock; liveness
|
||||
/// checks under it read only the atomic slot word, and the eviction path
|
||||
/// keeps it off the send path.
|
||||
pub(crate) process_groups: RawMutex<crate::pg::ProcessGroups>,
|
||||
/// Recycled stacks waiting to be reused by the next spawn.
|
||||
pub(crate) stack_pool: RawMutex<Vec<crate::stack::Stack>>,
|
||||
/// Maximum number of stacks to retain in the pool.
|
||||
@@ -521,6 +557,8 @@ impl RuntimeInner {
|
||||
stack_pool_cap: usize,
|
||||
max_actors: usize,
|
||||
wake_slot: bool,
|
||||
node_id: crate::pg::NodeId,
|
||||
incarnation: crate::pg::Incarnation,
|
||||
) -> Arc<Self> {
|
||||
let stats = (0..thread_count).map(|_| SchedulerStats::new()).collect();
|
||||
let slots: Box<[Slot]> = (0..max_actors).map(|_| Slot::vacant()).collect();
|
||||
@@ -542,6 +580,9 @@ impl RuntimeInner {
|
||||
timeslice_cycles,
|
||||
wake_slot,
|
||||
registry: RawMutex::new(crate::registry::Registry::new()),
|
||||
node_id,
|
||||
incarnation,
|
||||
process_groups: RawMutex::new(crate::pg::ProcessGroups::new()),
|
||||
stack_pool: RawMutex::new(Vec::new()),
|
||||
stack_pool_cap,
|
||||
})
|
||||
@@ -712,6 +753,8 @@ pub fn init(config: Config) -> Runtime {
|
||||
config.stack_pool_cap,
|
||||
config.max_actors,
|
||||
config.wake_slot,
|
||||
config.node_id,
|
||||
config.incarnation,
|
||||
),
|
||||
thread_count: n,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user