From 31f8b816bda59c3d1a61d980ff67b7ca1d96b4eb Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 1 Feb 2024 14:27:44 +0100 Subject: [PATCH] Make `EventLoopProxy` Sync Co-authored-by: daxpedda Closes: #3448 --- CHANGELOG.md | 1 + src/event_loop.rs | 3 ++- src/platform_impl/ios/event_loop.rs | 1 + src/platform_impl/macos/event_loop.rs | 1 + src/platform_impl/web/async/dispatcher.rs | 4 ++-- src/platform_impl/web/async/waker.rs | 4 ++-- src/platform_impl/web/async/wrapper.rs | 14 +++++++------- tests/send_objects.rs | 2 +- tests/sync_object.rs | 9 +++++++++ 9 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77696402..8e12b62c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Unreleased` header. - On X11, don't require XIM to run. - On X11, fix xkb state not being updated correctly sometimes leading to wrong input. - Fix compatibility with 32-bit platforms without 64-bit atomics. +- Implement `Sync` for `EventLoopProxy`. - On X11, fix swapped instance and general class names. - **Breaking:** Removed unnecessary generic parameter `T` from `EventLoopWindowTarget`. - On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example. diff --git a/src/event_loop.rs b/src/event_loop.rs index ad2bfa59..b8dd1a21 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -253,7 +253,8 @@ impl EventLoop { self.event_loop.run(event_handler) } - /// Creates an [`EventLoopProxy`] that can be used to dispatch user events to the main event loop. + /// Creates an [`EventLoopProxy`] that can be used to dispatch user events + /// to the main event loop, possibly from another thread. pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { event_loop_proxy: self.event_loop.create_proxy(), diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index cf69eec5..1df992cc 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -229,6 +229,7 @@ pub struct EventLoopProxy { } unsafe impl Send for EventLoopProxy {} +unsafe impl Sync for EventLoopProxy {} impl Clone for EventLoopProxy { fn clone(&self) -> EventLoopProxy { diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 32cc1990..59c6e2b4 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -532,6 +532,7 @@ pub struct EventLoopProxy { } unsafe impl Send for EventLoopProxy {} +unsafe impl Sync for EventLoopProxy {} impl Drop for EventLoopProxy { fn drop(&mut self) { diff --git a/src/platform_impl/web/async/dispatcher.rs b/src/platform_impl/web/async/dispatcher.rs index f7307d9f..a83d4ab2 100644 --- a/src/platform_impl/web/async/dispatcher.rs +++ b/src/platform_impl/web/async/dispatcher.rs @@ -5,7 +5,7 @@ use std::{ sync::{Arc, Condvar, Mutex}, }; -pub struct Dispatcher(Wrapper>, Closure>); +pub struct Dispatcher(Wrapper>, Closure>); struct Closure(Box); @@ -85,7 +85,7 @@ impl Dispatcher { } pub struct DispatchRunner { - wrapper: Wrapper>, Closure>, + wrapper: Wrapper>, Closure>, receiver: Receiver>, } diff --git a/src/platform_impl/web/async/waker.rs b/src/platform_impl/web/async/waker.rs index fd8733af..8280e13d 100644 --- a/src/platform_impl/web/async/waker.rs +++ b/src/platform_impl/web/async/waker.rs @@ -6,9 +6,9 @@ use std::task::Poll; use super::super::main_thread::MainThreadMarker; use super::{AtomicWaker, Wrapper}; -pub struct WakerSpawner(Wrapper, Sender, usize>); +pub struct WakerSpawner(Wrapper, Sender, usize>); -pub struct Waker(Wrapper, Sender, usize>); +pub struct Waker(Wrapper, Sender, usize>); struct Handler { value: T, diff --git a/src/platform_impl/web/async/wrapper.rs b/src/platform_impl/web/async/wrapper.rs index d8b05c71..1825df13 100644 --- a/src/platform_impl/web/async/wrapper.rs +++ b/src/platform_impl/web/async/wrapper.rs @@ -6,14 +6,14 @@ use std::sync::Arc; // Unsafe wrapper type that allows us to use `T` when it's not `Send` from other threads. // `value` **must** only be accessed on the main thread. -pub struct Wrapper { - value: Value, +pub struct Wrapper { + value: Value, handler: fn(&RefCell>, E), sender_data: S, sender_handler: fn(&S, E), } -struct Value { +struct Value { // SAFETY: // This value must not be accessed if not on the main thread. // @@ -28,11 +28,11 @@ struct Value { } // SAFETY: See `Self::value`. -unsafe impl Send for Value {} +unsafe impl Send for Value {} // SAFETY: See `Self::value`. -unsafe impl Sync for Value {} +unsafe impl Sync for Value {} -impl Wrapper { +impl Wrapper { #[track_caller] pub fn new>( _: MainThreadMarker, @@ -81,7 +81,7 @@ impl Wrapper { } } -impl Clone for Wrapper { +impl Clone for Wrapper { fn clone(&self) -> Self { Self { value: Value { diff --git a/tests/send_objects.rs b/tests/send_objects.rs index 0a5d1a9e..a238d5bb 100644 --- a/tests/send_objects.rs +++ b/tests/send_objects.rs @@ -5,7 +5,7 @@ fn needs_send() {} fn event_loop_proxy_send() { #[allow(dead_code)] fn is_send() { - // ensures that `winit::EventLoopProxy` implements `Send` + // ensures that `winit::EventLoopProxy` implements `Send` needs_send::>(); } } diff --git a/tests/sync_object.rs b/tests/sync_object.rs index 8500ac5f..7740b8fc 100644 --- a/tests/sync_object.rs +++ b/tests/sync_object.rs @@ -1,6 +1,15 @@ #[allow(dead_code)] fn needs_sync() {} +#[test] +fn event_loop_proxy_send() { + #[allow(dead_code)] + fn is_send() { + // ensures that `winit::EventLoopProxy` implements `Sync` + needs_sync::>(); + } +} + #[test] fn window_sync() { // ensures that `winit::Window` implements `Sync`