diff --git a/src/runtime2/runtime.rs b/src/runtime2/runtime.rs index bf954b4cdea2ede7f5efb75fef397e823e46f962..7cbce4137cf2d6c188236378ba877df3e45e5461 100644 --- a/src/runtime2/runtime.rs +++ b/src/runtime2/runtime.rs @@ -74,7 +74,8 @@ pub(crate) struct RuntimeComp { pub exiting: bool, } -/// Should contain everything that is accessible in a thread-safe manner +/// Should contain everything that is accessible in a thread-safe manner. May +/// NOT contain non-threadsafe fields. // TODO: Do something about the `num_handles` thing. This needs to be a bit more // "foolproof" to lighten the mental burden of using the `num_handles` // variable. @@ -95,12 +96,19 @@ pub(crate) struct CompHandle { } impl CompHandle { - fn new(id: CompId, public: &CompPublic) -> CompHandle { - let handle = CompHandle{ + /// Creates a new component handle and does not increment the reference + /// counter. + fn new_unincremented(id: CompId, public: &CompPublic) -> CompHandle { + return CompHandle{ target: public, id, #[cfg(debug_assertions)] decremented: false, }; + } + + /// Creates a new component handle and increments the reference counter. + fn new(id: CompId, public: &CompPublic) -> CompHandle { + let mut handle = Self::new_unincremented(id, public); handle.increment_users(); return handle; } @@ -232,10 +240,10 @@ impl Runtime { module_name, routine_name, ValueGroup::new_stack(Vec::new()) )?; - let reserved = self.inner.start_create_pdl_component(); + let reserved = self.inner.start_create_component(); let ctx = CompCtx::new(&reserved); let component = Box::new(CompPDL::new(prompt, 0)); - let (key, _) = self.inner.finish_create_pdl_component(reserved, component, ctx, false); + let (key, _) = self.inner.finish_create_component(reserved, component, ctx, false); self.inner.enqueue_work(key); return Ok(()) @@ -284,22 +292,24 @@ impl RuntimeInner { // Creating/destroying components - pub(crate) fn start_create_pdl_component(&self) -> CompReserved { + pub(crate) fn start_create_component(&self) -> CompReserved { self.increment_active_components(); let reservation = self.components.reserve(); return CompReserved{ reservation }; } - pub(crate) fn finish_create_pdl_component( + pub(crate) fn finish_create_component( &self, reserved: CompReserved, component: Box, mut context: CompCtx, initially_sleeping: bool, ) -> (CompKey, &mut RuntimeComp) { + // Construct runtime component let inbox_queue = QueueDynMpsc::new(16); let inbox_producer = inbox_queue.producer(); - let _id = reserved.id(); - context.id = reserved.id(); - let component = RuntimeComp { + let component_id = reserved.id(); + context.id = component_id; + + let mut component = RuntimeComp { public: CompPublic{ sleeping: AtomicBool::new(initially_sleeping), num_handles: AtomicU32::new(1), // the component itself acts like a handle @@ -311,10 +321,17 @@ impl RuntimeInner { exiting: false, }; + // Submit created component into storage. let index = self.components.submit(reserved.reservation, component); - debug_assert_eq!(index, _id.0); + debug_assert_eq!(index, component_id.0); let component = self.components.get_mut(index); + // Bit messy, but here we create the reference of a component to itself, + // the `num_handles` being initialized to `1` above, and add it to the + // component context. + let self_handle = CompHandle::new_unincremented(component_id, &component.public); + component.ctx.add_self_reference(self_handle); + return (CompKey(index), component); }