use core::ffi::c_void;
use core::ptr;
use core::sync::atomic::{AtomicPtr, Ordering};
use crate::ffi;
use crate::runtime::{Class, Sel};
#[doc(hidden)]
pub struct CachedSel {
ptr: AtomicPtr<c_void>,
}
impl CachedSel {
pub const fn new() -> CachedSel {
CachedSel {
ptr: AtomicPtr::new(ptr::null_mut()),
}
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn get(&self, name: &str) -> Sel {
let ptr = self.ptr.load(Ordering::Relaxed);
if ptr.is_null() {
let ptr = unsafe { ffi::sel_registerName(name.as_ptr() as *const _) };
self.ptr.store(ptr as *mut _, Ordering::Relaxed);
unsafe { Sel::from_ptr(ptr as *const _) }
} else {
unsafe { Sel::from_ptr(ptr) }
}
}
}
#[doc(hidden)]
pub struct CachedClass {
ptr: AtomicPtr<Class>,
}
impl CachedClass {
pub const fn new() -> CachedClass {
CachedClass {
ptr: AtomicPtr::new(ptr::null_mut()),
}
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn get(&self, name: &str) -> Option<&'static Class> {
let ptr = self.ptr.load(Ordering::Relaxed);
if ptr.is_null() {
let cls = unsafe { ffi::objc_getClass(name.as_ptr() as *const _) } as *const Class;
self.ptr.store(cls as *mut _, Ordering::Relaxed);
unsafe { cls.as_ref() }
} else {
Some(unsafe { &*ptr })
}
}
}