diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 3e17d8b6be1..15faf5be258 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -12,10 +12,10 @@ use prelude::*; use sync::atomic::{mod, AtomicUint}; use sync::poison::{mod, LockResult}; -use sync::CondvarGuard; use sys_common::condvar as sys; use sys_common::mutex as sys_mutex; use time::Duration; +use sync::{mutex, MutexGuard}; /// A Condition Variable /// @@ -57,6 +57,7 @@ use time::Duration; /// started = cvar.wait(started).unwrap(); /// } /// ``` +#[stable] pub struct Condvar { inner: Box } unsafe impl Send for Condvar {} @@ -74,6 +75,7 @@ unsafe impl Sync for Condvar {} /// /// static CVAR: StaticCondvar = CONDVAR_INIT; /// ``` +#[unstable = "may be merged with Condvar in the future"] pub struct StaticCondvar { inner: sys::Condvar, mutex: AtomicUint, @@ -83,24 +85,16 @@ unsafe impl Send for StaticCondvar {} unsafe impl Sync for StaticCondvar {} /// Constant initializer for a statically allocated condition variable. +#[unstable = "may be merged with Condvar in the future"] pub const CONDVAR_INIT: StaticCondvar = StaticCondvar { inner: sys::CONDVAR_INIT, mutex: atomic::INIT_ATOMIC_UINT, }; -/// A trait for vaules which can be passed to the waiting methods of condition -/// variables. This is implemented by the mutex guards in this module. -/// -/// Note that this trait should likely not be implemented manually unless you -/// really know what you're doing. -pub trait AsGuard { - #[allow(missing_docs)] - fn as_guard(&self) -> CondvarGuard; -} - impl Condvar { /// Creates a new condition variable which is ready to be waited on and /// notified. + #[stable] pub fn new() -> Condvar { Condvar { inner: box StaticCondvar { @@ -136,11 +130,12 @@ impl Condvar { /// over time. Each condition variable is dynamically bound to exactly one /// mutex to ensure defined behavior across platforms. If this functionality /// is not desired, then unsafe primitives in `sys` are provided. - pub fn wait(&self, mutex_guard: T) - -> LockResult { + #[stable] + pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) + -> LockResult> { unsafe { let me: &'static Condvar = &*(self as *const _); - me.inner.wait(mutex_guard) + me.inner.wait(guard) } } @@ -164,11 +159,11 @@ impl Condvar { // provide. There are also additional concerns about the unix-specific // implementation which may need to be addressed. #[allow(dead_code)] - fn wait_timeout(&self, mutex_guard: T, dur: Duration) - -> LockResult<(T, bool)> { + fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration) + -> LockResult<(MutexGuard<'a, T>, bool)> { unsafe { let me: &'static Condvar = &*(self as *const _); - me.inner.wait_timeout(mutex_guard, dur) + me.inner.wait_timeout(guard, dur) } } @@ -179,6 +174,7 @@ impl Condvar { /// `notify_one` are not buffered in any way. /// /// To wake up all threads, see `notify_one()`. + #[stable] pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } } /// Wake up all blocked threads on this condvar. @@ -188,6 +184,7 @@ impl Condvar { /// way. /// /// To wake up only one thread, see `notify_one()`. + #[stable] pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } } } @@ -202,17 +199,19 @@ impl StaticCondvar { /// notification. /// /// See `Condvar::wait`. - pub fn wait(&'static self, mutex_guard: T) -> LockResult { + #[unstable = "may be merged with Condvar in the future"] + pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>) + -> LockResult> { let poisoned = unsafe { - let cvar_guard = mutex_guard.as_guard(); - self.verify(cvar_guard.lock); - self.inner.wait(cvar_guard.lock); - cvar_guard.poisoned.get() + let lock = mutex::guard_lock(&guard); + self.verify(lock); + self.inner.wait(lock); + mutex::guard_poison(&guard).get() }; if poisoned { - Err(poison::new_poison_error(mutex_guard)) + Err(poison::new_poison_error(guard)) } else { - Ok(mutex_guard) + Ok(guard) } } @@ -221,29 +220,31 @@ impl StaticCondvar { /// /// See `Condvar::wait_timeout`. #[allow(dead_code)] // may want to stabilize this later, see wait_timeout above - fn wait_timeout(&'static self, mutex_guard: T, dur: Duration) - -> LockResult<(T, bool)> { + fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration) + -> LockResult<(MutexGuard<'a, T>, bool)> { let (poisoned, success) = unsafe { - let cvar_guard = mutex_guard.as_guard(); - self.verify(cvar_guard.lock); - let success = self.inner.wait_timeout(cvar_guard.lock, dur); - (cvar_guard.poisoned.get(), success) + let lock = mutex::guard_lock(&guard); + self.verify(lock); + let success = self.inner.wait_timeout(lock, dur); + (mutex::guard_poison(&guard).get(), success) }; if poisoned { - Err(poison::new_poison_error((mutex_guard, success))) + Err(poison::new_poison_error((guard, success))) } else { - Ok((mutex_guard, success)) + Ok((guard, success)) } } /// Wake up one blocked thread on this condvar. /// /// See `Condvar::notify_one`. + #[unstable = "may be merged with Condvar in the future"] pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } } /// Wake up all blocked threads on this condvar. /// /// See `Condvar::notify_all`. + #[unstable = "may be merged with Condvar in the future"] pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } } /// Deallocate all resources associated with this static condvar. @@ -252,6 +253,7 @@ impl StaticCondvar { /// active users of the condvar, and this also doesn't prevent any future /// users of the condvar. This method is required to be called to not leak /// memory on all platforms. + #[unstable = "may be merged with Condvar in the future"] pub unsafe fn destroy(&'static self) { self.inner.destroy() } diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 3f95eac5090..092acc7ff25 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -17,16 +17,13 @@ #![experimental] -use sys_common::mutex as sys_mutex; - pub use alloc::arc::{Arc, Weak}; -pub use self::mutex::{Mutex, MutexGuard, StaticMutex, StaticMutexGuard}; +pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; pub use self::mutex::MUTEX_INIT; pub use self::rwlock::{RWLock, StaticRWLock, RWLOCK_INIT}; pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; -pub use self::rwlock::{StaticRWLockReadGuard, StaticRWLockWriteGuard}; -pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT, AsGuard}; +pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; pub use self::semaphore::{Semaphore, SemaphoreGuard}; pub use self::barrier::Barrier; @@ -45,10 +42,3 @@ mod poison; mod rwlock; mod semaphore; mod task_pool; - -/// Structure returned by `AsGuard` to wait on a condition variable. -// NB: defined here to all modules have access to these private fields. -pub struct CondvarGuard<'a> { - lock: &'a sys_mutex::Mutex, - poisoned: &'a poison::Flag, -} diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 621d7274062..32c2c67152f 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -12,7 +12,6 @@ use prelude::*; use cell::UnsafeCell; use kinds::marker; -use sync::{AsGuard, CondvarGuard}; use sync::poison::{mod, TryLockError, TryLockResult, LockResult}; use sys_common::mutex as sys; @@ -107,6 +106,7 @@ use sys_common::mutex as sys; /// /// *guard += 1; /// ``` +#[stable] pub struct Mutex { // Note that this static mutex is in a *box*, not inlined into the struct // itself. Once a native mutex has been used once, its address can never @@ -142,6 +142,7 @@ unsafe impl Sync for Mutex { } /// } /// // lock is unlocked here. /// ``` +#[unstable = "may be merged with Mutex in the future"] pub struct StaticMutex { lock: sys::Mutex, poison: poison::Flag, @@ -155,27 +156,19 @@ unsafe impl Sync for StaticMutex {} /// The data protected by the mutex can be access through this guard via its /// Deref and DerefMut implementations #[must_use] +#[stable] pub struct MutexGuard<'a, T: 'a> { // funny underscores due to how Deref/DerefMut currently work (they // disregard field privacy). - __inner: Guard<'a, Mutex>, -} - -/// An RAII implementation of a "scoped lock" of a static mutex. When this -/// structure is dropped (falls out of scope), the lock will be unlocked. -#[must_use] -pub struct StaticMutexGuard { - inner: Guard<'static, StaticMutex>, -} - -struct Guard<'a, T: 'a> { - inner: &'a T, - poison: poison::Guard, - marker: marker::NoSend, // even if 'a is static, this cannot be sent + __lock: &'a StaticMutex, + __data: &'a UnsafeCell, + __poison: poison::Guard, + __marker: marker::NoSend, } /// Static initialization of a mutex. This constant can be used to initialize /// other mutex constants. +#[unstable = "may be merged with Mutex in the future"] pub const MUTEX_INIT: StaticMutex = StaticMutex { lock: sys::MUTEX_INIT, poison: poison::FLAG_INIT, @@ -183,6 +176,7 @@ pub const MUTEX_INIT: StaticMutex = StaticMutex { impl Mutex { /// Creates a new mutex in an unlocked state ready for use. + #[stable] pub fn new(t: T) -> Mutex { Mutex { inner: box MUTEX_INIT, @@ -201,9 +195,10 @@ impl Mutex { /// /// If another user of this mutex panicked while holding the mutex, then /// this call will return an error once the mutex is acquired. + #[stable] pub fn lock(&self) -> LockResult> { unsafe { self.inner.lock.lock() } - MutexGuard::new(self) + MutexGuard::new(&*self.inner, &self.data) } /// Attempts to acquire this lock. @@ -219,9 +214,10 @@ impl Mutex { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. + #[stable] pub fn try_lock(&self) -> TryLockResult> { if unsafe { self.inner.lock.try_lock() } { - Ok(try!(MutexGuard::new(self))) + Ok(try!(MutexGuard::new(&*self.inner, &self.data))) } else { Err(TryLockError::WouldBlock) } @@ -238,19 +234,23 @@ impl Drop for Mutex { } } +static DUMMY: UnsafeCell<()> = UnsafeCell { value: () }; + impl StaticMutex { /// Acquires this lock, see `Mutex::lock` #[inline] - pub fn lock(&'static self) -> LockResult { + #[unstable = "may be merged with Mutex in the future"] + pub fn lock(&'static self) -> LockResult> { unsafe { self.lock.lock() } - StaticMutexGuard::new(self) + MutexGuard::new(self, &DUMMY) } /// Attempts to grab this lock, see `Mutex::try_lock` #[inline] - pub fn try_lock(&'static self) -> TryLockResult { + #[unstable = "may be merged with Mutex in the future"] + pub fn try_lock(&'static self) -> TryLockResult> { if unsafe { self.lock.try_lock() } { - Ok(try!(StaticMutexGuard::new(self))) + Ok(try!(MutexGuard::new(self, &DUMMY))) } else { Err(TryLockError::WouldBlock) } @@ -266,95 +266,56 @@ impl StaticMutex { /// *all* platforms. It may be the case that some platforms do not leak /// memory if this method is not called, but this is not guaranteed to be /// true on all platforms. + #[unstable = "may be merged with Mutex in the future"] pub unsafe fn destroy(&'static self) { self.lock.destroy() } } impl<'mutex, T> MutexGuard<'mutex, T> { - fn new(lock: &Mutex) -> LockResult> { - poison::map_result(Guard::new(lock), |guard| { - MutexGuard { __inner: guard } - }) - } -} - -impl AsGuard for Mutex { - fn as_guard(&self) -> CondvarGuard { self.inner.as_guard() } -} - -impl<'mutex, T> AsGuard for MutexGuard<'mutex, T> { - fn as_guard(&self) -> CondvarGuard { - CondvarGuard { - lock: &self.__inner.inner.inner.lock, - poisoned: &self.__inner.inner.inner.poison, - } - } -} - -impl<'mutex, T> Deref for MutexGuard<'mutex, T> { - fn deref<'a>(&'a self) -> &'a T { - unsafe { &*self.__inner.inner.data.get() } - } -} -impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> { - fn deref_mut<'a>(&'a mut self) -> &'a mut T { - unsafe { &mut *self.__inner.inner.data.get() } - } -} - -impl StaticMutexGuard { - #[inline] - fn new(lock: &'static StaticMutex) -> LockResult { - poison::map_result(Guard::new(lock), |guard| { - StaticMutexGuard { inner: guard } - }) - } -} - -impl AsGuard for StaticMutex { - #[inline] - fn as_guard(&self) -> CondvarGuard { - CondvarGuard { lock: &self.lock, poisoned: &self.poison } - } -} - -impl AsGuard for StaticMutexGuard { - #[inline] - fn as_guard(&self) -> CondvarGuard { - CondvarGuard { - lock: &self.inner.inner.lock, - poisoned: &self.inner.inner.poison, - } - } -} - -impl<'a, T: AsGuard> Guard<'a, T> { - #[inline] - fn new(t: &T) -> LockResult> { - let data = t.as_guard(); - poison::map_result(data.poisoned.borrow(), |guard| { - Guard { - inner: t, - poison: guard, - marker: marker::NoSend, + fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell) + -> LockResult> { + poison::map_result(lock.poison.borrow(), |guard| { + MutexGuard { + __lock: lock, + __data: data, + __poison: guard, + __marker: marker::NoSend, } }) } } +impl<'mutex, T> Deref for MutexGuard<'mutex, T> { + fn deref<'a>(&'a self) -> &'a T { + unsafe { &*self.__data.get() } + } +} +impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> { + fn deref_mut<'a>(&'a mut self) -> &'a mut T { + unsafe { &mut *self.__data.get() } + } +} + #[unsafe_destructor] -impl<'a, T: AsGuard> Drop for Guard<'a, T> { +impl<'a, T> Drop for MutexGuard<'a, T> { #[inline] fn drop(&mut self) { unsafe { - let data = self.inner.as_guard(); - data.poisoned.done(&self.poison); - data.lock.unlock(); + self.__lock.poison.done(&self.__poison); + self.__lock.lock.unlock(); } } } +pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { + &guard.__lock.lock +} + +pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { + &guard.__lock.poison +} + #[cfg(test)] mod test { use prelude::*; diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index d99fd91d0ac..edf16d99f49 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -53,18 +53,22 @@ pub struct Guard { /// is held. The precise semantics for when a lock is poisoned is documented on /// each lock, but once a lock is poisoned then all future acquisitions will /// return this error. +#[stable] pub struct PoisonError { guard: T, } /// An enumeration of possible errors which can occur while calling the /// `try_lock` method. +#[stable] pub enum TryLockError { /// The lock could not be acquired because another task failed while holding /// the lock. + #[stable] Poisoned(PoisonError), /// The lock could not be acquired at this time because the operation would /// otherwise block. + #[stable] WouldBlock, } @@ -75,6 +79,7 @@ pub enum TryLockError { /// that the primitive was poisoned. Note that the `Err` variant *also* carries /// the associated guard, and it can be acquired through the `into_inner` /// method. +#[stable] pub type LockResult = Result>; /// A type alias for the result of a nonblocking locking method. @@ -82,6 +87,7 @@ pub type LockResult = Result>; /// For more information, see `LockResult`. A `TryLockResult` doesn't /// necessarily hold the associated guard in the `Err` type as the lock may not /// have been acquired for other reasons. +#[stable] pub type TryLockResult = Result>; impl fmt::Show for PoisonError { @@ -93,6 +99,7 @@ impl fmt::Show for PoisonError { impl PoisonError { /// Consumes this error indicating that a lock is poisoned, returning the /// underlying guard to allow access regardless. + #[stable] pub fn into_guard(self) -> T { self.guard } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index f7632c4f8b5..29cc1f8563f 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -57,6 +57,7 @@ use sys_common::rwlock as sys; /// assert_eq!(*w, 6); /// } // write lock is dropped here /// ``` +#[stable] pub struct RWLock { inner: Box, data: UnsafeCell, @@ -88,6 +89,7 @@ unsafe impl Sync for RWLock {} /// } /// unsafe { LOCK.destroy() } // free all resources /// ``` +#[unstable = "may be merged with RWLock in the future"] pub struct StaticRWLock { lock: sys::RWLock, poison: poison::Flag, @@ -97,6 +99,7 @@ unsafe impl Send for StaticRWLock {} unsafe impl Sync for StaticRWLock {} /// Constant initialization for a statically-initialized rwlock. +#[unstable = "may be merged with RWLock in the future"] pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { lock: sys::RWLOCK_INIT, poison: poison::FLAG_INIT, @@ -105,49 +108,27 @@ pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { /// RAII structure used to release the shared read access of a lock when /// dropped. #[must_use] +#[stable] pub struct RWLockReadGuard<'a, T: 'a> { - __inner: ReadGuard<'a, RWLock>, + __lock: &'a StaticRWLock, + __data: &'a UnsafeCell, + __marker: marker::NoSend, } /// RAII structure used to release the exclusive write access of a lock when /// dropped. #[must_use] +#[stable] pub struct RWLockWriteGuard<'a, T: 'a> { - __inner: WriteGuard<'a, RWLock>, -} - -/// RAII structure used to release the shared read access of a lock when -/// dropped. -#[must_use] -pub struct StaticRWLockReadGuard { - _inner: ReadGuard<'static, StaticRWLock>, -} - -/// RAII structure used to release the exclusive write access of a lock when -/// dropped. -#[must_use] -pub struct StaticRWLockWriteGuard { - _inner: WriteGuard<'static, StaticRWLock>, -} - -struct ReadGuard<'a, T: 'a> { - inner: &'a T, - marker: marker::NoSend, // even if 'a == static, cannot send -} - -struct WriteGuard<'a, T: 'a> { - inner: &'a T, - poison: poison::Guard, - marker: marker::NoSend, // even if 'a == static, cannot send -} - -#[doc(hidden)] -trait AsStaticRWLock { - fn as_static_rwlock(&self) -> &StaticRWLock; + __lock: &'a StaticRWLock, + __data: &'a UnsafeCell, + __poison: poison::Guard, + __marker: marker::NoSend, } impl RWLock { /// Creates a new instance of an RWLock which is unlocked and read to go. + #[stable] pub fn new(t: T) -> RWLock { RWLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) } } @@ -170,9 +151,10 @@ impl RWLock { /// is poisoned whenever a writer panics while holding an exclusive lock. /// The failure will occur immediately after the lock has been acquired. #[inline] + #[stable] pub fn read(&self) -> LockResult> { unsafe { self.inner.lock.read() } - RWLockReadGuard::new(self) + RWLockReadGuard::new(&*self.inner, &self.data) } /// Attempt to acquire this lock with shared read access. @@ -191,9 +173,10 @@ impl RWLock { /// error will only be returned if the lock would have otherwise been /// acquired. #[inline] + #[stable] pub fn try_read(&self) -> TryLockResult> { if unsafe { self.inner.lock.try_read() } { - Ok(try!(RWLockReadGuard::new(self))) + Ok(try!(RWLockReadGuard::new(&*self.inner, &self.data))) } else { Err(TryLockError::WouldBlock) } @@ -214,9 +197,10 @@ impl RWLock { /// is poisoned whenever a writer panics while holding an exclusive lock. /// An error will be returned when the lock is acquired. #[inline] + #[stable] pub fn write(&self) -> LockResult> { unsafe { self.inner.lock.write() } - RWLockWriteGuard::new(self) + RWLockWriteGuard::new(&*self.inner, &self.data) } /// Attempt to lock this rwlock with exclusive write access. @@ -232,9 +216,10 @@ impl RWLock { /// error will only be returned if the lock would have otherwise been /// acquired. #[inline] + #[stable] pub fn try_write(&self) -> TryLockResult> { if unsafe { self.inner.lock.try_read() } { - Ok(try!(RWLockWriteGuard::new(self))) + Ok(try!(RWLockWriteGuard::new(&*self.inner, &self.data))) } else { Err(TryLockError::WouldBlock) } @@ -248,24 +233,29 @@ impl Drop for RWLock { } } +static DUMMY: UnsafeCell<()> = UnsafeCell { value: () }; + impl StaticRWLock { /// Locks this rwlock with shared read access, blocking the current thread /// until it can be acquired. /// /// See `RWLock::read`. #[inline] - pub fn read(&'static self) -> LockResult { + #[unstable = "may be merged with RWLock in the future"] + pub fn read(&'static self) -> LockResult> { unsafe { self.lock.read() } - StaticRWLockReadGuard::new(self) + RWLockReadGuard::new(self, &DUMMY) } /// Attempt to acquire this lock with shared read access. /// /// See `RWLock::try_read`. #[inline] - pub fn try_read(&'static self) -> TryLockResult { + #[unstable = "may be merged with RWLock in the future"] + pub fn try_read(&'static self) + -> TryLockResult> { if unsafe { self.lock.try_read() } { - Ok(try!(StaticRWLockReadGuard::new(self))) + Ok(try!(RWLockReadGuard::new(self, &DUMMY))) } else { Err(TryLockError::WouldBlock) } @@ -276,18 +266,21 @@ impl StaticRWLock { /// /// See `RWLock::write`. #[inline] - pub fn write(&'static self) -> LockResult { + #[unstable = "may be merged with RWLock in the future"] + pub fn write(&'static self) -> LockResult> { unsafe { self.lock.write() } - StaticRWLockWriteGuard::new(self) + RWLockWriteGuard::new(self, &DUMMY) } /// Attempt to lock this rwlock with exclusive write access. /// /// See `RWLock::try_write`. #[inline] - pub fn try_write(&'static self) -> TryLockResult { + #[unstable = "may be merged with RWLock in the future"] + pub fn try_write(&'static self) + -> TryLockResult> { if unsafe { self.lock.try_write() } { - Ok(try!(StaticRWLockWriteGuard::new(self))) + Ok(try!(RWLockWriteGuard::new(self, &DUMMY))) } else { Err(TryLockError::WouldBlock) } @@ -299,93 +292,62 @@ impl StaticRWLock { /// active users of the lock, and this also doesn't prevent any future users /// of this lock. This method is required to be called to not leak memory on /// all platforms. + #[unstable = "may be merged with RWLock in the future"] pub unsafe fn destroy(&'static self) { self.lock.destroy() } } impl<'rwlock, T> RWLockReadGuard<'rwlock, T> { - fn new(lock: &RWLock) -> LockResult> { - poison::map_result(ReadGuard::new(lock), |guard| { - RWLockReadGuard { __inner: guard } + fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell) + -> LockResult> { + poison::map_result(lock.poison.borrow(), |_| { + RWLockReadGuard { + __lock: lock, + __data: data, + __marker: marker::NoSend, + } }) } } impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { - fn new(lock: &RWLock) -> LockResult> { - poison::map_result(WriteGuard::new(lock), |guard| { - RWLockWriteGuard { __inner: guard } + fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell) + -> LockResult> { + poison::map_result(lock.poison.borrow(), |guard| { + RWLockWriteGuard { + __lock: lock, + __data: data, + __poison: guard, + __marker: marker::NoSend, + } }) } } impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> { - fn deref(&self) -> &T { unsafe { &*self.__inner.inner.data.get() } } + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> { - fn deref(&self) -> &T { unsafe { &*self.__inner.inner.data.get() } } + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.__inner.inner.data.get() } - } -} - -impl StaticRWLockReadGuard { - #[inline] - fn new(lock: &'static StaticRWLock) -> LockResult { - poison::map_result(ReadGuard::new(lock), |guard| { - StaticRWLockReadGuard { _inner: guard } - }) - } -} -impl StaticRWLockWriteGuard { - #[inline] - fn new(lock: &'static StaticRWLock) -> LockResult { - poison::map_result(WriteGuard::new(lock), |guard| { - StaticRWLockWriteGuard { _inner: guard } - }) - } -} - -impl AsStaticRWLock for RWLock { - #[inline] - fn as_static_rwlock(&self) -> &StaticRWLock { &*self.inner } -} -impl AsStaticRWLock for StaticRWLock { - #[inline] - fn as_static_rwlock(&self) -> &StaticRWLock { self } -} - -impl<'a, T: AsStaticRWLock> ReadGuard<'a, T> { - fn new(t: &'a T) -> LockResult> { - poison::map_result(t.as_static_rwlock().poison.borrow(), |_| { - ReadGuard { inner: t, marker: marker::NoSend } - }) - } -} - -impl<'a, T: AsStaticRWLock> WriteGuard<'a, T> { - fn new(t: &'a T) -> LockResult> { - poison::map_result(t.as_static_rwlock().poison.borrow(), |guard| { - WriteGuard { inner: t, marker: marker::NoSend, poison: guard } - }) + unsafe { &mut *self.__data.get() } } } #[unsafe_destructor] -impl<'a, T: AsStaticRWLock> Drop for ReadGuard<'a, T> { +impl<'a, T> Drop for RWLockReadGuard<'a, T> { fn drop(&mut self) { - unsafe { self.inner.as_static_rwlock().lock.read_unlock(); } + unsafe { self.__lock.lock.read_unlock(); } } } #[unsafe_destructor] -impl<'a, T: AsStaticRWLock> Drop for WriteGuard<'a, T> { +impl<'a, T> Drop for RWLockWriteGuard<'a, T> { fn drop(&mut self) { - let inner = self.inner.as_static_rwlock(); - inner.poison.done(&self.poison); - unsafe { inner.lock.write_unlock(); } + self.__lock.poison.done(&self.__poison); + unsafe { self.__lock.lock.write_unlock(); } } }