From 229029f2da1156f5ef6c2a556575e7685cb6bfa1 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Wed, 18 Oct 2017 20:40:21 +0200 Subject: [PATCH] Formalize thread-safety guarantees (#322) --- CHANGELOG.md | 2 ++ src/lib.rs | 7 +++++++ src/os/unix.rs | 10 ++++++++-- tests/events_loop_proxy_send.rs | 8 -------- tests/send_objects.rs | 23 +++++++++++++++++++++++ 5 files changed, 40 insertions(+), 10 deletions(-) delete mode 100644 tests/events_loop_proxy_send.rs create mode 100644 tests/send_objects.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cfa5bdc..62d62ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Added method `MonitorId::get_hidpi_factor`. - Deprecated `get_inner_size_pixels` and `get_inner_size_points` methods of `Window` in favor of `get_inner_size`. +- **Breaking:** `EventsLoop` is `!Send` and `!Sync` because of platform-dependant constraints, + but `Window`, `WindowId`, `DeviceId` and `MonitorId` guaranteed to be `Send`. # Version 0.8.3 (2017-10-11) diff --git a/src/lib.rs b/src/lib.rs index 165713ff..90653659 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,8 +167,14 @@ pub struct DeviceId(platform::DeviceId); /// an events loop opens a connection to the X or Wayland server. /// /// To wake up an `EventsLoop` from a another thread, see the `EventsLoopProxy` docs. +/// +/// Note that the `EventsLoop` cannot be shared accross threads (due to platform-dependant logic +/// forbiding it), as such it is neither `Send` nor `Sync`. If you need cross-thread access, the +/// `Window` created from this `EventsLoop` _can_ be sent to an other thread, and the +/// `EventsLoopProxy` allows you to wakeup an `EventsLoop` from an other thread. pub struct EventsLoop { events_loop: platform::EventsLoop, + _marker: ::std::marker::PhantomData<*mut ()> // Not Send nor Sync } /// Returned by the user callback given to the `EventsLoop::run_forever` method. @@ -192,6 +198,7 @@ impl EventsLoop { pub fn new() -> EventsLoop { EventsLoop { events_loop: platform::EventsLoop::new(), + _marker: ::std::marker::PhantomData, } } diff --git a/src/os/unix.rs b/src/os/unix.rs index e743e426..e6d43628 100644 --- a/src/os/unix.rs +++ b/src/os/unix.rs @@ -41,7 +41,12 @@ pub trait EventsLoopExt { impl EventsLoopExt for EventsLoop { #[inline] fn new_x11() -> Result { - LinuxEventsLoop::new_x11().map(|ev| EventsLoop { events_loop: ev }) + LinuxEventsLoop::new_x11().map(|ev| + EventsLoop { + events_loop: ev, + _marker: ::std::marker::PhantomData, + } + ) } #[inline] @@ -50,7 +55,8 @@ impl EventsLoopExt for EventsLoop { events_loop: match LinuxEventsLoop::new_wayland() { Ok(e) => e, Err(_) => panic!() // TODO: propagate - } + }, + _marker: ::std::marker::PhantomData, } } diff --git a/tests/events_loop_proxy_send.rs b/tests/events_loop_proxy_send.rs deleted file mode 100644 index 5c44aa13..00000000 --- a/tests/events_loop_proxy_send.rs +++ /dev/null @@ -1,8 +0,0 @@ -extern crate winit; - -#[test] -fn events_loop_proxy_send() { - // ensures that `winit::EventsLoopProxy` implements `Send` - fn needs_send() {} - needs_send::(); -} diff --git a/tests/send_objects.rs b/tests/send_objects.rs new file mode 100644 index 00000000..f3328c10 --- /dev/null +++ b/tests/send_objects.rs @@ -0,0 +1,23 @@ +extern crate winit; + +fn needs_send() {} + +#[test] +fn events_loop_proxy_send() { + // ensures that `winit::EventsLoopProxy` implements `Send` + needs_send::(); +} + +#[test] +fn window_send() { + // ensures that `winit::Window` implements `Send` + needs_send::(); +} + +#[test] +fn ids_send() { + // ensures that the various `..Id` types implement `Send` + needs_send::(); + needs_send::(); + needs_send::(); +}