shared_mutex/
monitor.rs

1//! A monitor convenience type that couples a SharedMutex and a Condvar.
2//!
3//! This type is more convenient to use but a little bit less general than
4//! SharedMutex since the monitor uses only one condition variable, whereas
5//! a SharedMutex can be used with any number of condition variables.
6
7use std::sync::{Condvar, LockResult};
8use std::ops::{Deref, DerefMut};
9use std::fmt;
10
11use poison;
12use {SharedMutex, SharedMutexReadGuard, SharedMutexWriteGuard};
13
14/// A convenience wrapper around a SharedMutex and a Condvar.
15///
16/// Provides an ergonomic API for locking and waiting on predicates
17/// associated with the internal data.
18pub struct Monitor<T: ?Sized> {
19    cond: Condvar,
20    mutex: SharedMutex<T>
21}
22
23/// A shared read guard to the data in a Monitor.
24pub struct MonitorReadGuard<'mutex, T: ?Sized + 'mutex> {
25    guard: SharedMutexReadGuard<'mutex, T>,
26    cond: &'mutex Condvar
27}
28
29/// An exclusive write guard to the data in a Monitor.
30pub struct MonitorWriteGuard<'mutex, T: ?Sized + 'mutex> {
31    guard: SharedMutexWriteGuard<'mutex, T>,
32    cond: &'mutex Condvar
33}
34
35impl<T> Monitor<T> {
36    /// Create a new Monitor.
37    pub fn new(val: T) -> Monitor<T> {
38        Monitor {
39            mutex: SharedMutex::new(val),
40            cond: Condvar::new()
41        }
42    }
43}
44
45impl<T: ?Sized> Monitor<T> {
46    /// Acquire a shared read lock on the monitor.
47    pub fn read(&self) -> LockResult<MonitorReadGuard<T>> {
48        poison::map_result(self.mutex.read(), |guard| {
49            MonitorReadGuard {
50                guard: guard,
51                cond: &self.cond
52            }
53        })
54    }
55
56    /// Acquire an exclusive write lock on the monitor.
57    pub fn write(&self) -> LockResult<MonitorWriteGuard<T>> {
58        poison::map_result(self.mutex.write(), |guard| {
59            MonitorWriteGuard {
60                guard: guard,
61                cond: &self.cond
62            }
63        })
64    }
65
66    /// Notify one thread which is waiting on the monitor.
67    ///
68    /// Note that it is safe but often incorrect to notify without holding any
69    /// lock on the monitor, since the predicate may change between a
70    /// notification and a predicate check, potentially causing a deadlock.
71    #[inline]
72    pub fn notify_one(&self) { self.cond.notify_one() }
73
74    /// Notify all threads which are waiting on the monitor.
75    ///
76    /// Note that it is safe but often incorrect to notify without holding any
77    /// lock on the monitor, since the predicate may change between a
78    /// notification and a predicate check, potentially causing a deadlock.
79    #[inline]
80    pub fn notify_all(&self) { self.cond.notify_all() }
81
82    /// Get a reference to the condition variable in this Monitor for external use.
83    #[inline]
84    pub fn cond(&self) -> &Condvar { &self.cond }
85}
86
87impl<'mutex, T: ?Sized> MonitorReadGuard<'mutex, T> {
88    /// Wait for a notification on the monitor, then resume with another read guard.
89    pub fn wait_for_read(self) -> LockResult<Self> {
90        let (guard, cond) = (self.guard, self.cond);
91        poison::map_result(guard.wait_for_read(cond), |guard| {
92            MonitorReadGuard {
93                guard: guard,
94                cond: cond
95            }
96        })
97    }
98
99    /// Wait for a notification on the monitor, then resume with a write guard.
100    pub fn wait_for_write(self) -> LockResult<MonitorWriteGuard<'mutex, T>> {
101        let (guard, cond) = (self.guard, self.cond);
102        poison::map_result(guard.wait_for_write(cond), |guard| {
103            MonitorWriteGuard {
104                guard: guard,
105                cond: cond
106            }
107        })
108    }
109
110    /// Notify a thread waiting on the monitor.
111    pub fn notify_one(&self) { self.cond.notify_one() }
112
113    /// Notify all threads waiting on the monitor.
114    pub fn notify_all(&self) { self.cond.notify_all() }
115}
116
117impl<'mutex, T: ?Sized> MonitorWriteGuard<'mutex, T> {
118    /// Wait for a notification on the monitor, then resume with another read guard.
119    pub fn wait_for_read(self) -> LockResult<MonitorReadGuard<'mutex, T>> {
120        let (guard, cond) = (self.guard, self.cond);
121        poison::map_result(guard.wait_for_read(cond), |guard| {
122            MonitorReadGuard {
123                guard: guard,
124                cond: cond
125            }
126        })
127    }
128
129    /// Wait for a notification on the monitor, then resume with another write guard.
130    pub fn wait_for_write(self) -> LockResult<Self> {
131        let (guard, cond) = (self.guard, self.cond);
132        poison::map_result(guard.wait_for_write(cond), |guard| {
133            MonitorWriteGuard {
134                guard: guard,
135                cond: cond
136            }
137        })
138    }
139
140    /// Notify a thread waiting on the monitor.
141    pub fn notify_one(&self) { self.cond.notify_one() }
142
143    /// Notify all threads waiting on the monitor.
144    pub fn notify_all(&self) { self.cond.notify_all() }
145}
146
147impl<'mutex, T: ?Sized> Deref for MonitorReadGuard<'mutex, T> {
148    type Target = SharedMutexReadGuard<'mutex, T>;
149
150    fn deref(&self) -> &Self::Target { &self.guard }
151}
152
153impl<'mutex, T: ?Sized> Deref for MonitorWriteGuard<'mutex, T> {
154    type Target = SharedMutexWriteGuard<'mutex, T>;
155
156    fn deref(&self) -> &Self::Target { &self.guard }
157}
158
159impl<'mutex, T: ?Sized> DerefMut for MonitorWriteGuard<'mutex, T> {
160    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.guard }
161}
162
163impl<'mutex, T: ?Sized> Into<SharedMutexWriteGuard<'mutex, T>> for MonitorWriteGuard<'mutex, T> {
164    fn into(self) -> SharedMutexWriteGuard<'mutex, T> { self.guard }
165}
166
167impl<'mutex, T: ?Sized> Into<SharedMutexReadGuard<'mutex, T>> for MonitorReadGuard<'mutex, T> {
168    fn into(self) -> SharedMutexReadGuard<'mutex, T> { self.guard }
169}
170
171impl<T: ?Sized> AsRef<SharedMutex<T>> for Monitor<T> {
172    fn as_ref(&self) -> &SharedMutex<T> { &self.mutex }
173}
174
175impl<T: ?Sized> AsMut<SharedMutex<T>> for Monitor<T> {
176    fn as_mut(&mut self) -> &mut SharedMutex<T> { &mut self.mutex }
177}
178
179impl<T> Into<SharedMutex<T>> for Monitor<T> {
180    fn into(self) -> SharedMutex<T> { self.mutex }
181}
182
183impl<T: ?Sized + fmt::Debug> fmt::Debug for Monitor<T> {
184    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185        f.debug_struct("Monitor")
186            .field("mutex", &&self.mutex)
187            .finish()
188    }
189}
190
191impl<'mutex, T: ?Sized + fmt::Debug> fmt::Debug for MonitorReadGuard<'mutex, T> {
192    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
193        f.debug_struct("MonitorReadGuard")
194            .field("data", &self.guard)
195            .finish()
196    }
197}
198
199impl<'mutex, T: ?Sized + fmt::Debug> fmt::Debug for MonitorWriteGuard<'mutex, T> {
200    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
201        f.debug_struct("MonitorWriteGuard")
202            .field("data", &self.guard)
203            .finish()
204    }
205}
206