Skip to content

Commit

Permalink
Use a normal static and some unsafe instead of a thread local
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Aug 11, 2024
1 parent 1030703 commit 53f7c34
Showing 1 changed file with 23 additions and 14 deletions.
37 changes: 23 additions & 14 deletions src/platform_impl/apple/appkit/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,22 @@ pub(super) struct AppState {
}

// TODO(madsmtm): Use `MainThreadBound` once that is possible in `static`s.
thread_local! {
static GLOBAL: OnceCell<Rc<AppState>> = const { OnceCell::new() };
struct StaticMainThreadBound<T>(T);

impl<T> StaticMainThreadBound<T> {
const fn get(&self, _mtm: MainThreadMarker) -> &T {
&self.0
}
}

unsafe impl<T> Send for StaticMainThreadBound<T> {}
unsafe impl<T> Sync for StaticMainThreadBound<T> {}

// SAFETY: Creating `StaticMainThreadBound` in a `const` context, where there is no concept of the
// main thread.
static GLOBAL: StaticMainThreadBound<OnceCell<Rc<AppState>>> =
const { StaticMainThreadBound(OnceCell::new()) };

impl AppState {
pub(super) fn setup_global(
mtm: MainThreadMarker,
Expand Down Expand Up @@ -79,13 +91,18 @@ impl AppState {
pending_redraw: RefCell::new(vec![]),
});

GLOBAL.with(|key: &OnceCell<Rc<AppState>>| {
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<Self> {
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<Self>, _notification: &NSNotification) {
Expand Down Expand Up @@ -135,14 +152,6 @@ impl AppState {
self.internal_exit();
}

pub fn get(mtm: MainThreadMarker) -> Rc<Self> {
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"))
})
}

/// Place the event handler in the application state for the duration
/// of the given closure.
pub fn set_event_handler<R>(
Expand Down

0 comments on commit 53f7c34

Please sign in to comment.