From 09588ab31da9485984275e9b9455fed81fa1c09c Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 30 May 2022 19:00:19 -0400 Subject: [PATCH] refactor: store weak client in the nodes --- src/core/client.rs | 29 +++++++++++------ src/core/eventloop.rs | 12 ++++++-- src/core/scenegraph.rs | 12 ++++++-- src/nodes/core.rs | 36 +++++++++++----------- src/nodes/spatial.rs | 70 ++++++++++++++++++++++-------------------- 5 files changed, 93 insertions(+), 66 deletions(-) diff --git a/src/core/client.rs b/src/core/client.rs index 6dbaa5b..76ce724 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,27 +1,36 @@ use super::scenegraph::Scenegraph; use libstardustxr::messenger::Messenger; use mio::net::UnixStream; -use std::rc::{Rc, Weak}; +use rccell::{RcCell, WeakCell}; pub struct Client<'a> { - messenger: Rc>, - pub scenegraph: Option>, + weak_ref: WeakCell>, + messenger: Messenger<'a>, + scenegraph: Option>, } impl<'a> Client<'a> { - pub fn from_connection(connection: UnixStream) -> Self { - let mut client = Client { + pub fn from_connection(connection: UnixStream) -> RcCell { + let client = RcCell::new(Client { + weak_ref: WeakCell::new(), scenegraph: None, - messenger: Rc::new(Messenger::new(connection)), - }; - client.scenegraph = Some(Scenegraph::new(&mut client)); + messenger: Messenger::new(connection), + }); + client.borrow_mut().weak_ref = client.downgrade(); + client.borrow_mut().scenegraph = Some(Scenegraph::new(client.clone())); client } pub fn dispatch(&self) -> Result<(), std::io::Error> { self.messenger.dispatch(self.scenegraph.as_ref().unwrap()) } - pub fn get_weak_messenger(&self) -> Weak> { - Rc::downgrade(&self.messenger) + pub fn get_messenger(&self) -> &Messenger<'a> { + &self.messenger + } + pub fn get_scenegraph(&self) -> &Scenegraph<'a> { + self.scenegraph.as_ref().unwrap() + } + pub fn get_scenegraph_mut(&mut self) -> &mut Scenegraph<'a> { + self.scenegraph.as_mut().unwrap() } } diff --git a/src/core/eventloop.rs b/src/core/eventloop.rs index 7c26487..a579863 100644 --- a/src/core/eventloop.rs +++ b/src/core/eventloop.rs @@ -3,6 +3,7 @@ use libstardustxr::server; use mio::net::UnixListener; use mio::unix::pipe; use mio::{Events, Interest, Poll, Token}; +use rccell::RcCell; use slab::Slab; use std::io::Write; use std::thread::{self, JoinHandle}; @@ -22,7 +23,7 @@ impl EventLoop { let mut socket = UnixListener::bind(socket_path.clone())?; let (sender, mut receiver) = pipe::new()?; let join_handle = Some(thread::spawn(move || -> Result<()> { - let mut clients: Slab> = Slab::new(); + let mut clients: Slab>> = Slab::new(); let mut poll = Poll::new()?; let mut events = Events::with_capacity(1024); const LISTENER: Token = Token(usize::MAX - 1); @@ -57,7 +58,14 @@ impl EventLoop { }, STOP => return Ok(()), token => loop { - match clients.get(token.0).unwrap().as_ref().unwrap().dispatch() { + match clients + .get(token.0) + .unwrap() + .as_ref() + .unwrap() + .borrow() + .dispatch() + { Ok(_) => continue, Err(e) => { if e.kind() == std::io::ErrorKind::WouldBlock { diff --git a/src/core/scenegraph.rs b/src/core/scenegraph.rs index 8b2ce16..b5efb58 100644 --- a/src/core/scenegraph.rs +++ b/src/core/scenegraph.rs @@ -3,7 +3,7 @@ use crate::nodes::spatial::Spatial; use anyhow::Result; use libstardustxr::scenegraph; use libstardustxr::scenegraph::ScenegraphError; -use rccell::{RcCell, WeakCell}; +use rccell::RcCell; use std::collections::HashMap; pub struct Scenegraph<'a> { @@ -11,7 +11,7 @@ pub struct Scenegraph<'a> { } impl<'a> Scenegraph<'a> { - pub fn new(client: &mut Client<'a>) -> Self { + pub fn new(client: RcCell>) -> Self { // root: Spatial::new(Some(client), "/", Default::default()), // hmd: Spatial::new(Some(client), "/hmd", Default::default()), Scenegraph { @@ -20,6 +20,14 @@ impl<'a> Scenegraph<'a> { } } +impl<'a> Default for Scenegraph<'a> { + fn default() -> Self { + Scenegraph { + spatial_nodes: HashMap::new(), + } + } +} + impl<'a> scenegraph::Scenegraph for Scenegraph<'a> { fn send_signal(&self, path: &str, method: &str, data: &[u8]) -> Result<(), ScenegraphError> { self.spatial_nodes diff --git a/src/nodes/core.rs b/src/nodes/core.rs index 7567362..5ec256e 100644 --- a/src/nodes/core.rs +++ b/src/nodes/core.rs @@ -1,22 +1,24 @@ use crate::core::client::Client; -use crate::core::scenegraph::Scenegraph; use anyhow::{anyhow, ensure, Result}; -use libstardustxr::messenger::Messenger; -use std::{collections::HashMap, rc::Weak, vec::Vec}; +use rccell::{RcCell, WeakCell}; +use std::{collections::HashMap, vec::Vec}; pub type Signal<'a> = Box Result<()> + 'a>; pub type Method<'a> = Box Result> + 'a>; pub struct Node<'a> { + client: WeakCell>, path: String, trailing_slash_pos: usize, - messenger: Weak>, - scenegraph: Option<&'a Scenegraph<'a>>, local_signals: HashMap>, local_methods: HashMap>, + destroyable: bool, } impl<'a> Node<'a> { + pub fn get_client(&self) -> Option>> { + self.client.clone().upgrade() + } pub fn get_name(&self) -> &str { &self.path[self.trailing_slash_pos + 1..] } @@ -25,24 +27,20 @@ impl<'a> Node<'a> { } pub fn from_path( - client: Option<&Client<'a>>, + client: WeakCell>, path: &str, destroyable: bool, ) -> Result> { ensure!(path.starts_with('/'), "Invalid path {}", path); - let mut weak_messenger = Weak::default(); - if let Some(c) = client.as_ref() { - weak_messenger = c.get_weak_messenger(); - } Ok(Node { + client, path: path.to_string(), trailing_slash_pos: path .rfind('/') .ok_or_else(|| anyhow!("Invalid path {}", path))?, - messenger: weak_messenger, - scenegraph: client.as_ref().map(|f| f.scenegraph.as_ref().unwrap()), local_signals: HashMap::new(), local_methods: HashMap::new(), + destroyable, }) } @@ -61,9 +59,10 @@ impl<'a> Node<'a> { .ok_or_else(|| anyhow!("Method {} not found", method))?(data) } pub fn send_remote_signal(&self, method: &str, data: &[u8]) -> Result<()> { - self.messenger - .upgrade() - .ok_or_else(|| anyhow!("Invalid messenger"))? + self.get_client() + .ok_or(anyhow!("Node has no client, can't send remote signal!"))? + .borrow() + .get_messenger() .send_remote_signal(self.path.as_str(), method, data) .map_err(|_| anyhow!("Unable to write in messenger")) } @@ -73,9 +72,10 @@ impl<'a> Node<'a> { data: &[u8], callback: Box, ) -> Result<()> { - self.messenger - .upgrade() - .ok_or_else(|| anyhow!("Invalid messenger"))? + self.get_client() + .ok_or(anyhow!("Node has no client, can't send remote signal!"))? + .borrow() + .get_messenger() .execute_remote_method(self.path.as_str(), method, data, callback) .map_err(|_| anyhow!("Unable to write in messenger")) } diff --git a/src/nodes/spatial.rs b/src/nodes/spatial.rs index 2fbce10..f7ea361 100644 --- a/src/nodes/spatial.rs +++ b/src/nodes/spatial.rs @@ -1,7 +1,7 @@ use super::core::Node; use crate::core::client::Client; use anyhow::{anyhow, Result}; -use euler::Mat4; +// use euler::Mat4; use libstardustxr::{flex_to_quat, flex_to_vec3}; use mint::RowMatrix4; use rccell::{RcCell, WeakCell}; @@ -14,44 +14,46 @@ pub struct Spatial<'a> { impl<'a> Spatial<'a> { pub fn new( - client: Option<&mut Client<'a>>, + client: WeakCell>, path: &str, transform: RowMatrix4, ) -> Result> { - let mut spatial = Spatial { - node: Node::from_path(client.as_deref(), path, true).unwrap(), + let spatial = RcCell::new(Spatial { + node: Node::from_path(client.clone(), path, true).unwrap(), parent: WeakCell::new(), transform, - }; - let spatial_cell = RcCell::new(spatial); - let weak_spatial = spatial_cell.downgrade(); - if let Some(client) = client { - let weak_spatial = weak_spatial.clone(); - spatial.node.add_local_signal( - "setTransform", - Box::new(|data| { - let root = flexbuffers::Reader::get_root(data).unwrap(); - let flex_vec = root.get_vector().unwrap(); - let spatial = client - .scenegraph - .as_ref() - .unwrap() - .spatial_nodes - .get(flex_vec.idx(1).as_str()) - .ok_or(anyhow!("Spatial not found"))?; - let pos = flex_to_vec3!(flex_vec.idx(1)); - let rot = flex_to_quat!(flex_vec.idx(2)); - let scl = flex_to_vec3!(flex_vec.idx(3)); - Ok(()) - }), - ); - client - .scenegraph - .as_mut() - .unwrap() - .spatial_nodes - .insert(path.to_string(), spatial_cell); - } + }); + let weak_spatial = spatial.downgrade(); + let captured_spatial = weak_spatial.clone(); + let captured_client = client.clone(); + spatial.borrow_mut().node.add_local_signal( + "setTransform", + Box::new(move |data| { + let root = flexbuffers::Reader::get_root(data)?; + let flex_vec = root.get_vector()?; + let spatial = captured_spatial + .upgrade() + .ok_or(anyhow!("Invalid spatial"))?; + let client = captured_client.upgrade().ok_or(anyhow!("Invalid client"))?; + let other_spatial = client + .borrow() + .get_scenegraph() + .spatial_nodes + .get(flex_vec.idx(1).as_str()) + .ok_or(anyhow!("Spatial not found"))?; + let pos = flex_to_vec3!(flex_vec.idx(1)); + let rot = flex_to_quat!(flex_vec.idx(2)); + let scl = flex_to_vec3!(flex_vec.idx(3)); + Ok(()) + }), + ); + client + .upgrade() + .unwrap() + .borrow_mut() + .get_scenegraph_mut() + .spatial_nodes + .insert(path.to_string(), spatial); Ok(weak_spatial) }