Make EventLoopProxy Sync

Co-authored-by: daxpedda <daxpedda@gmail.com>
Closes: #3448
This commit is contained in:
Mads Marquart 2024-02-01 14:27:44 +01:00 committed by Kirill Chibisov
parent e61a7320a2
commit 31f8b816bd
9 changed files with 26 additions and 13 deletions

View file

@ -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<T: Send>`.
- 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.

View file

@ -253,7 +253,8 @@ impl<T> EventLoop<T> {
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<T> {
EventLoopProxy {
event_loop_proxy: self.event_loop.create_proxy(),

View file

@ -229,6 +229,7 @@ pub struct EventLoopProxy<T> {
}
unsafe impl<T: Send> Send for EventLoopProxy<T> {}
unsafe impl<T: Send> Sync for EventLoopProxy<T> {}
impl<T> Clone for EventLoopProxy<T> {
fn clone(&self) -> EventLoopProxy<T> {

View file

@ -532,6 +532,7 @@ pub struct EventLoopProxy<T> {
}
unsafe impl<T: Send> Send for EventLoopProxy<T> {}
unsafe impl<T: Send> Sync for EventLoopProxy<T> {}
impl<T> Drop for EventLoopProxy<T> {
fn drop(&mut self) {

View file

@ -5,7 +5,7 @@ use std::{
sync::{Arc, Condvar, Mutex},
};
pub struct Dispatcher<T: 'static>(Wrapper<true, T, Sender<Closure<T>>, Closure<T>>);
pub struct Dispatcher<T: 'static>(Wrapper<T, Sender<Closure<T>>, Closure<T>>);
struct Closure<T>(Box<dyn FnOnce(&T) + Send>);
@ -85,7 +85,7 @@ impl<T> Dispatcher<T> {
}
pub struct DispatchRunner<T: 'static> {
wrapper: Wrapper<true, T, Sender<Closure<T>>, Closure<T>>,
wrapper: Wrapper<T, Sender<Closure<T>>, Closure<T>>,
receiver: Receiver<Closure<T>>,
}

View file

@ -6,9 +6,9 @@ use std::task::Poll;
use super::super::main_thread::MainThreadMarker;
use super::{AtomicWaker, Wrapper};
pub struct WakerSpawner<T: 'static>(Wrapper<false, Handler<T>, Sender, usize>);
pub struct WakerSpawner<T: 'static>(Wrapper<Handler<T>, Sender, usize>);
pub struct Waker<T: 'static>(Wrapper<false, Handler<T>, Sender, usize>);
pub struct Waker<T: 'static>(Wrapper<Handler<T>, Sender, usize>);
struct Handler<T> {
value: T,

View file

@ -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<const SYNC: bool, V: 'static, S: Clone + Send, E> {
value: Value<SYNC, V>,
pub struct Wrapper<V: 'static, S: Clone + Send, E> {
value: Value<V>,
handler: fn(&RefCell<Option<V>>, E),
sender_data: S,
sender_handler: fn(&S, E),
}
struct Value<const SYNC: bool, V> {
struct Value<V> {
// SAFETY:
// This value must not be accessed if not on the main thread.
//
@ -28,11 +28,11 @@ struct Value<const SYNC: bool, V> {
}
// SAFETY: See `Self::value`.
unsafe impl<const SYNC: bool, V> Send for Value<SYNC, V> {}
unsafe impl<V> Send for Value<V> {}
// SAFETY: See `Self::value`.
unsafe impl<V> Sync for Value<true, V> {}
unsafe impl<V> Sync for Value<V> {}
impl<const SYNC: bool, V, S: Clone + Send, E> Wrapper<SYNC, V, S, E> {
impl<V, S: Clone + Send, E> Wrapper<V, S, E> {
#[track_caller]
pub fn new<R: Future<Output = ()>>(
_: MainThreadMarker,
@ -81,7 +81,7 @@ impl<const SYNC: bool, V, S: Clone + Send, E> Wrapper<SYNC, V, S, E> {
}
}
impl<const SYNC: bool, V, S: Clone + Send, E> Clone for Wrapper<SYNC, V, S, E> {
impl<V, S: Clone + Send, E> Clone for Wrapper<V, S, E> {
fn clone(&self) -> Self {
Self {
value: Value {

View file

@ -5,7 +5,7 @@ fn needs_send<T: Send>() {}
fn event_loop_proxy_send() {
#[allow(dead_code)]
fn is_send<T: 'static + Send>() {
// ensures that `winit::EventLoopProxy` implements `Send`
// ensures that `winit::EventLoopProxy<T: Send>` implements `Send`
needs_send::<winit::event_loop::EventLoopProxy<T>>();
}
}

View file

@ -1,6 +1,15 @@
#[allow(dead_code)]
fn needs_sync<T: Sync>() {}
#[test]
fn event_loop_proxy_send() {
#[allow(dead_code)]
fn is_send<T: 'static + Send>() {
// ensures that `winit::EventLoopProxy<T: Send>` implements `Sync`
needs_sync::<winit::event_loop::EventLoopProxy<T>>();
}
}
#[test]
fn window_sync() {
// ensures that `winit::Window` implements `Sync`