flize 4.2.3

non global, configurable and fast concurrent resource reclamation
Documentation
use crate::{Backoff, CachePadded};
use core::{
    cell::UnsafeCell,
    ops::{Deref, DerefMut},
    sync::atomic::{AtomicBool, Ordering},
};

const UNLOCKED: bool = false;
const LOCKED: bool = true;

pub struct Mutex<T> {
    state: CachePadded<AtomicBool>,
    data: UnsafeCell<T>,
}

impl<T> Mutex<T> {
    pub fn new(data: T) -> Self {
        Self {
            state: CachePadded::new(AtomicBool::new(UNLOCKED)),
            data: UnsafeCell::new(data),
        }
    }

    fn acquire(&self) {
        let backoff = Backoff::new();

        while self
            .state
            .compare_exchange_weak(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed)
            .is_err()
        {
            backoff.snooze();
        }
    }

    fn release(&self) {
        self.state.store(UNLOCKED, Ordering::Release);
    }

    fn get_shared(&self) -> &T {
        unsafe { &*self.data.get() }
    }

    #[allow(clippy::mut_from_ref)]
    fn get_unique(&self) -> &mut T {
        unsafe { &mut *self.data.get() }
    }

    pub fn lock(&self) -> MutexGuard<'_, T> {
        self.acquire();
        MutexGuard::new(self)
    }
}

unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}

pub struct MutexGuard<'a, T> {
    mutex: &'a Mutex<T>,
}

impl<'a, T> MutexGuard<'a, T> {
    fn new(mutex: &'a Mutex<T>) -> Self {
        Self { mutex }
    }
}

impl<'a, T> Deref for MutexGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.mutex.get_shared()
    }
}

impl<'a, T> DerefMut for MutexGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.mutex.get_unique()
    }
}

impl<'a, T> Drop for MutexGuard<'a, T> {
    fn drop(&mut self) {
        self.mutex.release();
    }
}

unsafe impl<'a, T: Send> Send for MutexGuard<'a, T> {}
unsafe impl<'a, T: Sync> Sync for MutexGuard<'a, T> {}