Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make EventLoopProxy Sync #3449

Merged
merged 2 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion examples/web_aspect_ratio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub fn main() {
#[cfg(web_platform)]
mod wasm {
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::HtmlCanvasElement;
use winit::{
dpi::PhysicalSize,
Expand Down
3 changes: 2 additions & 1 deletion src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/ios/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
2 changes: 0 additions & 2 deletions src/platform_impl/ios/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]

use std::convert::TryInto;

use icrate::Foundation::{NSInteger, NSUInteger};
use objc2::encode::{Encode, Encoding};

Expand Down
1 change: 0 additions & 1 deletion src/platform_impl/linux/common/xkb/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::convert::TryInto;
use std::ops::Deref;
use std::os::raw::c_char;
use std::ptr::{self, NonNull};
Expand Down
1 change: 0 additions & 1 deletion src/platform_impl/linux/wayland/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

use sctk::reexports::calloop;
use sctk::reexports::calloop::Error as CalloopError;
use sctk::reexports::calloop_wayland_source::WaylandSource;
use sctk::reexports::client::globals;
Expand Down
1 change: 0 additions & 1 deletion src/platform_impl/linux/wayland/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};

use sctk::reexports::calloop;
use sctk::reexports::client::protocol::wl_display::WlDisplay;
use sctk::reexports::client::protocol::wl_surface::WlSurface;
use sctk::reexports::client::Proxy;
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/linux/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::{ptr, slice, str};
use calloop::generic::Generic;
use calloop::EventLoop as Loop;
use calloop::{ping::Ping, Readiness};
use libc::{self, setlocale, LC_CTYPE};
use libc::{setlocale, LC_CTYPE};
use log::warn;

use x11rb::connection::RequestConnection;
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/macos/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 0 additions & 1 deletion src/platform_impl/macos/observer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::{
self,
ffi::c_void,
panic::{AssertUnwindSafe, UnwindSafe},
ptr,
Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/web/async/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>);

Expand Down Expand Up @@ -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>>,
}

Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/web/async/waker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
14 changes: 7 additions & 7 deletions src/platform_impl/web/async/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion src/platform_impl/web/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use crate::window::WindowId;

use std::{
cell::{Cell, RefCell},
clone::Clone,
collections::{HashSet, VecDeque},
iter,
ops::Deref,
Expand Down
1 change: 0 additions & 1 deletion src/platform_impl/web/web_sys/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::keyboard::{Key, KeyLocation, ModifiersState, NamedKey, PhysicalKey};

use smol_str::SmolStr;
use std::cell::OnceCell;
use std::convert::TryInto;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::{KeyboardEvent, MouseEvent, PointerEvent, WheelEvent};
Expand Down
2 changes: 1 addition & 1 deletion tests/send_objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>();
}
}
Expand Down
9 changes: 9 additions & 0 deletions tests/sync_object.rs
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
Loading