Android: avoid deadlocks while handling UserEvent (#2343)

Replace `Arc<Mutex<VecDeque<T>>` by `mpsc`
This commit is contained in:
Rodrigo Batista de Moraes 2022-07-20 14:52:36 -03:00 committed by GitHub
parent 5397b53e04
commit 3e991e13dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -2,7 +2,7 @@
use std::{ use std::{
collections::VecDeque, collections::VecDeque,
sync::{Arc, Mutex, RwLock}, sync::{mpsc, RwLock},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -235,7 +235,8 @@ fn poll(poll: Poll) -> Option<EventSource> {
pub struct EventLoop<T: 'static> { pub struct EventLoop<T: 'static> {
window_target: event_loop::EventLoopWindowTarget<T>, window_target: event_loop::EventLoopWindowTarget<T>,
user_queue: Arc<Mutex<VecDeque<T>>>, user_events_sender: mpsc::Sender<T>,
user_events_receiver: mpsc::Receiver<T>,
first_event: Option<EventSource>, first_event: Option<EventSource>,
start_cause: event::StartCause, start_cause: event::StartCause,
looper: ThreadLooper, looper: ThreadLooper,
@ -258,6 +259,7 @@ macro_rules! call_event_handler {
impl<T: 'static> EventLoop<T> { impl<T: 'static> EventLoop<T> {
pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Self { pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Self {
let (user_events_sender, user_events_receiver) = mpsc::channel();
Self { Self {
window_target: event_loop::EventLoopWindowTarget { window_target: event_loop::EventLoopWindowTarget {
p: EventLoopWindowTarget { p: EventLoopWindowTarget {
@ -265,7 +267,8 @@ impl<T: 'static> EventLoop<T> {
}, },
_marker: std::marker::PhantomData, _marker: std::marker::PhantomData,
}, },
user_queue: Default::default(), user_events_sender,
user_events_receiver,
first_event: None, first_event: None,
start_cause: event::StartCause::Init, start_cause: event::StartCause::Init,
looper: ThreadLooper::for_thread().unwrap(), looper: ThreadLooper::for_thread().unwrap(),
@ -493,8 +496,9 @@ impl<T: 'static> EventLoop<T> {
} }
} }
Some(EventSource::User) => { Some(EventSource::User) => {
let mut user_queue = self.user_queue.lock().unwrap(); // try_recv only errors when empty (expected) or disconnect. But because Self
while let Some(event) = user_queue.pop_front() { // 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!( call_event_handler!(
event_handler, event_handler,
self.window_target(), self.window_target(),
@ -595,20 +599,22 @@ impl<T: 'static> EventLoop<T> {
pub fn create_proxy(&self) -> EventLoopProxy<T> { pub fn create_proxy(&self) -> EventLoopProxy<T> {
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"), looper: ForeignLooper::for_thread().expect("called from event loop thread"),
} }
} }
} }
pub struct EventLoopProxy<T: 'static> { pub struct EventLoopProxy<T: 'static> {
queue: Arc<Mutex<VecDeque<T>>>, user_events_sender: mpsc::Sender<T>,
looper: ForeignLooper, looper: ForeignLooper,
} }
impl<T> EventLoopProxy<T> { impl<T> EventLoopProxy<T> {
pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed<T>> { pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed<T>> {
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(); self.looper.wake();
Ok(()) Ok(())
} }
@ -617,7 +623,7 @@ impl<T> EventLoopProxy<T> {
impl<T> Clone for EventLoopProxy<T> { impl<T> Clone for EventLoopProxy<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
EventLoopProxy { EventLoopProxy {
queue: self.queue.clone(), user_events_sender: self.user_events_sender.clone(),
looper: self.looper.clone(), looper: self.looper.clone(),
} }
} }