use core::marker::PhantomData;
use std::{cell::Cell, ptr::NonNull};
use crate::world::WorldLocal;
std::thread_local! {
static WORLD_TLS: Cell<Option<NonNull<WorldLocal>>> = const { Cell::new(None) };
}
pub struct Guard<'a> {
#[cfg(debug_assertions)]
this: NonNull<WorldLocal>,
prev: Option<NonNull<WorldLocal>>,
marker: PhantomData<&'a mut WorldLocal>,
}
impl<'a> Guard<'a> {
pub fn new(world: &'a mut WorldLocal) -> Self {
let this = NonNull::from(world);
let prev = WORLD_TLS.with(|tls| tls.replace(Some(this)));
Guard {
#[cfg(debug_assertions)]
this,
prev,
marker: PhantomData,
}
}
}
impl Drop for Guard<'_> {
fn drop(&mut self) {
WORLD_TLS.with(|tls| {
#[cfg(debug_assertions)]
assert_eq!(tls.get(), Some(self.this));
tls.set(self.prev)
});
}
}
pub unsafe fn try_get_world_ref<'a>() -> Option<&'a WorldLocal> {
WORLD_TLS.with(|tls| unsafe { tls.get().map(|w| w.as_ref()) })
}
pub unsafe fn try_get_world_mut<'a>() -> Option<&'a mut WorldLocal> {
WORLD_TLS.with(|tls| unsafe { tls.get().map(|mut w| w.as_mut()) })
}
pub unsafe fn get_world_ref<'a>() -> &'a WorldLocal {
WORLD_TLS.with(|tls| unsafe { tls.get().unwrap_unchecked().as_ref() })
}
pub unsafe fn get_world_mut<'a>() -> &'a mut WorldLocal {
WORLD_TLS.with(|tls| unsafe { tls.get().unwrap_unchecked().as_mut() })
}