use core::cell::Cell; pub struct Mutex { // This platform has no threads, so we can use a Cell here. locked: Cell, } unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} // no threads on this platform impl Mutex { #[inline] pub const fn new() -> Mutex { Mutex { locked: Cell::new(false), } } /// Locks the mutex /// /// # Safety /// /// UB occurs if the mutex is already locked by the current thread and the /// `unsafe_lock` feature is enabled. #[inline] pub unsafe fn lock(&self) { if self.locked.replace(true) { if cfg!(feature = "unsafe_lock") { // safety: it's UB to lock this when it's already locked unsafe { core::hint::unreachable_unchecked() }; } else { panic!("deadlock on a platform with no threads"); } } } /// If the mutex is unlocked, it is locked, and this function returns /// `true'. Otherwise, `false` is returned. #[inline] pub unsafe fn try_lock(&self) -> bool { self.locked.replace(true) == false } /// Unlocks the mutex /// /// # Safety /// /// UB occurs if the mutex is already unlocked or if it has been locked on /// a different thread. #[inline] pub unsafe fn unlock(&self) { self.locked.set(false); } #[inline] pub unsafe fn is_locked(&self) -> bool { self.locked.get() } } pub struct RwLock { // This platform has no threads, so we can use a Cell here. mode: Cell, } unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} // no threads on this platform impl RwLock { #[inline] pub const fn new() -> RwLock { RwLock { mode: Cell::new(0) } } #[inline] pub unsafe fn read(&self) { let m = self.mode.get(); if m >= 0 { self.mode.set(m + 1); } else { unsafe { core::hint::unreachable_unchecked() }; } } #[inline] pub unsafe fn try_read(&self) -> bool { let m = self.mode.get(); if m >= 0 { self.mode.set(m + 1); true } else { false } } #[inline] pub unsafe fn write(&self) { if self.mode.replace(isize::MAX) != 0 { unsafe { core::hint::unreachable_unchecked() }; } } #[inline] pub unsafe fn try_write(&self) -> bool { if self.mode.get() == 0 { self.mode.set(-1); true } else { false } } #[inline] pub unsafe fn read_unlock(&self) { self.mode.set(self.mode.get() - 1); } #[inline] pub unsafe fn write_unlock(&self) { assert_eq!(self.mode.replace(0), -1); } }