diff --git a/CHANGELOG.md b/CHANGELOG.md index 31bc55b5f2..77e959abc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ And please only add new entries to the top of this list, right below the `# Unre - Bump MSRV from `1.60` to `1.64`. - On macOS, fixed potential panic when getting refresh rate. - On macOS, fix crash when calling `Window::set_ime_position` from another thread. +- On all platforms except Web, implement `Sync` for `EventLoopProxy`. # 0.28.3 diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 2e1924e27b..33f36d8488 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -5,7 +5,7 @@ use std::{ hash::Hash, sync::{ atomic::{AtomicBool, Ordering}, - mpsc, Arc, RwLock, + mpsc, Arc, Mutex, RwLock, }, time::{Duration, Instant}, }; @@ -788,21 +788,21 @@ impl EventLoop { pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { - user_events_sender: self.user_events_sender.clone(), + user_events_sender: Mutex::new(self.user_events_sender.clone()), waker: self.android_app.create_waker(), } } } pub struct EventLoopProxy { - user_events_sender: mpsc::Sender, + user_events_sender: Mutex>, waker: AndroidAppWaker, } impl Clone for EventLoopProxy { fn clone(&self) -> Self { EventLoopProxy { - user_events_sender: self.user_events_sender.clone(), + user_events_sender: Mutex::new(self.user_events_sender.lock().unwrap().clone()), waker: self.waker.clone(), } } @@ -811,6 +811,8 @@ impl Clone for EventLoopProxy { impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed> { self.user_events_sender + .lock() + .unwrap() .send(event) .map_err(|err| event_loop::EventLoopClosed(err.0))?; self.waker.wake(); diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index 8649c8c7a8..a3270a8715 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -5,6 +5,7 @@ use std::{ marker::PhantomData, ptr, sync::mpsc::{self, Receiver, Sender}, + sync::Mutex, }; use core_foundation::base::{CFIndex, CFRelease}; @@ -153,15 +154,16 @@ impl EventLoop { } pub struct EventLoopProxy { - sender: Sender, + sender: Mutex>, source: CFRunLoopSourceRef, } unsafe impl Send for EventLoopProxy {} +unsafe impl Sync for EventLoopProxy {} impl Clone for EventLoopProxy { fn clone(&self) -> EventLoopProxy { - EventLoopProxy::new(self.sender.clone()) + EventLoopProxy::new(self.sender.lock().unwrap().clone()) } } @@ -200,12 +202,17 @@ impl EventLoopProxy { CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); CFRunLoopWakeUp(rl); - EventLoopProxy { sender, source } + EventLoopProxy { + sender: Mutex::new(sender), + source, + } } } pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { self.sender + .lock() + .unwrap() .send(event) .map_err(|::std::sync::mpsc::SendError(x)| EventLoopClosed(x))?; unsafe { diff --git a/src/platform_impl/linux/wayland/event_loop/proxy.rs b/src/platform_impl/linux/wayland/event_loop/proxy.rs index dad64ef2c9..d1824285ac 100644 --- a/src/platform_impl/linux/wayland/event_loop/proxy.rs +++ b/src/platform_impl/linux/wayland/event_loop/proxy.rs @@ -1,6 +1,7 @@ //! An event loop proxy. use std::sync::mpsc::SendError; +use std::sync::Mutex; use sctk::reexports::calloop::channel::Sender; @@ -8,24 +9,28 @@ use crate::event_loop::EventLoopClosed; /// A handle that can be sent across the threads and used to wake up the `EventLoop`. pub struct EventLoopProxy { - user_events_sender: Sender, + user_events_sender: Mutex>, } impl Clone for EventLoopProxy { fn clone(&self) -> Self { EventLoopProxy { - user_events_sender: self.user_events_sender.clone(), + user_events_sender: Mutex::new(self.user_events_sender.lock().unwrap().clone()), } } } impl EventLoopProxy { pub fn new(user_events_sender: Sender) -> Self { - Self { user_events_sender } + Self { + user_events_sender: Mutex::new(user_events_sender), + } } pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { self.user_events_sender + .lock() + .unwrap() .send(event) .map_err(|SendError(error)| EventLoopClosed(error)) } diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 0ef073d9e4..e825ff503e 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -28,8 +28,11 @@ use std::{ ptr, rc::Rc, slice, - sync::mpsc::{Receiver, Sender, TryRecvError}, sync::{mpsc, Arc, Weak}, + sync::{ + mpsc::{Receiver, Sender, TryRecvError}, + Mutex, + }, time::{Duration, Instant}, }; @@ -123,14 +126,14 @@ pub struct EventLoop { } pub struct EventLoopProxy { - user_sender: Sender, + user_sender: Mutex>, waker: Arc, } impl Clone for EventLoopProxy { fn clone(&self) -> Self { EventLoopProxy { - user_sender: self.user_sender.clone(), + user_sender: Mutex::new(self.user_sender.lock().unwrap().clone()), waker: self.waker.clone(), } } @@ -294,7 +297,7 @@ impl EventLoop { pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { - user_sender: self.user_sender.clone(), + user_sender: Mutex::new(self.user_sender.clone()), waker: self.waker.clone(), } } @@ -578,6 +581,8 @@ impl EventLoopWindowTarget { impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { self.user_sender + .lock() + .unwrap() .send(event) .map_err(|e| EventLoopClosed(e.0)) .map(|_| self.waker.wake().unwrap()) diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 72434ac478..5409ff83b4 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -8,7 +8,7 @@ use std::{ panic::{catch_unwind, resume_unwind, RefUnwindSafe, UnwindSafe}, process, ptr, rc::{Rc, Weak}, - sync::mpsc, + sync::{mpsc, Mutex}, }; use core_foundation::base::{CFIndex, CFRelease}; @@ -264,11 +264,12 @@ pub fn stop_app_on_panic R + UnwindSafe, R>( } pub struct EventLoopProxy { - sender: mpsc::Sender, + sender: Mutex>, source: CFRunLoopSourceRef, } unsafe impl Send for EventLoopProxy {} +unsafe impl Sync for EventLoopProxy {} impl Drop for EventLoopProxy { fn drop(&mut self) { @@ -280,7 +281,7 @@ impl Drop for EventLoopProxy { impl Clone for EventLoopProxy { fn clone(&self) -> Self { - EventLoopProxy::new(self.sender.clone()) + EventLoopProxy::new(self.sender.lock().unwrap().clone()) } } @@ -310,12 +311,17 @@ impl EventLoopProxy { CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); CFRunLoopWakeUp(rl); - EventLoopProxy { sender, source } + EventLoopProxy { + sender: Mutex::new(sender), + source, + } } } pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { self.sender + .lock() + .unwrap() .send(event) .map_err(|mpsc::SendError(x)| EventLoopClosed(x))?; unsafe { diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index f0ad43d5b3..db18b09e7d 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -648,20 +648,22 @@ impl EventLoop { pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { - user_events_sender: self.window_target.p.user_events_sender.clone(), + user_events_sender: Mutex::new(self.window_target.p.user_events_sender.clone()), wake_socket: self.window_target.p.wake_socket.clone(), } } } pub struct EventLoopProxy { - user_events_sender: mpsc::Sender, + user_events_sender: Mutex>, wake_socket: Arc, } impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed> { self.user_events_sender + .lock() + .unwrap() .send(event) .map_err(|mpsc::SendError(x)| event_loop::EventLoopClosed(x))?; @@ -674,7 +676,7 @@ impl EventLoopProxy { impl Clone for EventLoopProxy { fn clone(&self) -> Self { Self { - user_events_sender: self.user_events_sender.clone(), + user_events_sender: Mutex::new(self.user_events_sender.lock().unwrap().clone()), wake_socket: self.wake_socket.clone(), } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 6d5f9d44a5..14c80d3c90 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -306,7 +306,7 @@ impl EventLoop { pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { target_window: self.window_target.p.thread_msg_target, - event_send: self.thread_msg_sender.clone(), + event_send: Mutex::new(self.thread_msg_sender.clone()), } } } @@ -575,7 +575,7 @@ type ThreadExecFn = Box>; pub struct EventLoopProxy { target_window: HWND, - event_send: Sender, + event_send: Mutex>, } unsafe impl Send for EventLoopProxy {} @@ -583,7 +583,7 @@ impl Clone for EventLoopProxy { fn clone(&self) -> Self { Self { target_window: self.target_window, - event_send: self.event_send.clone(), + event_send: Mutex::new(self.event_send.lock().unwrap().clone()), } } } @@ -592,7 +592,7 @@ impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { unsafe { if PostMessageW(self.target_window, USER_EVENT_MSG_ID.get(), 0, 0) != false.into() { - self.event_send.send(event).ok(); + self.event_send.lock().unwrap().send(event).ok(); Ok(()) } else { Err(EventLoopClosed(event)) diff --git a/tests/sync_object.rs b/tests/sync_object.rs index 80be177352..08d041f640 100644 --- a/tests/sync_object.rs +++ b/tests/sync_object.rs @@ -1,6 +1,16 @@ #[allow(dead_code)] fn needs_sync() {} +#[cfg(not(wasm_platform))] +#[test] +fn event_loop_proxy_send() { + #[allow(dead_code)] + fn is_send() { + // ensures that `winit::EventLoopProxy` implements `Sync` + needs_sync::>(); + } +} + #[cfg(not(wasm_platform))] #[test] fn window_sync() {