about summary refs log tree commit diff
path: root/src/libstd/sync
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-12-29 10:01:38 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-12-29 14:41:30 -0800
commit35e63e382783c1dfea6f8c8ec451bab9f4076f9c (patch)
treeb3bb4f939a4b9f0d374954c0926fbf33077d3cc6 /src/libstd/sync
parent76e5ed655c762b812c3da4749a55f1bb1b52c787 (diff)
downloadrust-35e63e382783c1dfea6f8c8ec451bab9f4076f9c.tar.gz
rust-35e63e382783c1dfea6f8c8ec451bab9f4076f9c.zip
std: Stabilization pass for mutex/rwlock/condvar
This commit performs a stabilization pass over the sync::{mutex, rwlock,
condvar} modules, marking the following items as stable:

* Mutex
* Mutex::new
* Mutex::lock
* Mutex::try_lock
* MutexGuard
* RWLock
* RWLock::new
* RWLock::read
* RWLock::try_read
* RWLock::write
* RWLock::try_write
* RWLockReadGuard
* RWLockWriteGuard
* Condvar
* Condvar::new
* Condvar::wait
* Condvar::notify_one
* Condvar::notify_all
* PoisonError
* TryLockError
* TryLockError::Poisoned
* TryLockError::WouldBlock
* LockResult
* TryLockResult

The following items remain unstable to explore future possibilities of unifying
the static/non-static variants of the types:

* StaticMutex
* StaticMutex::new
* StaticMutex::lock
* StaticMutex::try_lock
* StaticMutex::desroy
* StaticRWLock
* StaticRWLock::new
* StaticRWLock::read
* StaticRWLock::try_read
* StaticRWLock::write
* StaticRWLock::try_write
* StaticRWLock::destroy

The following items were removed in favor of `Guard<'static, ()>` instead.

* StaticMutexGuard
* StaticRWLockReadGuard
* StaticRWLockWriteGuard
Diffstat (limited to 'src/libstd/sync')
-rw-r--r--src/libstd/sync/condvar.rs66
-rw-r--r--src/libstd/sync/mod.rs14
-rw-r--r--src/libstd/sync/mutex.rs125
-rw-r--r--src/libstd/sync/poison.rs7
-rw-r--r--src/libstd/sync/rwlock.rs164
5 files changed, 149 insertions, 227 deletions
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<StaticCondvar> }
 
 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<T: AsGuard>(&self, mutex_guard: T)
-                            -> LockResult<T> {
+    #[stable]
+    pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
+                       -> LockResult<MutexGuard<'a, T>> {
         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<T: AsGuard>(&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<T: AsGuard>(&'static self, mutex_guard: T) -> LockResult<T> {
+    #[unstable = "may be merged with Condvar in the future"]
+    pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>)
+                       -> LockResult<MutexGuard<'a, T>> {
         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<T: AsGuard>(&'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<T> {
     // 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<T:Send> Sync for Mutex<T> { }
 /// }
 /// // 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<T>>,
-}
-
-/// 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<T>,
+    __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<T: Send> Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
+    #[stable]
     pub fn new(t: T) -> Mutex<T> {
         Mutex {
             inner: box MUTEX_INIT,
@@ -201,9 +195,10 @@ impl<T: Send> Mutex<T> {
     ///
     /// 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<MutexGuard<T>> {
         unsafe { self.inner.lock.lock() }
-        MutexGuard::new(self)
+        MutexGuard::new(&*self.inner, &self.data)
     }
 
     /// Attempts to acquire this lock.
@@ -219,9 +214,10 @@ impl<T: Send> Mutex<T> {
     /// 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<MutexGuard<T>> {
         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<T: Send> Drop for Mutex<T> {
     }
 }
 
+static DUMMY: UnsafeCell<()> = UnsafeCell { value: () };
+
 impl StaticMutex {
     /// Acquires this lock, see `Mutex::lock`
     #[inline]
-    pub fn lock(&'static self) -> LockResult<StaticMutexGuard> {
+    #[unstable = "may be merged with Mutex in the future"]
+    pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
         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<StaticMutexGuard> {
+    #[unstable = "may be merged with Mutex in the future"]
+    pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
         if unsafe { self.lock.try_lock() } {
-            Ok(try!(StaticMutexGuard::new(self)))
+            Ok(try!(MutexGuard::new(self, &DUMMY)))
         } else {
             Err(TryLockError::WouldBlock)
         }
@@ -266,93 +266,54 @@ 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<T>) -> LockResult<MutexGuard<T>> {
-        poison::map_result(Guard::new(lock), |guard| {
-            MutexGuard { __inner: guard }
+    fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
+           -> LockResult<MutexGuard<'mutex, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            MutexGuard {
+                __lock: lock,
+                __data: data,
+                __poison: guard,
+                __marker: marker::NoSend,
+            }
         })
     }
 }
 
-impl<T> AsGuard for Mutex<T> {
-    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<T> for MutexGuard<'mutex, T> {
     fn deref<'a>(&'a self) -> &'a T {
-        unsafe { &*self.__inner.inner.data.get() }
+        unsafe { &*self.__data.get() }
     }
 }
 impl<'mutex, T> DerefMut<T> 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<StaticMutexGuard> {
-        poison::map_result(Guard::new(lock), |guard| {
-            StaticMutexGuard { inner: guard }
-        })
+        unsafe { &mut *self.__data.get() }
     }
 }
 
-impl AsGuard for StaticMutex {
-    #[inline]
-    fn as_guard(&self) -> CondvarGuard {
-        CondvarGuard { lock: &self.lock, poisoned: &self.poison }
-    }
-}
-
-impl AsGuard for StaticMutexGuard {
+#[unsafe_destructor]
+impl<'a, T> Drop for MutexGuard<'a, T> {
     #[inline]
-    fn as_guard(&self) -> CondvarGuard {
-        CondvarGuard {
-            lock: &self.inner.inner.lock,
-            poisoned: &self.inner.inner.poison,
+    fn drop(&mut self) {
+        unsafe {
+            self.__lock.poison.done(&self.__poison);
+            self.__lock.lock.unlock();
         }
     }
 }
 
-impl<'a, T: AsGuard> Guard<'a, T> {
-    #[inline]
-    fn new(t: &T) -> LockResult<Guard<T>> {
-        let data = t.as_guard();
-        poison::map_result(data.poisoned.borrow(), |guard| {
-            Guard {
-                inner: t,
-                poison: guard,
-                marker: marker::NoSend,
-            }
-        })
-    }
+pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
+    &guard.__lock.lock
 }
 
-#[unsafe_destructor]
-impl<'a, T: AsGuard> Drop for Guard<'a, T> {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            let data = self.inner.as_guard();
-            data.poisoned.done(&self.poison);
-            data.lock.unlock();
-        }
-    }
+pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
+    &guard.__lock.poison
 }
 
 #[cfg(test)]
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<T> {
     guard: T,
 }
 
 /// An enumeration of possible errors which can occur while calling the
 /// `try_lock` method.
+#[stable]
 pub enum TryLockError<T> {
     /// The lock could not be acquired because another task failed while holding
     /// the lock.
+    #[stable]
     Poisoned(PoisonError<T>),
     /// The lock could not be acquired at this time because the operation would
     /// otherwise block.
+    #[stable]
     WouldBlock,
 }
 
@@ -75,6 +79,7 @@ pub enum TryLockError<T> {
 /// 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<Guard> = Result<Guard, PoisonError<Guard>>;
 
 /// A type alias for the result of a nonblocking locking method.
@@ -82,6 +87,7 @@ pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
 /// 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<Guard> = Result<Guard, TryLockError<Guard>>;
 
 impl<T> fmt::Show for PoisonError<T> {
@@ -93,6 +99,7 @@ impl<T> fmt::Show for PoisonError<T> {
 impl<T> PoisonError<T> {
     /// 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<T> {
     inner: Box<StaticRWLock>,
     data: UnsafeCell<T>,
@@ -88,6 +89,7 @@ unsafe impl<T> Sync for RWLock<T> {}
 /// }
 /// 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<T>>,
+    __lock: &'a StaticRWLock,
+    __data: &'a UnsafeCell<T>,
+    __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<T>>,
-}
-
-/// 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<T>,
+    __poison: poison::Guard,
+    __marker: marker::NoSend,
 }
 
 impl<T: Send + Sync> RWLock<T> {
     /// Creates a new instance of an RWLock which is unlocked and read to go.
+    #[stable]
     pub fn new(t: T) -> RWLock<T> {
         RWLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) }
     }
@@ -170,9 +151,10 @@ impl<T: Send + Sync> RWLock<T> {
     /// 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<RWLockReadGuard<T>> {
         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<T: Send + Sync> RWLock<T> {
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
     #[inline]
+    #[stable]
     pub fn try_read(&self) -> TryLockResult<RWLockReadGuard<T>> {
         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<T: Send + Sync> RWLock<T> {
     /// 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<RWLockWriteGuard<T>> {
         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<T: Send + Sync> RWLock<T> {
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
     #[inline]
+    #[stable]
     pub fn try_write(&self) -> TryLockResult<RWLockWriteGuard<T>> {
         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<T> Drop for RWLock<T> {
     }
 }
 
+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<StaticRWLockReadGuard> {
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn read(&'static self) -> LockResult<RWLockReadGuard<'static, ()>> {
         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<StaticRWLockReadGuard> {
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn try_read(&'static self)
+                    -> TryLockResult<RWLockReadGuard<'static, ()>> {
         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<StaticRWLockWriteGuard> {
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn write(&'static self) -> LockResult<RWLockWriteGuard<'static, ()>> {
         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<StaticRWLockWriteGuard> {
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn try_write(&'static self)
+                     -> TryLockResult<RWLockWriteGuard<'static, ()>> {
         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<T>) -> LockResult<RWLockReadGuard<T>> {
-        poison::map_result(ReadGuard::new(lock), |guard| {
-            RWLockReadGuard { __inner: guard }
+    fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell<T>)
+           -> LockResult<RWLockReadGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |_| {
+            RWLockReadGuard {
+                __lock: lock,
+                __data: data,
+                __marker: marker::NoSend,
+            }
         })
     }
 }
 impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> {
-    fn new(lock: &RWLock<T>) -> LockResult<RWLockWriteGuard<T>> {
-        poison::map_result(WriteGuard::new(lock), |guard| {
-            RWLockWriteGuard { __inner: guard }
+    fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell<T>)
+           -> LockResult<RWLockWriteGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            RWLockWriteGuard {
+                __lock: lock,
+                __data: data,
+                __poison: guard,
+                __marker: marker::NoSend,
+            }
         })
     }
 }
 
 impl<'rwlock, T> Deref<T> 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<T> 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<T> 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<StaticRWLockReadGuard> {
-        poison::map_result(ReadGuard::new(lock), |guard| {
-            StaticRWLockReadGuard { _inner: guard }
-        })
-    }
-}
-impl StaticRWLockWriteGuard {
-    #[inline]
-    fn new(lock: &'static StaticRWLock) -> LockResult<StaticRWLockWriteGuard> {
-        poison::map_result(WriteGuard::new(lock), |guard| {
-            StaticRWLockWriteGuard { _inner: guard }
-        })
-    }
-}
-
-impl<T> AsStaticRWLock for RWLock<T> {
-    #[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<ReadGuard<'a, T>> {
-        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<WriteGuard<'a, T>> {
-        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(); }
     }
 }