use core::cell::UnsafeCell;
use core::sync::atomic::{AtomicBool, Ordering};
use crate::Allocator;
struct Global {
ptr: UnsafeCell<Option<&'static dyn Allocator>>,
locked: AtomicBool,
}
unsafe impl Sync for Global {}
impl Global {
#[allow(dead_code)]
const fn new(allocator: &'static dyn Allocator) -> Self {
Self {
ptr: UnsafeCell::new(Some(allocator)),
locked: AtomicBool::new(false),
}
}
#[allow(dead_code)]
const fn none() -> Self {
Self {
ptr: UnsafeCell::new(None),
locked: AtomicBool::new(false),
}
}
fn get(&self) -> Option<&'static dyn Allocator> {
while self.locked.swap(true, Ordering::SeqCst) {
core::hint::spin_loop();
}
let allocator = unsafe { *self.ptr.get() };
self.locked.swap(false, Ordering::SeqCst);
allocator
}
fn set(&self, allocator: Option<&'static dyn Allocator>) {
while self.locked.swap(true, Ordering::SeqCst) {
core::hint::spin_loop();
}
unsafe { self.ptr.get().write(allocator) };
self.locked.swap(false, Ordering::SeqCst);
}
}
#[cfg(feature = "platform")]
static GLOBAL: Global = Global::new(&crate::platform::PLATFORM_ALLOCATOR);
#[cfg(not(feature = "platform"))]
static GLOBAL: Global = Global::none();
pub fn get() -> Option<&'static dyn Allocator> {
GLOBAL.get()
}
pub fn set(allocator: &'static dyn Allocator) {
GLOBAL.set(Some(allocator))
}