use core::{convert::Infallible, fmt::{Debug, Display}, marker::PhantomData, ops::{Deref, DerefMut}};
use irid_syscall::ffi::thread::syscall_yield;
use spin::{RelaxStrategy, Spin, mutex::{SpinMutex, SpinMutexGuard}};
type Strategy = Spin;
#[derive(Debug, Default)]
pub struct Mutex<T: ?Sized> {
lock: SpinMutex<T, Strategy>
}
impl <T> From<T> for Mutex<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
unsafe impl <T: ?Sized + Send> Send for Mutex<T> {
}
unsafe impl <T: ?Sized + Send> Sync for Mutex<T> {
}
impl <T> Mutex<T> {
pub const fn new(value: T) -> Self {
Self {
lock: SpinMutex::new(value)
}
}
}
impl <T: ?Sized> Mutex<T> {
pub fn lock(&self) -> Result<MutexGuard<'_, T>, PoisonError<T>> {
Ok(MutexGuard { guard: self.lock.lock() })
}
pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError<T>> {
if let Some(guard) = self.lock.try_lock() {
Ok(MutexGuard { guard })
} else {
Err(TryLockError::WouldBlock)
}
}
pub fn is_poisoned(&self) -> bool {
false
}
pub fn clear_poison(&self) {
}
pub fn into_inner(self) -> Result<T, PoisonError<T>> where T: Sized {
Ok(self.lock.into_inner())
}
pub fn get_mut(&mut self) -> Result<&mut T, PoisonError<T>> {
Ok(self.lock.get_mut())
}
}
#[derive(Debug)]
pub struct MutexGuard<'a, T: ?Sized> {
guard: SpinMutexGuard<'a, T, Strategy>
}
impl <'a, T: Display> Display for MutexGuard<'a, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", &*self.guard)
}
}
unsafe impl <'a, T: ?Sized + Send> Sync for MutexGuard<'a, T> {
}
impl <'a, T: ?Sized> !Send for MutexGuard<'a, T> {
}
impl <'a, T: ?Sized> Deref for MutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&*self.guard
}
}
impl <'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.guard
}
}
pub struct PoisonError<T: ?Sized> {
value: PhantomData<T>,
_cannot_construct: Infallible
}
impl <T: ?Sized> Debug for PoisonError<T> {
fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
unreachable!("cannot debug a type that can never be constructed")
}
}
pub(crate) struct Yield;
impl RelaxStrategy for Yield {
fn relax() {
syscall_yield()
}
}
pub enum TryLockError<T: ?Sized> {
Poisoned(PoisonError<T>),
WouldBlock
}