Closed superlou closed 1 year ago
One approach seems to be putting it in a mutex:
impl WindowHandler<String> for SignWindowHandler {
fn on_start(
&mut self,
helper: &mut WindowHelper<String>,
info: speedy2d::window::WindowStartupInfo
) {
let sender = helper.create_user_event_sender();
let sender_mutex = Mutex::new(sender);
thread::spawn(move || {
rouille::start_server("0.0.0.0:3000", move |_request| {
sender_mutex.lock().unwrap().send_event("Test".to_owned()).unwrap();
Response::text("Hello, world!")
});
});
}
This agrees with the Rouille docs, but is thatf how UserEventSender is expected to behave?
Thanks for the question! The issue is that rouille::start_server
may call the provided request handler (move |_request| {...
) from lots of different threads, and so everything in the handler needs to be Sync
.
UserEventSender
is Send
but not Sync
, which means you can pass it between threads, but you can't have one UserEventSender
shared between threads by reference (which is what's happening here).
The mutex is probably the best solution here IMO.
I get a bit nervous when I start doing lots of wrapping, but that explanation makes a lot of sense. Plus, to be able to get information from the WindowHandler to the server, I'll need to also get comfortable with wrapping things in Arc<Mutex<_>>
, which seems to be the Sync equivalent of Rc<RefCell<_>>
. Something like:
impl WindowHandler<String> for SignWindowHandler {
fn on_start(&mut self, helper: &mut WindowHelper<String>, _info: WindowStartupInfo) {
let sender = helper.create_user_event_sender();
crate::server::start_server(&self, Mutex::new(sender));
}
...
pub fn start_server(handler: &SignWindowHandler, sender: Mutex<UserEventSender<String>>) {
let path = handler.root_path.clone();
thread::spawn(move || {
rouille::start_server("0.0.0.0:3000", move |_request| {
sender.lock().unwrap().send_event("Test".to_owned()).unwrap();
let path_str = path.lock().unwrap();
Response::text(path_str.to_str().unwrap())
});
});
}
I probably have a hidden type that's something like ApplicationState which is owned by the SignWindowHandler, but this seems to work for now. Thanks!
I'm trying to tie a web server and a
WindowHandler
together, so that the web server can send events to theWindowHandler
as well as return status information. I'm using Rouille, since it seemed like a syncrhonous server would be easier to integrate. I followed the user event example, which seems to be the right way to communicate between two threads, and I can see that does seem to work:However, when I try to pass the
UserEventSender
to Rouille, I receive an error that the sender cannot be shared between threads safely:Is there a better approach for communicating between threads? In both cases, I believe the closure captures the sender, and
UserEventSender
implements Send and Sync.