use base::prelude::*;
use io::{Write};
use fmt::{Debug};
use cell::{Cell};
use stlock::{SingleThreadLock, SingleThreadLockGuard};
pub struct SingleThreadMutex<T> {
lock: SingleThreadLock,
data: Cell<T>,
}
impl<T> SingleThreadMutex<T> {
pub const fn new(data: T) -> SingleThreadMutex<T> {
SingleThreadMutex {
lock: SingleThreadLock::new(),
data: Cell::new(data),
}
}
fn guard<'a>(&'a self,
guard: SingleThreadLockGuard<'a>) -> SingleThreadMutexGuard<'a, T> {
SingleThreadMutexGuard {
guard: guard,
mutex: self,
_marker: (NoSend, NoInterrupt),
}
}
pub fn as_lock(&self) -> &SingleThreadLock {
&self.lock
}
pub fn try_lock<'a>(&'a self) -> Option<SingleThreadMutexGuard<'a, T>> {
self.lock.try_lock().map(|g| self.guard(g))
}
pub fn lock<'a>(&'a self) -> SingleThreadMutexGuard<'a, T> {
self.guard(self.lock.lock())
}
pub fn existing_lock<'a>(
&'a self,
guard: SingleThreadLockGuard<'a>
) -> SingleThreadMutexGuard<'a, T>
{
assert!(&self.lock == guard.as_lock());
self.guard(guard)
}
pub fn data(&mut self) -> &mut T {
unsafe { &mut *self.data.ptr() }
}
}
unsafe impl<T> Interrupt for SingleThreadMutex<T> { }
unsafe impl<T> Send for SingleThreadMutex<T> where T: Send { }
pub struct SingleThreadMutexGuard<'a, T: 'a> {
guard: SingleThreadLockGuard<'a>,
mutex: &'a SingleThreadMutex<T>,
_marker: (NoSend, NoInterrupt),
}
impl<'a, T> SingleThreadMutexGuard<'a, T> {
pub fn as_lock_guard(&self) -> &SingleThreadLockGuard<'a> {
&self.guard
}
pub fn into_lock_guard(self) -> SingleThreadLockGuard<'a> {
self.guard
}
pub fn as_mutex(&self) -> &'a SingleThreadMutex<T> {
self.mutex
}
pub fn unlock(self) -> &'a SingleThreadMutex<T> {
self.mutex
}
}
unsafe impl<'a, T> Sync for SingleThreadMutexGuard<'a, T> where T: Sync { }
impl<'a, T> Deref for SingleThreadMutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.mutex.data.ptr() }
}
}
impl<'a, T> DerefMut for SingleThreadMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.mutex.data.ptr() }
}
}
impl<'a, T: Debug> Debug for SingleThreadMutexGuard<'a, T> {
fn fmt<W: Write>(&self, w: &mut W) -> Result {
self.deref().fmt(w)
}
}