diff --git a/src/runtime2/component/component_context.rs b/src/runtime2/component/component_context.rs index c02320d58b382798cd59dff48078bd4f00e9b7d6..bb1d8c6254cdff67386d18035d0d3d23c0ac757f 100644 --- a/src/runtime2/component/component_context.rs +++ b/src/runtime2/component/component_context.rs @@ -1,3 +1,5 @@ +use std::fmt::{Debug, Formatter, Result as FmtResult}; + use crate::runtime2::scheduler::*; use crate::runtime2::runtime::*; use crate::runtime2::communication::*; @@ -12,6 +14,86 @@ pub enum PortInstruction { SourceLocation(ExpressionId), } +/// Directionality of a port +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum PortKind { + Putter, + Getter, +} + +/// Bitflags for port +// TODO: Incorporate remaining flags from `Port` struct +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum PortStateFlag { + Closed = 0x01, // If not closed, then the port is open + BlockedDueToPeerChange = 0x02, // busy changing peers, hence use of port is temporarily blocked + BlockedDueToFullBuffers = 0x04, +} + +#[derive(Copy, Clone)] +pub struct PortState { + flags: u32 +} + +impl PortState { + pub(crate) fn new() -> PortState { + return PortState{ flags: 0 } + } + + // high-level + + #[inline] + pub fn is_open(&self) -> bool { + return !self.is_closed(); + } + + #[inline] + pub fn is_closed(&self) -> bool { + return self.is_set(PortStateFlag::Closed); + } + + #[inline] + pub fn is_blocked(&self) -> bool { + return + self.is_set(PortStateFlag::BlockedDueToPeerChange) || + self.is_set(PortStateFlag::BlockedDueToFullBuffers); + } + + // lower-level utils + #[inline] + pub fn set(&mut self, flag: PortStateFlag) { + self.flags |= flag as u32; + } + + #[inline] + pub fn clear(&mut self, flag: PortStateFlag) { + self.flags &= !(flag as u32); + } + + #[inline] + pub const fn is_set(&self, flag: PortStateFlag) -> bool { + return (self.flags & (flag as u32)) != 0; + } +} + +impl Debug for PortState { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + use PortStateFlag::*; + + let mut s = f.debug_struct("PortState"); + for (flag_name, flag_value) in &[ + ("closed", Closed), + ("blocked_peer_change", BlockedDueToPeerChange), + ("blocked_full_buffers", BlockedDueToFullBuffers) + ] { + s.field(flag_name, &self.is_set(*flag_value)); + } + + return s.finish(); + } +} + #[derive(Debug)] pub struct Port { // Identifiers @@ -25,9 +107,7 @@ pub struct Port { pub last_instruction: PortInstruction, // used during sync round to detect port-closed-during-sync errors pub received_message_for_sync: bool, // used during sync round to detect port-closed-before-sync errors pub close_at_sync_end: bool, // set during sync round when receiving a port-closed-after-sync message - // Debugging flag to make sure each port is properly associated and - // disassociated with a peer component - #[cfg(debug_assertions)] pub(crate) associated_with_peer: bool, + pub(crate) associated_with_peer: bool, } pub struct Peer { @@ -74,23 +154,23 @@ impl CompCtx { self_id: putter_id, peer_port_id: getter_id, kind: PortKind::Putter, - state: PortState::Open, + state: PortState::new(), peer_comp_id: self.id, last_instruction: PortInstruction::None, close_at_sync_end: false, received_message_for_sync: false, - #[cfg(debug_assertions)] associated_with_peer: false, + associated_with_peer: false, }); self.ports.push(Port{ self_id: getter_id, peer_port_id: putter_id, kind: PortKind::Getter, - state: PortState::Open, + state: PortState::new(), peer_comp_id: self.id, last_instruction: PortInstruction::None, close_at_sync_end: false, received_message_for_sync: false, - #[cfg(debug_assertions)] associated_with_peer: false, + associated_with_peer: false, }); return Channel{ putter_id, getter_id }; @@ -104,7 +184,7 @@ impl CompCtx { last_instruction: PortInstruction::None, close_at_sync_end: false, received_message_for_sync: false, - #[cfg(debug_assertions)] associated_with_peer: false, + associated_with_peer: false, }); return LocalPortHandle(self_id); } @@ -173,12 +253,6 @@ impl CompCtx { } } - pub(crate) fn set_port_state(&mut self, port_handle: LocalPortHandle, new_state: PortState) { - let port_info = self.get_port_mut(port_handle); - debug_assert_ne!(port_info.state, PortState::Closed); // because then we do not expect to change the state - port_info.state = new_state; - } - pub(crate) fn get_port_handle(&self, port_id: PortId) -> LocalPortHandle { return LocalPortHandle(port_id); } @@ -242,7 +316,7 @@ impl CompCtx { #[inline] fn requires_peer_reference(port: &Port, self_id: CompId, required_if_closed: bool) -> bool { - return (port.state != PortState::Closed || required_if_closed) && port.peer_comp_id != self_id; + return (!port.state.is_closed() || required_if_closed) && port.peer_comp_id != self_id; } fn must_get_port_index(&self, handle: LocalPortHandle) -> usize {