use std::sync::{Condvar, LockResult};
use std::ops::{Deref, DerefMut};
use std::fmt;
use poison;
use {SharedMutex, SharedMutexReadGuard, SharedMutexWriteGuard};
pub struct Monitor<T: ?Sized> {
cond: Condvar,
mutex: SharedMutex<T>
}
pub struct MonitorReadGuard<'mutex, T: ?Sized + 'mutex> {
guard: SharedMutexReadGuard<'mutex, T>,
cond: &'mutex Condvar
}
pub struct MonitorWriteGuard<'mutex, T: ?Sized + 'mutex> {
guard: SharedMutexWriteGuard<'mutex, T>,
cond: &'mutex Condvar
}
impl<T> Monitor<T> {
pub fn new(val: T) -> Monitor<T> {
Monitor {
mutex: SharedMutex::new(val),
cond: Condvar::new()
}
}
}
impl<T: ?Sized> Monitor<T> {
pub fn read(&self) -> LockResult<MonitorReadGuard<T>> {
poison::map_result(self.mutex.read(), |guard| {
MonitorReadGuard {
guard: guard,
cond: &self.cond
}
})
}
pub fn write(&self) -> LockResult<MonitorWriteGuard<T>> {
poison::map_result(self.mutex.write(), |guard| {
MonitorWriteGuard {
guard: guard,
cond: &self.cond
}
})
}
#[inline]
pub fn notify_one(&self) { self.cond.notify_one() }
#[inline]
pub fn notify_all(&self) { self.cond.notify_all() }
#[inline]
pub fn cond(&self) -> &Condvar { &self.cond }
}
impl<'mutex, T: ?Sized> MonitorReadGuard<'mutex, T> {
pub fn wait_for_read(self) -> LockResult<Self> {
let (guard, cond) = (self.guard, self.cond);
poison::map_result(guard.wait_for_read(cond), |guard| {
MonitorReadGuard {
guard: guard,
cond: cond
}
})
}
pub fn wait_for_write(self) -> LockResult<MonitorWriteGuard<'mutex, T>> {
let (guard, cond) = (self.guard, self.cond);
poison::map_result(guard.wait_for_write(cond), |guard| {
MonitorWriteGuard {
guard: guard,
cond: cond
}
})
}
pub fn notify_one(&self) { self.cond.notify_one() }
pub fn notify_all(&self) { self.cond.notify_all() }
}
impl<'mutex, T: ?Sized> MonitorWriteGuard<'mutex, T> {
pub fn wait_for_read(self) -> LockResult<MonitorReadGuard<'mutex, T>> {
let (guard, cond) = (self.guard, self.cond);
poison::map_result(guard.wait_for_read(cond), |guard| {
MonitorReadGuard {
guard: guard,
cond: cond
}
})
}
pub fn wait_for_write(self) -> LockResult<Self> {
let (guard, cond) = (self.guard, self.cond);
poison::map_result(guard.wait_for_write(cond), |guard| {
MonitorWriteGuard {
guard: guard,
cond: cond
}
})
}
pub fn notify_one(&self) { self.cond.notify_one() }
pub fn notify_all(&self) { self.cond.notify_all() }
}
impl<'mutex, T: ?Sized> Deref for MonitorReadGuard<'mutex, T> {
type Target = SharedMutexReadGuard<'mutex, T>;
fn deref(&self) -> &Self::Target { &self.guard }
}
impl<'mutex, T: ?Sized> Deref for MonitorWriteGuard<'mutex, T> {
type Target = SharedMutexWriteGuard<'mutex, T>;
fn deref(&self) -> &Self::Target { &self.guard }
}
impl<'mutex, T: ?Sized> DerefMut for MonitorWriteGuard<'mutex, T> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.guard }
}
impl<'mutex, T: ?Sized> Into<SharedMutexWriteGuard<'mutex, T>> for MonitorWriteGuard<'mutex, T> {
fn into(self) -> SharedMutexWriteGuard<'mutex, T> { self.guard }
}
impl<'mutex, T: ?Sized> Into<SharedMutexReadGuard<'mutex, T>> for MonitorReadGuard<'mutex, T> {
fn into(self) -> SharedMutexReadGuard<'mutex, T> { self.guard }
}
impl<T: ?Sized> AsRef<SharedMutex<T>> for Monitor<T> {
fn as_ref(&self) -> &SharedMutex<T> { &self.mutex }
}
impl<T: ?Sized> AsMut<SharedMutex<T>> for Monitor<T> {
fn as_mut(&mut self) -> &mut SharedMutex<T> { &mut self.mutex }
}
impl<T> Into<SharedMutex<T>> for Monitor<T> {
fn into(self) -> SharedMutex<T> { self.mutex }
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for Monitor<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Monitor")
.field("mutex", &&self.mutex)
.finish()
}
}
impl<'mutex, T: ?Sized + fmt::Debug> fmt::Debug for MonitorReadGuard<'mutex, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MonitorReadGuard")
.field("data", &self.guard)
.finish()
}
}
impl<'mutex, T: ?Sized + fmt::Debug> fmt::Debug for MonitorWriteGuard<'mutex, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MonitorWriteGuard")
.field("data", &self.guard)
.finish()
}
}