//! Traits for syncronization primitives.

use core::cell::UnsafeCell;

/// For the duration of the closure `f`, an object implementing this trait
/// guarantees exclusive access to the data wrapped by the Mutex object.
pub trait Mutex {
    /// The type of the data wrapped by the mutex.
    type Data;
    /// Locks the mutex and grants access to the wrapped data to the closure.
    fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
}

/// Dummy Mutex that does not protect agains anythings.
/// This in only save in monocore monothread context, without
/// interrupt.
pub struct DummyMutex<T: ?Sized> {
    data: UnsafeCell<T>,
}

unsafe impl<T: ?Sized + Send> Send for DummyMutex<T> {}
unsafe impl<T: ?Sized + Send> Sync for DummyMutex<T> {}

impl<T> DummyMutex<T> {
    /// Constructor for [`DummyMutex`].
    pub const fn new(data: T) -> Self {
        // panic!("PseudoMutex is verry unsafe");
        Self {
            data: UnsafeCell::new(data),
        }
    }
}

impl<T> Mutex for DummyMutex<T> {
    type Data = T;

    fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {
        let data = unsafe { &mut *self.data.get() };
        f(data)
    }
}
