diff --git a/src/runtime2/runtime.rs b/src/runtime2/runtime.rs index 9a43e687e1389cb34c3b6ebd684ce1b71f1b49ce..b75d686ad2cea3fa8f9f1fe36eb812aca2da7080 100644 --- a/src/runtime2/runtime.rs +++ b/src/runtime2/runtime.rs @@ -70,6 +70,11 @@ struct BranchPortDesc { num_times_fired: u32, // number of puts/gets on this port } +struct BranchContext { + just_called_did_put: bool, + pending_channel: Option<(Value, Value)>, +} + struct BranchDesc { index: u32, parent_index: Option, @@ -78,6 +83,7 @@ struct BranchDesc { owned_ports: Vec, message_inbox: HashMap<(PortId, u32), ValueGroup>, // from (port id, 1-based recv index) to received value port_mapping: HashMap, + branch_context: BranchContext, } impl BranchDesc { @@ -91,6 +97,10 @@ impl BranchDesc { owned_ports, message_inbox: HashMap::new(), port_mapping: HashMap::new(), + branch_context: BranchContext{ + just_called_did_put: false, + pending_channel: None, + } } } @@ -98,6 +108,11 @@ impl BranchDesc { /// is the branching point for the new one, i.e. the parent in the branching /// tree. fn new_sync_from(index: u32, branch_state: &BranchDesc) -> Self { + // We expect that the given branche's context is not halfway handling a + // `put(...)` or a `channel x -> y` statement. + debug_assert!(!branch_state.branch_context.just_called_did_put); + debug_assert!(branch_state.branch_context.pending_channel.is_none()); + Self{ index, parent_index: Some(branch_state.index), @@ -106,6 +121,10 @@ impl BranchDesc { owned_ports: branch_state.owned_ports.clone(), message_inbox: branch_state.message_inbox.clone(), port_mapping: branch_state.port_mapping.clone(), + branch_context: BranchContext{ + just_called_did_put: false, + pending_channel: None, + } } } } @@ -280,10 +299,7 @@ impl Runtime { let mut run_context = Context{ inbox: &branch.message_inbox, port_mapping: &branch.port_mapping, - connector_id, - branch_id: Some(branch_index), - just_called_did_put: false, - pending_channel: None, + branch_ctx: &mut branch.branch_context, }; let run_result = branch.code_state.run(&mut run_context, &self.protocol); @@ -415,6 +431,7 @@ impl Runtime { // assigned the port value and if so, if it is // consistent. let mut can_put = true; + branch.branch_context.just_called_did_put = true; match branch.port_mapping.entry(port_id) { Entry::Vacant(entry) => { // No entry yet @@ -500,10 +517,7 @@ impl Runtime { let mut run_context = Context{ inbox: &branch.message_inbox, port_mapping: &branch.port_mapping, - connector_id, - branch_id: None, - just_called_did_put: false, - pending_channel: None, + branch_ctx: &mut branch.branch_context, }; let run_result = branch.code_state.run(&mut run_context, &self.protocol); @@ -542,9 +556,9 @@ impl Runtime { }, RunResult::NewChannel => { // Prepare channel - debug_assert!(run_context.pending_channel.is_none()); + debug_assert!(run_context.branch_ctx.pending_channel.is_none()); let (put_id, get_id) = Self::add_owned_channel(&mut self.ports, &mut self.port_counter, Some(connector_id)); - run_context.pending_channel = Some(( + run_context.branch_ctx.pending_channel = Some(( port_value_from_id(Some(connector_id), put_id, true), port_value_from_id(Some(connector_id), get_id, false) )); @@ -1028,19 +1042,16 @@ struct Context<'a> { // Temporary references to branch related storage inbox: &'a HashMap<(PortId, u32), ValueGroup>, port_mapping: &'a HashMap, - // Properties of currently running connector/branch - connector_id: u32, - branch_id: Option, - just_called_did_put: bool, - // Resources ready to be retrieved by running code - pending_channel: Option<(Value, Value)>, // (put, get) ports + branch_ctx: &'a mut BranchContext, } impl<'a> crate::protocol::RunContext for Context<'a> { fn did_put(&mut self, port: PortId) -> bool { // Note that we want "did put" to return false if we have fired zero // times, because this implies we did a prevous - return self.just_called_did_put + let old_value = self.branch_ctx.just_called_did_put; + self.branch_ctx.just_called_did_put = false; + return old_value; } fn get(&mut self, port: PortId) -> Option { @@ -1059,7 +1070,7 @@ impl<'a> crate::protocol::RunContext for Context<'a> { } fn get_channel(&mut self) -> Option<(Value, Value)> { - self.pending_channel.take() + self.branch_ctx.pending_channel.take() } }