diff --git a/src/core/client.rs b/src/core/client.rs index ad7378f..9a89345 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,18 +1,22 @@ +use super::eventloop::EventLoop; use super::scenegraph::Scenegraph; use crate::nodes::field; use crate::nodes::spatial; use libstardustxr::messenger::Messenger; use mio::net::UnixStream; use std::rc::Rc; +use std::sync::{Arc, Weak}; pub struct Client<'a> { + event_loop: Weak, messenger: Messenger<'a>, scenegraph: Scenegraph<'a>, } impl<'a> Client<'a> { - pub fn from_connection(connection: UnixStream) -> Rc { + pub fn from_connection(connection: UnixStream, event_loop_ref: &Arc) -> Rc { let client = Rc::new(Client { + event_loop: Arc::downgrade(event_loop_ref), messenger: Messenger::new(connection), scenegraph: Default::default(), }); diff --git a/src/core/eventloop.rs b/src/core/eventloop.rs index 4777b36..6c80267 100644 --- a/src/core/eventloop.rs +++ b/src/core/eventloop.rs @@ -7,23 +7,31 @@ use mio::{Events, Interest, Poll, Token}; use slab::Slab; use std::io::Write; use std::rc::Rc; +use std::sync::{Arc, RwLock}; use std::thread::{self, JoinHandle}; pub struct EventLoop { pub socket_path: String, - join_handle: Option>>, + join_handle: RwLock>>>, stop_write: pipe::Sender, } impl EventLoop { - pub fn new(timeout: Option) -> Result { + pub fn new(timeout: Option) -> Result> { let socket_path = server::get_free_socket_path() .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::Other))?; let mut socket = UnixListener::bind(socket_path.clone())?; let (sender, mut receiver) = pipe::new()?; + let event_loop_arc = Arc::new(EventLoop { + socket_path, + join_handle: RwLock::new(None), + stop_write: sender, + }); + let event_loop_arc_captured = event_loop_arc.clone(); let join_handle = thread::Builder::new() .name("event_loop".to_owned()) .spawn(move || -> Result<()> { + let event_loop_arc = event_loop_arc_captured; let mut clients: Slab>> = Slab::new(); let mut poll = Poll::new()?; let mut events = Events::with_capacity(1024); @@ -46,7 +54,8 @@ impl EventLoop { Token(client_number), Interest::READABLE, )?; - let client = Client::from_connection(socket); + let client = + Client::from_connection(socket, &event_loop_arc); *clients.get_mut(client_number).unwrap() = Some(client); } Err(e) => { @@ -74,11 +83,12 @@ impl EventLoop { } }) .ok(); - Ok(EventLoop { - socket_path, - join_handle, - stop_write: sender, - }) + event_loop_arc.set_join_handle(join_handle); + Ok(event_loop_arc) + } + + fn set_join_handle(&self, handle: Option>>) { + *self.join_handle.write().unwrap() = handle; } } @@ -88,8 +98,10 @@ impl Drop for EventLoop { let _ = self.stop_write.write(buf.as_slice()); let _ = self .join_handle - .take() - .map(|handle| handle.join()) + .get_mut() + .ok() + .and_then(|handle| handle.take()) + .and_then(|handle| handle.join().ok()) .expect("Couldn't join the event loop thread at drop"); } }