blob: f831f5f41af498823a94d046d5da25914e98273e (
plain)
use core::cell::Cell;
pub struct Mutex {
// This platform has no threads, so we can use a Cell here.
locked: Cell<bool>,
}
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<isize>,
}
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);
}
}
|