From 7e17899f9804d59290d941a6056d85baed4b9b2b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 14 Jul 2024 17:17:12 +0200 Subject: [PATCH] Use a normal static and some `unsafe` instead of a thread local --- src/platform_impl/apple/appkit/app_state.rs | 37 +++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/platform_impl/apple/appkit/app_state.rs b/src/platform_impl/apple/appkit/app_state.rs index 1b95db7525..9fffa9cfcd 100644 --- a/src/platform_impl/apple/appkit/app_state.rs +++ b/src/platform_impl/apple/appkit/app_state.rs @@ -47,10 +47,22 @@ pub(super) struct AppState { } // TODO(madsmtm): Use `MainThreadBound` once that is possible in `static`s. -thread_local! { - static GLOBAL: OnceCell> = const { OnceCell::new() }; +struct StaticMainThreadBound(T); + +impl StaticMainThreadBound { + const fn get(&self, _mtm: MainThreadMarker) -> &T { + &self.0 + } } +unsafe impl Send for StaticMainThreadBound {} +unsafe impl Sync for StaticMainThreadBound {} + +// SAFETY: Creating `StaticMainThreadBound` in a `const` context, where there is no concept of the +// main thread. +static GLOBAL: StaticMainThreadBound>> = + const { StaticMainThreadBound(OnceCell::new()) }; + impl AppState { pub(super) fn setup_global( mtm: MainThreadMarker, @@ -81,13 +93,18 @@ impl AppState { pending_redraw: RefCell::new(vec![]), }); - GLOBAL.with(|key: &OnceCell>| { - key.set(this.clone()).expect("application state can only be set once"); - }); - + GLOBAL.get(mtm).set(this.clone()).expect("application state can only be set once"); this } + pub fn get(mtm: MainThreadMarker) -> Rc { + GLOBAL + .get(mtm) + .get() + .expect("tried to get application state before it was registered") + .clone() + } + // NOTE: This notification will, globally, only be emitted once, // no matter how many `EventLoop`s the user creates. pub fn did_finish_launching(self: &Rc, _notification: &NSNotification) { @@ -137,14 +154,6 @@ impl AppState { self.internal_exit(); } - pub fn get(mtm: MainThreadMarker) -> Rc { - let _ = mtm; - GLOBAL.with(|s| { - // We hold `MainThreadMarker`, so this should always be set on this thread. - Rc::clone(s.get().expect("tried to get application state before it was registered")) - }) - } - pub fn mtm(&self) -> MainThreadMarker { self.mtm }