about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2014-02-15 12:01:52 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2014-02-16 10:13:56 +1100
commit0937f659993631da3b3ddc198dd502c58d1634c6 (patch)
tree3b241161b563b4ef77a840188d822522e26ef174 /src/libstd
parentb87ed605c0ef27f5532ec30c92128bd890de5955 (diff)
downloadrust-0937f659993631da3b3ddc198dd502c58d1634c6.tar.gz
rust-0937f659993631da3b3ddc198dd502c58d1634c6.zip
std: add a NativeMutex type as a wrapper to destroy StaticNativeMutex.
This obsoletes LittleLock, and so it is removed.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/unstable/mutex.rs118
-rw-r--r--src/libstd/unstable/sync.rs54
2 files changed, 107 insertions, 65 deletions
diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs
index d8d051236b3..d217e90522c 100644
--- a/src/libstd/unstable/mutex.rs
+++ b/src/libstd/unstable/mutex.rs
@@ -8,44 +8,50 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! A native mutex and condition variable type
+//! A native mutex and condition variable type.
 //!
 //! This module contains bindings to the platform's native mutex/condition
-//! variable primitives. It provides a single type, `StaticNativeMutex`, which can be
-//! statically initialized via the `NATIVE_MUTEX_INIT` value. This object serves as
-//! both a mutex and a condition variable simultaneously.
+//! variable primitives. It provides two types: `StaticNativeMutex`, which can
+//! be statically initialized via the `NATIVE_MUTEX_INIT` value, and a simple
+//! wrapper `NativeMutex` that has a destructor to clean up after itself. These
+//! objects serve as both mutexes and condition variables simultaneously.
 //!
-//! The lock is lazily initialized, but it can only be unsafely destroyed. A
-//! statically initialized lock doesn't necessarily have a time at which it can
-//! get deallocated. For this reason, there is no `Drop` implementation of the
-//! mutex, but rather the `destroy()` method must be invoked manually if
-//! destruction of the mutex is desired.
+//! The static lock is lazily initialized, but it can only be unsafely
+//! destroyed. A statically initialized lock doesn't necessarily have a time at
+//! which it can get deallocated. For this reason, there is no `Drop`
+//! implementation of the static mutex, but rather the `destroy()` method must
+//! be invoked manually if destruction of the mutex is desired.
 //!
-//! It is not recommended to use this type for idiomatic rust use. This type is
-//! appropriate where no other options are available, but other rust concurrency
-//! primitives should be used before this type.
+//! The non-static `NativeMutex` type does have a destructor, but cannot be
+//! statically initialized.
+//!
+//! It is not recommended to use this type for idiomatic rust use. These types
+//! are appropriate where no other options are available, but other rust
+//! concurrency primitives should be used before them.
 //!
 //! # Example
 //!
 //!     use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
 //!
 //!     // Use a statically initialized mutex
-//!     static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
+//!     static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
 //!
 //!     unsafe {
-//!         let _guard = lock.lock();
+//!         let _guard = LOCK.lock();
 //!     } // automatically unlocked here
 //!
 //!     // Use a normally initialized mutex
 //!     unsafe {
-//!         let mut lock = StaticNativeMutex::new();
+//!         let mut lock = NativeMutex::new();
+//!
+//!         {
+//!             let _guard = lock.lock();
+//!         } // unlocked here
 //!
 //!         // sometimes the RAII guard isn't appropriate
 //!         lock.lock_noguard();
 //!         lock.unlock_noguard();
-//!
-//!         lock.destroy();
-//!     }
+//!     } // `lock` is deallocated here
 
 #[allow(non_camel_case_types)];
 
@@ -54,10 +60,20 @@ use ops::Drop;
 
 /// A native mutex suitable for storing in statics (that is, it has
 /// the `destroy` method rather than a destructor).
+///
+/// Prefer the `NativeMutex` type where possible.
 pub struct StaticNativeMutex {
     priv inner: imp::Mutex,
 }
 
+/// A native mutex with a destructor for clean-up.
+///
+/// See `StaticNativeMutex` for a version that is suitable for storing in
+/// statics.
+pub struct NativeMutex {
+    priv inner: StaticNativeMutex
+}
+
 /// Automatically unlocks the mutex that it was created from on
 /// destruction.
 ///
@@ -144,6 +160,72 @@ impl StaticNativeMutex {
     pub unsafe fn destroy(&mut self) { self.inner.destroy() }
 }
 
+impl NativeMutex {
+    /// Creates a new mutex.
+    ///
+    /// The user must be careful to ensure the mutex is not locked when its is
+    /// being destroyed.
+    pub unsafe fn new() -> NativeMutex {
+        NativeMutex { inner: StaticNativeMutex::new() }
+    }
+
+    /// Acquires this lock. This assumes that the current thread does not
+    /// already hold the lock.
+    ///
+    /// # Example
+    /// ```rust
+    /// use std::unstable::mutex::NativeMutex;
+    /// let mut lock = NativeMutex::new();
+    /// unsafe {
+    ///     let _guard = lock.lock();
+    ///     // critical section...
+    /// } // automatically unlocked in `_guard`'s destructor
+    /// ```
+    pub unsafe fn lock<'a>(&'a mut self) -> LockGuard<'a> {
+        self.inner.lock()
+    }
+
+    /// Attempts to acquire the lock. The value returned is `Some` if
+    /// the attempt succeeded.
+    pub unsafe fn trylock<'a>(&'a mut self) -> Option<LockGuard<'a>> {
+        self.inner.trylock()
+    }
+
+    /// Acquire the lock without creating a `LockGuard`.
+    ///
+    /// Prefer using `.lock`.
+    pub unsafe fn lock_noguard(&mut self) { self.inner.lock_noguard() }
+
+    /// Attempts to acquire the lock without creating a
+    /// `LockGuard`. The value returned is whether the lock was
+    /// acquired or not.
+    ///
+    /// Prefer using `.trylock`.
+    pub unsafe fn trylock_noguard(&mut self) -> bool {
+        self.inner.trylock_noguard()
+    }
+
+    /// Unlocks the lock. This assumes that the current thread already holds the
+    /// lock.
+    pub unsafe fn unlock_noguard(&mut self) { self.inner.unlock_noguard() }
+
+    /// Block on the internal condition variable.
+    ///
+    /// This function assumes that the lock is already held. Prefer
+    /// using `LockGuard.wait` since that guarantees that the lock is
+    /// held.
+    pub unsafe fn wait_noguard(&mut self) { self.inner.wait_noguard() }
+
+    /// Signals a thread in `wait` to wake up
+    pub unsafe fn signal_noguard(&mut self) { self.inner.signal_noguard() }
+}
+
+impl Drop for NativeMutex {
+    fn drop(&mut self) {
+        unsafe {self.inner.destroy()}
+    }
+}
+
 impl<'a> LockGuard<'a> {
     /// Block on the internal condition variable.
     pub unsafe fn wait(&mut self) {
diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs
index 0a6de50bf23..93322977bc1 100644
--- a/src/libstd/unstable/sync.rs
+++ b/src/libstd/unstable/sync.rs
@@ -10,51 +10,11 @@
 
 use clone::Clone;
 use kinds::Send;
-use ops::Drop;
-use option::Option;
 use sync::arc::UnsafeArc;
-use unstable::mutex::{StaticNativeMutex, LockGuard};
-
-pub struct LittleLock {
-    priv l: StaticNativeMutex,
-}
-
-pub struct LittleGuard<'a> {
-    priv l: LockGuard<'a>
-}
-
-impl Drop for LittleLock {
-    fn drop(&mut self) {
-        unsafe { self.l.destroy(); }
-    }
-}
-
-impl LittleLock {
-    pub fn new() -> LittleLock {
-        unsafe { LittleLock { l: StaticNativeMutex::new() } }
-    }
-
-    pub unsafe fn lock<'a>(&'a mut self) -> LittleGuard<'a> {
-        LittleGuard { l: self.l.lock() }
-    }
-
-    pub unsafe fn try_lock<'a>(&'a mut self) -> Option<LittleGuard<'a>> {
-        self.l.trylock().map(|guard| LittleGuard { l: guard })
-    }
-
-    pub unsafe fn signal(&mut self) {
-        self.l.signal_noguard();
-    }
-}
-
-impl<'a> LittleGuard<'a> {
-    pub unsafe fn wait(&mut self) {
-        self.l.wait();
-    }
-}
+use unstable::mutex::NativeMutex;
 
 struct ExData<T> {
-    lock: LittleLock,
+    lock: NativeMutex,
     failed: bool,
     data: T,
 }
@@ -83,7 +43,7 @@ impl<T:Send> Clone for Exclusive<T> {
 impl<T:Send> Exclusive<T> {
     pub fn new(user_data: T) -> Exclusive<T> {
         let data = ExData {
-            lock: LittleLock::new(),
+            lock: unsafe {NativeMutex::new()},
             failed: false,
             data: user_data
         };
@@ -92,8 +52,8 @@ impl<T:Send> Exclusive<T> {
         }
     }
 
-    // Exactly like std::arc::MutexArc,access(), but with the LittleLock
-    // instead of a proper mutex. Same reason for being unsafe.
+    // Exactly like sync::MutexArc.access(). Same reason for being
+    // unsafe.
     //
     // Currently, scheduling operations (i.e., descheduling, receiving on a pipe,
     // accessing the provided condition variable) are prohibited while inside
@@ -119,14 +79,14 @@ impl<T:Send> Exclusive<T> {
     #[inline]
     pub unsafe fn hold_and_signal(&self, f: |x: &mut T|) {
         let rec = self.x.get();
-        let _l = (*rec).lock.lock();
+        let mut guard = (*rec).lock.lock();
         if (*rec).failed {
             fail!("Poisoned Exclusive::new - another task failed inside!");
         }
         (*rec).failed = true;
         f(&mut (*rec).data);
         (*rec).failed = false;
-        (*rec).lock.signal();
+        guard.signal();
     }
 
     #[inline]