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: *const c_void = unsafe { ffi::sel_registerName(name.as_ptr().cast()).cast() };
self.ptr.store(ptr as *mut c_void, Ordering::Relaxed);
unsafe { Sel::from_ptr(ptr) }
} 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 let Some(cls) = unsafe { ptr.as_ref() } {
Some(cls)
} else {
let ptr: *const Class = unsafe { ffi::objc_getClass(name.as_ptr().cast()) }.cast();
self.ptr.store(ptr as *mut Class, Ordering::Relaxed);
unsafe { ptr.as_ref() }
}
}
}