From 3e991e13dc07be89748b8c97006e100b9027f306 Mon Sep 17 00:00:00 2001 From: Rodrigo Batista de Moraes <51273772+Rodrigodd@users.noreply.github.com> Date: Wed, 20 Jul 2022 14:52:36 -0300 Subject: [PATCH] Android: avoid deadlocks while handling UserEvent (#2343) Replace `Arc>` by `mpsc` --- src/platform_impl/android/mod.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 405130fc..65e1a8cf 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -2,7 +2,7 @@ use std::{ collections::VecDeque, - sync::{Arc, Mutex, RwLock}, + sync::{mpsc, RwLock}, time::{Duration, Instant}, }; @@ -235,7 +235,8 @@ fn poll(poll: Poll) -> Option { pub struct EventLoop { window_target: event_loop::EventLoopWindowTarget, - user_queue: Arc>>, + user_events_sender: mpsc::Sender, + user_events_receiver: mpsc::Receiver, first_event: Option, start_cause: event::StartCause, looper: ThreadLooper, @@ -258,6 +259,7 @@ macro_rules! call_event_handler { impl EventLoop { pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Self { + let (user_events_sender, user_events_receiver) = mpsc::channel(); Self { window_target: event_loop::EventLoopWindowTarget { p: EventLoopWindowTarget { @@ -265,7 +267,8 @@ impl EventLoop { }, _marker: std::marker::PhantomData, }, - user_queue: Default::default(), + user_events_sender, + user_events_receiver, first_event: None, start_cause: event::StartCause::Init, looper: ThreadLooper::for_thread().unwrap(), @@ -493,8 +496,9 @@ impl EventLoop { } } Some(EventSource::User) => { - let mut user_queue = self.user_queue.lock().unwrap(); - while let Some(event) = user_queue.pop_front() { + // try_recv only errors when empty (expected) or disconnect. But because Self + // contains a Sender it will never disconnect, so no error handling need. + while let Ok(event) = self.user_events_receiver.try_recv() { call_event_handler!( event_handler, self.window_target(), @@ -595,20 +599,22 @@ impl EventLoop { pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { - queue: self.user_queue.clone(), + user_events_sender: self.user_events_sender.clone(), looper: ForeignLooper::for_thread().expect("called from event loop thread"), } } } pub struct EventLoopProxy { - queue: Arc>>, + user_events_sender: mpsc::Sender, looper: ForeignLooper, } impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed> { - self.queue.lock().unwrap().push_back(event); + self.user_events_sender + .send(event) + .map_err(|mpsc::SendError(x)| event_loop::EventLoopClosed(x))?; self.looper.wake(); Ok(()) } @@ -617,7 +623,7 @@ impl EventLoopProxy { impl Clone for EventLoopProxy { fn clone(&self) -> Self { EventLoopProxy { - queue: self.queue.clone(), + user_events_sender: self.user_events_sender.clone(), looper: self.looper.clone(), } }