use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
pub struct MemoryGuard<'a> {
locker: &'a AtomicBool,
buffer: *mut u8,
size: usize,
}
impl<'a> MemoryGuard<'a> {
pub fn buffer(&self) -> *mut u8 {
self.buffer
}
pub fn size(&self) -> usize {
self.size
}
}
impl<'a> Drop for MemoryGuard<'a> {
fn drop(&mut self) {
self.locker.store(false, SeqCst);
}
}
pub struct MemoryMutex {
buffer: *mut u8,
size: usize,
}
impl MemoryMutex {
pub const SIZE: usize = std::mem::size_of::<AtomicBool>();
pub unsafe fn new(buffer: *mut u8, size: usize) -> Self {
Self { buffer, size }
}
pub fn lock<'a>(&self) -> MemoryGuard<'a> {
let locker = unsafe { &*(self.buffer as *mut AtomicBool) };
while let Err(_) = locker.compare_exchange(false, true, SeqCst, SeqCst) {
core::hint::spin_loop();
}
MemoryGuard {
locker,
size: self.size - Self::SIZE,
buffer: unsafe { self.buffer.add(Self::SIZE) },
}
}
}