use core::mem::ManuallyDrop;
use core::ptr;
use core::sync::atomic::{AtomicPtr, Ordering};
use objc2::rc::Retained;
use objc2::Message;
#[derive(Debug)]
pub struct CachedId<T> {
ptr: AtomicPtr<T>,
}
impl<T> CachedId<T> {
#[allow(clippy::new_without_default)]
pub const fn new() -> Self {
Self {
ptr: AtomicPtr::new(ptr::null_mut()),
}
}
}
impl<T: Message> CachedId<T> {
#[inline]
pub fn get(&self, f: impl FnOnce() -> Retained<T>) -> &'static T {
let ptr = self.ptr.load(Ordering::SeqCst);
unsafe { ptr.as_ref() }.unwrap_or_else(|| {
let s = ManuallyDrop::new(f());
let ptr = Retained::as_ptr(&s);
self.ptr.store(ptr as *mut T, Ordering::SeqCst);
unsafe { ptr.as_ref().unwrap_unchecked() }
})
}
}