use super::traits::{TlsProvider, TlsSlotAccess};
use crate::ThreadAllocator;
use crate::tls_slot::LocalAllocatorSlot;
use mnemosyne_arena::HasSegmentPool;
pub struct StandardTls<B, S>(core::marker::PhantomData<(B, S)>);
impl<B: HasSegmentPool, S: TlsSlotAccess<B>> TlsProvider<B> for StandardTls<B, S> {
const IDENTIFIER: &'static str = "StandardTls";
#[inline(always)]
fn register_current_allocator_ptr(ptr: *mut core::ffi::c_void) {
S::get_cached_cell(|cell| cell.set(ptr));
}
#[inline(always)]
fn with_allocator<R>(f: impl FnOnce(&mut ThreadAllocator<B>) -> R) -> Option<R> {
S::slot_access_armed(f)
}
#[inline(always)]
unsafe fn with_allocator_unguarded<R>(
f: impl FnOnce(&mut ThreadAllocator<B>) -> R,
) -> Option<R> {
unsafe { S::slot_access_unguarded(f) }
}
#[inline(always)]
fn get_allocator_ptr() -> *mut core::ffi::c_void {
S::get_slot_standard(|slot| slot.allocator_ptr())
}
}
pub struct CachedCellTls<B, S>(core::marker::PhantomData<(B, S)>);
#[inline(always)]
fn init_cached_allocator_ptr<
const ARM_THREAD_EXIT: bool,
B: HasSegmentPool,
S: TlsSlotAccess<B>,
>() -> *mut core::ffi::c_void {
S::get_slot_standard(|slot| {
let alloc_ptr = slot.allocator_ptr();
S::get_cached_cell(|cell| cell.set(alloc_ptr));
if ARM_THREAD_EXIT {
S::arm_thread_exit(slot);
}
alloc_ptr
})
}
impl<B: HasSegmentPool, S: TlsSlotAccess<B>> TlsProvider<B> for CachedCellTls<B, S> {
const IDENTIFIER: &'static str = "CachedCellTls";
#[inline(always)]
fn register_current_allocator_ptr(ptr: *mut core::ffi::c_void) {
S::get_cached_cell(|cell| cell.set(ptr));
}
#[inline(always)]
fn with_allocator<R>(f: impl FnOnce(&mut ThreadAllocator<B>) -> R) -> Option<R> {
let ptr = S::get_cached_cell(|cell| cell.get());
if !ptr.is_null() {
unsafe { LocalAllocatorSlot::<B>::with_allocator(ptr, f) }
} else {
let alloc_ptr = init_cached_allocator_ptr::<true, B, S>();
unsafe { LocalAllocatorSlot::<B>::with_allocator(alloc_ptr, f) }
}
}
#[inline(always)]
unsafe fn with_allocator_unguarded<R>(
f: impl FnOnce(&mut ThreadAllocator<B>) -> R,
) -> Option<R> {
let ptr = S::get_cached_cell(|cell| cell.get());
if !ptr.is_null() {
unsafe { LocalAllocatorSlot::<B>::with_allocator_unguarded(ptr, f) }
} else {
let alloc_ptr = init_cached_allocator_ptr::<true, B, S>();
unsafe { LocalAllocatorSlot::<B>::with_allocator_unguarded(alloc_ptr, f) }
}
}
#[inline(always)]
fn get_allocator_ptr() -> *mut core::ffi::c_void {
let ptr = S::get_cached_cell(|cell| cell.get());
if !ptr.is_null() {
ptr
} else {
init_cached_allocator_ptr::<false, B, S>()
}
}
#[inline(always)]
fn get_allocator_ptr_raw() -> *mut core::ffi::c_void {
S::get_cached_cell(|cell| cell.get())
}
}