use super::{
ActiveEntrySet, ActiveEntrySlot, CursorEndpoint, CursorInvariantError, CursorRefresh,
FrontierScratchSectionLease, LaneOfferState, OfferEntryKey, ReentryScopeLiveness, ScopeId,
StateIndex, Transport, frontier_global_active_entries_view, state_index_to_usize,
};
use crate::global::typestate::InboundFrameKey;
impl<'r, const ROLE: u8, T> CursorEndpoint<'r, ROLE, T>
where
T: Transport + 'r,
{
#[inline]
pub(in crate::endpoint::kernel) fn root_frontier_has_active_entries(
&self,
root: ScopeId,
) -> bool {
self.frontier_state.root_frontier_has_active_entries(root)
}
#[inline]
pub(in crate::endpoint::kernel) fn root_frontier_active_entries(
&self,
root: ScopeId,
) -> ActiveEntrySet<'_> {
self.frontier_state.root_frontier_active_entries(root)
}
#[inline]
pub(in crate::endpoint::kernel) fn active_frontier_entries<'a>(
&self,
current_parallel: Option<ScopeId>,
scratch: &'a mut FrontierScratchSectionLease<'_, ActiveEntrySlot>,
) -> ActiveEntrySet<'a> {
match current_parallel {
Some(root) => {
let source = self.root_frontier_active_entries(root);
let mut active_entries = frontier_global_active_entries_view(scratch);
active_entries.clear();
let mut slot_idx = 0usize;
while slot_idx < source.len() {
let slot = crate::invariant_some(source.slot_at(slot_idx));
active_entries.insert_key(slot.key, slot.lane_idx);
slot_idx += 1;
}
active_entries.seal()
}
None => self.global_active_entries(scratch),
}
}
pub(in crate::endpoint::kernel) fn detach_lane_from_root_frontier(
&mut self,
info: LaneOfferState,
) {
self.frontier_state.detach_lane_from_root_frontier(info);
}
pub(in crate::endpoint::kernel) fn attach_lane_to_root_frontier(
&mut self,
info: LaneOfferState,
) {
self.frontier_state.attach_lane_to_root_frontier(info);
}
#[inline]
pub(in crate::endpoint::kernel) fn attach_offer_entry_to_root_frontier(
&mut self,
key: OfferEntryKey,
root: ScopeId,
lane_idx: u8,
) {
self.frontier_state
.attach_offer_entry_to_root_frontier(key, root, lane_idx);
}
#[inline]
pub(in crate::endpoint::kernel) fn detach_offer_entry_from_root_frontier(
&mut self,
key: OfferEntryKey,
root: ScopeId,
) {
self.frontier_state
.detach_offer_entry_from_root_frontier(key, root);
}
#[inline]
pub(in crate::endpoint::kernel) fn refresh_after_cursor_move(
&mut self,
refresh: CursorRefresh,
) {
match refresh {
CursorRefresh::Lane(lane) => self.refresh_lane_offer_state(lane as usize),
CursorRefresh::AllLanes => self.sync_lane_offer_state(),
}
}
pub(in crate::endpoint::kernel) fn compute_lane_offer_state(
&self,
lane_idx: usize,
) -> Option<LaneOfferState> {
if lane_idx >= self.cursor.logical_lane_count() {
return None;
}
let reentry_offer = self.active_reentry_offer_for_lane(lane_idx);
let (entry_idx, scope_id) = if let Some(idx) = self.cursor.index_for_lane_step(lane_idx) {
let scope_id = self.cursor.node_scope_id_at(idx);
if self.cursor.has_route_scope(scope_id) {
(idx, scope_id)
} else {
let (scope_id, entry) = reentry_offer?;
(state_index_to_usize(entry), scope_id)
}
} else {
let (scope_id, entry) = reentry_offer?;
(state_index_to_usize(entry), scope_id)
};
let normalized = self.cursor.normalize_lane_offer_entry(
scope_id,
entry_idx,
|scope| self.selected_live_arm_for_scope(scope),
|| self.active_reentry_offer_for_lane(lane_idx),
)?;
let scope_id = normalized.scope_id();
let entry_idx = normalized.entry_idx();
let is_controller = self.cursor.is_route_controller(scope_id);
let is_dynamic = self.cursor.route_scope_resolver(scope_id).is_some();
let frontier_facts =
Self::frontier_facts_at(&self.cursor, scope_id, is_controller, is_dynamic, entry_idx);
let mut flags = 0u8;
if is_controller {
flags |= LaneOfferState::FLAG_CONTROLLER;
}
if is_dynamic {
flags |= LaneOfferState::FLAG_DYNAMIC;
}
if frontier_facts.ready() {
flags |= LaneOfferState::FLAG_INTRINSIC_READY;
}
let parallel_root = match Self::parallel_scope_root(&self.cursor, scope_id) {
Some(root) => root,
None => ScopeId::none(),
};
Some(LaneOfferState {
scope: scope_id,
entry: StateIndex::from_usize(entry_idx),
parallel_root,
frontier: frontier_facts.frontier,
flags,
})
}
pub(super) fn active_reentry_offer_for_lane(
&self,
lane_idx: usize,
) -> Option<(ScopeId, StateIndex)> {
if lane_idx >= self.cursor.logical_lane_count() {
return None;
}
let scope = match self
.decision_state
.active_reentry_scope_for_lane(lane_idx, |scope| {
if !self.is_reentry_route(scope) {
return Ok(ReentryScopeLiveness::NotReentry);
}
let Some(arm) = self.selected_arm_for_scope(scope) else {
return Ok(ReentryScopeLiveness::Incomplete);
};
Ok(if self.reentrant_selected_arm_complete(scope, arm) {
ReentryScopeLiveness::Complete
} else {
ReentryScopeLiveness::Incomplete
})
}) {
Ok(scope) => scope?,
Err(CursorInvariantError::INVARIANT) => crate::invariant(),
};
self.cursor.active_reentry_offer_entry(scope)
}
pub(in crate::endpoint::kernel) fn active_reentry_scope_for_observed_frame(
&self,
key: InboundFrameKey,
) -> Result<Option<ScopeId>, CursorInvariantError> {
let lane_idx = key.lane as usize;
if lane_idx >= self.cursor.logical_lane_count() {
return Ok(None);
}
self.decision_state
.active_reentry_scope_for_lane(lane_idx, |scope| {
if !self.is_reentry_route(scope) {
return Ok(ReentryScopeLiveness::NotReentry);
}
if self
.cursor
.passive_descendant_target_index_for_key(scope, key)?
.is_none()
{
return Ok(ReentryScopeLiveness::NotReentry);
}
let Some(arm) = self.selected_arm_for_scope(scope) else {
return Ok(ReentryScopeLiveness::Incomplete);
};
Ok(if self.reentrant_selected_arm_complete(scope, arm) {
ReentryScopeLiveness::Complete
} else {
ReentryScopeLiveness::Incomplete
})
})
}
}