about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-11-26 02:52:04 -0800
committerbors <bors@rust-lang.org>2013-11-26 02:52:04 -0800
commit4fe129651167e4ba1a16d6ee93bc0ca38c7cf7fa (patch)
tree96637056faae22b8e417b327d8de942ce1c75d65 /src/libstd
parent21990cdda624f5eee340311b7f8e542ab8a218e1 (diff)
parentac59888d8f466522a9802ee7d33134505794ee12 (diff)
downloadrust-4fe129651167e4ba1a16d6ee93bc0ca38c7cf7fa.tar.gz
rust-4fe129651167e4ba1a16d6ee93bc0ca38c7cf7fa.zip
auto merge of #10660 : alexcrichton/rust/little-scope, r=pcwalton
This moves the locking/waiting methods to returning an RAII struct instead of
relying on closures. Additionally, this changes the methods to all take
'&mut self' to discourage recursive locking. The new method to block is to call
`wait` on the returned RAII structure instead of calling it on the lock itself
(this enforces that the lock is held).

At the same time, this improves the Mutex interface a bit by allowing
destruction of non-initialized members and by allowing construction of an empty
mutex (nothing initialized inside).
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/unstable/mutex.rs23
-rw-r--r--src/libstd/unstable/sync.rs119
2 files changed, 71 insertions, 71 deletions
diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs
index 5be9be7bf8a..ff46824d823 100644
--- a/src/libstd/unstable/mutex.rs
+++ b/src/libstd/unstable/mutex.rs
@@ -70,6 +70,15 @@ impl Mutex {
         }
     }
 
+    /// Creates a new mutex, with the lock/condition variable not initialized.
+    /// This is the same as initializing from the MUTEX_INIT static.
+    pub unsafe fn empty() -> Mutex {
+        Mutex {
+            lock: atomics::AtomicUint::new(0),
+            cond: atomics::AtomicUint::new(0),
+        }
+    }
+
     /// Creates a new copy of this mutex. This is an unsafe operation because
     /// there is no reference counting performed on this type.
     ///
@@ -117,8 +126,10 @@ impl Mutex {
     /// that no other thread is currently holding the lock or waiting on the
     /// condition variable contained inside.
     pub unsafe fn destroy(&mut self) {
-        imp::free_lock(self.lock.swap(0, atomics::Relaxed));
-        imp::free_cond(self.cond.swap(0, atomics::Relaxed));
+        let lock = self.lock.swap(0, atomics::Relaxed);
+        let cond = self.cond.swap(0, atomics::Relaxed);
+        if lock != 0 { imp::free_lock(lock) }
+        if cond != 0 { imp::free_cond(cond) }
     }
 
     unsafe fn getlock(&mut self) -> *c_void {
@@ -333,4 +344,12 @@ mod test {
             t.join();
         }
     }
+
+    #[test]
+    fn destroy_immediately() {
+        unsafe {
+            let mut m = Mutex::empty();
+            m.destroy();
+        }
+    }
 }
diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs
index f22a707fef6..e80b58d01ef 100644
--- a/src/libstd/unstable/sync.rs
+++ b/src/libstd/unstable/sync.rs
@@ -319,67 +319,49 @@ pub struct LittleLock {
     priv l: Mutex,
 }
 
+pub struct LittleGuard<'a> {
+    priv l: &'a mut Mutex,
+}
+
 impl Drop for LittleLock {
     fn drop(&mut self) {
-        unsafe {
-            self.l.destroy();
-        }
+        unsafe { self.l.destroy(); }
+    }
+}
+
+#[unsafe_destructor]
+impl<'a> Drop for LittleGuard<'a> {
+    fn drop(&mut self) {
+        unsafe { self.l.unlock(); }
     }
 }
 
 impl LittleLock {
     pub fn new() -> LittleLock {
-        unsafe {
-            LittleLock {
-                l: Mutex::new()
-            }
-        }
+        unsafe { LittleLock { l: Mutex::new() } }
     }
 
-    pub unsafe fn lock<T>(&self, f: || -> T) -> T {
-        let this = cast::transmute_mut(self);
-        do atomically {
-            this.l.lock();
-            do (|| {
-                f()
-            }).finally {
-                this.l.unlock();
-            }
-        }
+    pub unsafe fn lock<'a>(&'a mut self) -> LittleGuard<'a> {
+        self.l.lock();
+        LittleGuard { l: &mut self.l }
     }
 
-    pub unsafe fn try_lock<T>(&self, f: || -> T) -> Option<T> {
-        let this = cast::transmute_mut(self);
-        do atomically {
-            if this.l.trylock() {
-                Some(do (|| {
-                    f()
-                }).finally {
-                    this.l.unlock();
-                })
-            } else {
-                None
-            }
+    pub unsafe fn try_lock<'a>(&'a mut self) -> Option<LittleGuard<'a>> {
+        if self.l.trylock() {
+            Some(LittleGuard { l: &mut self.l })
+        } else {
+            None
         }
     }
 
-    pub unsafe fn signal(&self) {
-        let this = cast::transmute_mut(self);
-        this.l.signal();
+    pub unsafe fn signal(&mut self) {
+        self.l.signal();
     }
+}
 
-    pub unsafe fn lock_and_wait(&self, f: || -> bool) {
-        let this = cast::transmute_mut(self);
-        do atomically {
-            this.l.lock();
-            do (|| {
-                if f() {
-                    this.l.wait();
-                }
-            }).finally {
-                this.l.unlock();
-            }
-        }
+impl<'a> LittleGuard<'a> {
+    pub unsafe fn wait(&mut self) {
+        self.l.wait();
     }
 }
 
@@ -431,15 +413,14 @@ impl<T:Send> Exclusive<T> {
     #[inline]
     pub unsafe fn with<U>(&self, f: |x: &mut T| -> U) -> U {
         let rec = self.x.get();
-        do (*rec).lock.lock {
-            if (*rec).failed {
-                fail!("Poisoned Exclusive::new - another task failed inside!");
-            }
-            (*rec).failed = true;
-            let result = f(&mut (*rec).data);
-            (*rec).failed = false;
-            result
+        let _l = (*rec).lock.lock();
+        if (*rec).failed {
+            fail!("Poisoned Exclusive::new - another task failed inside!");
         }
+        (*rec).failed = true;
+        let result = f(&mut (*rec).data);
+        (*rec).failed = false;
+        result
     }
 
     #[inline]
@@ -452,28 +433,28 @@ impl<T:Send> Exclusive<T> {
     #[inline]
     pub unsafe fn hold_and_signal(&self, f: |x: &mut T|) {
         let rec = self.x.get();
-        do (*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();
+        let _l = (*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();
     }
 
     #[inline]
     pub unsafe fn hold_and_wait(&self, f: |x: &T| -> bool) {
         let rec = self.x.get();
-        do (*rec).lock.lock_and_wait {
-            if (*rec).failed {
-                fail!("Poisoned Exclusive::new - another task failed inside!");
-            }
-            (*rec).failed = true;
-            let result = f(&(*rec).data);
-            (*rec).failed = false;
-            result
+        let mut l = (*rec).lock.lock();
+        if (*rec).failed {
+            fail!("Poisoned Exclusive::new - another task failed inside!");
+        }
+        (*rec).failed = true;
+        let result = f(&(*rec).data);
+        (*rec).failed = false;
+        if result {
+            l.wait();
         }
     }