use super::{
Context, FrameLabelMask, Lane, MAX_TRACKED_ROLES, PhantomData, Poll, ScopeId, ScopeKind,
UnsafeCell, WaiterSlot,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct ScopeCoord {
canonical: ScopeId,
}
impl ScopeCoord {
fn from_scope(scope: ScopeId) -> Option<Self> {
if scope.is_none() || scope.kind() != ScopeKind::Route {
return None;
}
Some(Self {
canonical: scope.canonical(),
})
}
}
#[derive(Clone, Copy)]
struct RouteEntry {
pub(crate) epoch: u16,
pub(crate) arm: u8,
seen_mask: u16,
}
impl RouteEntry {
pub(crate) const fn empty() -> Self {
Self {
epoch: 0,
arm: 0,
seen_mask: 0,
}
}
}
#[derive(Clone, Copy)]
pub(crate) struct RouteFrame {
pub(crate) scope: ScopeId,
entry: RouteEntry,
next: u16,
}
impl RouteFrame {
fn assign(coord: ScopeCoord, next: u16) -> Self {
Self {
scope: coord.canonical,
entry: RouteEntry::empty(),
next,
}
}
pub(crate) fn free(next: u16) -> Self {
Self {
scope: ScopeId::none(),
entry: RouteEntry::empty(),
next,
}
}
}
struct RouteTableStorageParts {
frames: *mut RouteFrame,
lane_heads: *mut u16,
free_head: *mut u16,
pending_frame_hint_masks: *mut FrameLabelMask,
waiters: *mut WaiterSlot,
}
pub(crate) struct RouteTable {
frames: UnsafeCell<*mut RouteFrame>,
route_slots: usize,
lane_base: u32,
lane_slots: u16,
lane_heads: UnsafeCell<*mut u16>,
free_head: UnsafeCell<*mut u16>,
pending_frame_hint_masks: UnsafeCell<*mut FrameLabelMask>,
change_epoch: UnsafeCell<u16>,
waiters: UnsafeCell<*mut WaiterSlot>,
_no_send_sync: PhantomData<*mut ()>,
}
impl Default for RouteTable {
fn default() -> Self {
Self::empty()
}
}
mod storage;
impl RouteTable {
#[inline]
fn lane_slot(&self, lane: Lane) -> usize {
debug_assert!(lane.raw() >= self.lane_base);
let lane_idx = (lane.raw() - self.lane_base) as usize;
debug_assert!(
lane_idx < self.lane_slots(),
"route lane must fit bound lane span"
);
lane_idx
}
#[inline]
fn role_slot_count(role_count: u8) -> usize {
core::cmp::min(role_count as usize, MAX_TRACKED_ROLES)
}
#[inline]
fn complete_seen_mask(role_slots: usize) -> u16 {
if role_slots == 0 {
0
} else if role_slots >= u16::BITS as usize {
u16::MAX
} else {
(1u16 << role_slots) - 1
}
}
#[inline]
fn frame_ref(&self, idx: usize) -> &RouteFrame {
unsafe { &*self.frames_ptr().add(idx) }
}
#[inline]
fn frame_mut(&self, idx: usize) -> &mut RouteFrame {
unsafe { &mut *self.frames_ptr().add(idx) }
}
#[inline]
fn slot_for_scope(&self, lane_idx: usize, coord: ScopeCoord) -> Option<usize> {
let mut current = unsafe { *self.lane_heads_ptr().add(lane_idx) };
while current != Self::NO_FRAME {
let idx = current as usize;
if self.frame_ref(idx).scope == coord.canonical {
return Some(idx);
}
current = self.frame_ref(idx).next;
}
None
}
fn slot_or_alloc(&self, lane_idx: usize, coord: ScopeCoord) -> Option<usize> {
if let Some(idx) = Self::slot_for_scope(self, lane_idx, coord) {
return Some(idx);
}
if self.route_slots == 0 {
return None;
}
let idx = self.pop_free_slot()?;
let head = unsafe { *self.lane_heads_ptr().add(lane_idx) };
*self.frame_mut(idx) = RouteFrame::assign(coord, head);
unsafe {
*self.lane_heads_ptr().add(lane_idx) = idx as u16;
}
Some(idx)
}
fn try_reclaim_route_slot(&self, lane_idx: usize, slot_idx: usize, role_count: u8) {
let role_mask = Self::complete_seen_mask(Self::role_slot_count(role_count));
if role_mask == 0 {
return;
}
let frame = self.frame_ref(slot_idx);
if frame.entry.epoch == 0 || (frame.entry.seen_mask & role_mask) != role_mask {
return;
}
let mut prev = Self::NO_FRAME;
let mut current = unsafe { *self.lane_heads_ptr().add(lane_idx) };
while current != Self::NO_FRAME {
let current_idx = current as usize;
let next = self.frame_ref(current_idx).next;
if current_idx == slot_idx {
if prev == Self::NO_FRAME {
unsafe {
*self.lane_heads_ptr().add(lane_idx) = next;
}
} else {
self.frame_mut(prev as usize).next = next;
}
self.push_free_slot(slot_idx);
return;
}
prev = current;
current = next;
}
}
#[inline]
fn seen_bit(role_idx: usize) -> u16 {
debug_assert!(role_idx < u16::BITS as usize);
1u16 << (role_idx as u32)
}
#[inline]
fn bump_change_epoch(&self) {
let epoch = unsafe { &mut *self.change_epoch.get() };
let next = epoch.wrapping_add(1);
*epoch = if next == 0 { 1 } else { next };
}
#[inline]
pub(crate) fn change_epoch(&self) -> u16 {
unsafe { *self.change_epoch.get() }
}
pub(crate) fn record_with_role_count(
&self,
lane: Lane,
role_count: u8,
role_from: u8,
scope: ScopeId,
arm: u8,
) -> u16 {
let coord = ScopeCoord::from_scope(scope).expect("route record requires structured scope");
let lane_idx = self.lane_slot(lane);
let slot_idx = Self::slot_or_alloc(self, lane_idx, coord).unwrap_or_else(|| {
let free_head = unsafe { *self.free_head_ptr() };
panic!(
"route ledger exhausted: lane_idx={lane_idx} frame_capacity={} free_head={} coord_local={}",
self.route_slots,
free_head,
coord.canonical.local_ordinal()
);
});
let entry = &mut self.frame_mut(slot_idx).entry;
let mut epoch = entry.epoch.wrapping_add(1);
if epoch == 0 {
epoch = 1;
}
entry.epoch = epoch;
entry.arm = arm;
entry.seen_mask = 0;
let role_slots = Self::role_slot_count(role_count);
if (role_from as usize) < role_slots {
entry.seen_mask |= Self::seen_bit(role_from as usize);
}
self.bump_change_epoch();
let waiters = self.waiters_ptr();
let mut role_idx = 0usize;
while role_idx < MAX_TRACKED_ROLES {
unsafe {
(*waiters.add(lane_idx * MAX_TRACKED_ROLES + role_idx)).wake();
}
role_idx += 1;
}
epoch
}
pub(crate) fn poll_with_role_count(
&self,
lane: Lane,
role_count: u8,
role: u8,
scope: ScopeId,
cx: &mut Context<'_>,
) -> Poll<u8> {
let role_slots = Self::role_slot_count(role_count);
if (role as usize) >= role_slots {
return Poll::Ready(0);
}
let coord = ScopeCoord::from_scope(scope).expect("route poll requires structured scope");
let lane_idx = self.lane_slot(lane);
let slot_idx = match Self::slot_or_alloc(self, lane_idx, coord) {
Some(idx) => idx,
None => return Poll::Pending,
};
let entry = &mut self.frame_mut(slot_idx).entry;
let role_bit = Self::seen_bit(role as usize);
if entry.epoch != 0 && (entry.seen_mask & role_bit) == 0 {
entry.seen_mask |= role_bit;
let arm = entry.arm;
self.try_reclaim_route_slot(lane_idx, slot_idx, role_count);
self.bump_change_epoch();
return Poll::Ready(arm);
}
let waiters = self.waiters_ptr();
let slot = unsafe { &mut *waiters.add(lane_idx * MAX_TRACKED_ROLES + role as usize) };
slot.set(cx.waker());
Poll::Pending
}
pub(crate) fn acknowledge_with_role_count(
&self,
lane: Lane,
role_count: u8,
role: u8,
scope: ScopeId,
) -> Option<u8> {
let role_slots = Self::role_slot_count(role_count);
if (role as usize) >= role_slots {
return None;
}
let coord = ScopeCoord::from_scope(scope)?;
let lane_idx = self.lane_slot(lane);
let slot_idx = Self::slot_for_scope(self, lane_idx, coord)?;
let entry = &mut self.frame_mut(slot_idx).entry;
if entry.epoch == 0 {
return None;
}
let role_bit = Self::seen_bit(role as usize);
if (entry.seen_mask & role_bit) != 0 {
return None;
}
entry.seen_mask |= role_bit;
let arm = entry.arm;
self.try_reclaim_route_slot(lane_idx, slot_idx, role_count);
self.bump_change_epoch();
Some(arm)
}
pub(crate) fn peek_with_role_count(
&self,
lane: Lane,
role_count: u8,
role: u8,
scope: ScopeId,
) -> Option<u8> {
let role_slots = Self::role_slot_count(role_count);
if (role as usize) >= role_slots {
return None;
}
let coord = ScopeCoord::from_scope(scope)?;
let lane_idx = self.lane_slot(lane);
let slot_idx = Self::slot_for_scope(self, lane_idx, coord)?;
let entry = self.frame_ref(slot_idx).entry;
let role_bit = Self::seen_bit(role as usize);
(entry.epoch != 0 && (entry.seen_mask & role_bit) == 0).then_some(entry.arm)
}
pub(crate) fn has_pending_lane_with_role_count(
&self,
role_count: u8,
role: u8,
scope: ScopeId,
lane: Lane,
) -> bool {
let role_slots = Self::role_slot_count(role_count);
if (role as usize) >= role_slots {
return false;
}
let coord = match ScopeCoord::from_scope(scope) {
Some(coord) => coord,
None => return false,
};
let role_bit = Self::seen_bit(role as usize);
let lane_idx = self.lane_slot(lane);
if let Some(slot_idx) = Self::slot_for_scope(self, lane_idx, coord) {
let entry = self.frame_ref(slot_idx).entry;
return entry.epoch != 0 && (entry.seen_mask & role_bit) == 0;
}
false
}
#[inline]
pub(crate) fn pending_frame_hint_mask_for_lane(&self, lane: Lane) -> FrameLabelMask {
if self.route_slots == 0 {
return FrameLabelMask::EMPTY;
}
let lane_idx = self.lane_slot(lane);
unsafe { *self.pending_frame_hint_masks_ptr().add(lane_idx) }
}
pub(crate) fn update_pending_frame_hint_mask_for_lane(
&self,
lane: Lane,
before: FrameLabelMask,
after: FrameLabelMask,
) {
if before == after || self.route_slots == 0 {
return;
}
let lane_idx = self.lane_slot(lane);
unsafe {
*self.pending_frame_hint_masks_ptr().add(lane_idx) = after;
}
self.bump_change_epoch();
}
pub(crate) fn has_pending_frame_hint_for_lane(
&self,
lane: Lane,
frame_label_mask: FrameLabelMask,
) -> bool {
if self.route_slots == 0 {
return false;
}
let lane_idx = self.lane_slot(lane);
unsafe { *self.pending_frame_hint_masks_ptr().add(lane_idx) }.intersects(frame_label_mask)
}
pub(crate) fn reset_lane(&self, lane: Lane) {
if self.route_slots == 0 {
return;
}
let lane_idx = self.lane_slot(lane);
let mut current = unsafe { *self.lane_heads_ptr().add(lane_idx) };
unsafe {
*self.lane_heads_ptr().add(lane_idx) = Self::NO_FRAME;
}
while current != Self::NO_FRAME {
let idx = current as usize;
let next = self.frame_ref(idx).next;
self.push_free_slot(idx);
current = next;
}
let pending_frame_hint_masks = self.pending_frame_hint_masks_ptr();
unsafe {
*pending_frame_hint_masks.add(lane_idx) = FrameLabelMask::EMPTY;
}
let waiters = self.waiters_ptr();
let mut role_idx = 0usize;
while role_idx < MAX_TRACKED_ROLES {
unsafe {
(*waiters.add(lane_idx * MAX_TRACKED_ROLES + role_idx)).clear();
}
role_idx += 1;
}
self.bump_change_epoch();
}
pub(crate) fn wake_lane_waiters(&self, lane: Lane) {
if self.route_slots == 0 {
return;
}
let lane_idx = self.lane_slot(lane);
let waiters = self.waiters_ptr();
let mut role_idx = 0usize;
while role_idx < MAX_TRACKED_ROLES {
unsafe {
(*waiters.add(lane_idx * MAX_TRACKED_ROLES + role_idx)).wake();
}
role_idx += 1;
}
}
}