about summary refs log tree commit diff
path: root/src/libsync
diff options
context:
space:
mode:
authorKevin Ballard <kevin@sb.org>2014-02-16 20:23:05 -0800
committerKevin Ballard <kevin@sb.org>2014-02-16 21:14:15 -0800
commit66bed17641a348ec4f531135c33c6e76eb11527f (patch)
treeb66cc1c6e58a52c9bc4b19419e611eafcf9f99f2 /src/libsync
parentc8489069b43191c5298f17430933b3b88fb79c3c (diff)
downloadrust-66bed17641a348ec4f531135c33c6e76eb11527f.tar.gz
rust-66bed17641a348ec4f531135c33c6e76eb11527f.zip
Remove Freeze bounds from sync::MutexArc
With Rc no longer trying to statically prevent cycles (and thus no
longer using the Freeze bound), it seems appropriate to remove that
restriction from MutexArc as well.
Diffstat (limited to 'src/libsync')
-rw-r--r--src/libsync/arc.rs105
1 files changed, 33 insertions, 72 deletions
diff --git a/src/libsync/arc.rs b/src/libsync/arc.rs
index 0e53ecd416a..db4260a30ee 100644
--- a/src/libsync/arc.rs
+++ b/src/libsync/arc.rs
@@ -192,12 +192,6 @@ impl<T:Send> MutexArc<T> {
      * other tasks wishing to access the data will block until the closure
      * finishes running.
      *
-     * The reason this function is 'unsafe' is because it is possible to
-     * construct a circular reference among multiple Arcs by mutating the
-     * underlying data. This creates potential for deadlock, but worse, this
-     * will guarantee a memory leak of all involved Arcs. Using MutexArcs
-     * inside of other Arcs is safe in absence of circular references.
-     *
      * If you wish to nest MutexArcs, one strategy for ensuring safety at
      * runtime is to add a "nesting level counter" inside the stored data, and
      * when traversing the arcs, assert that they monotonically decrease.
@@ -210,63 +204,33 @@ impl<T:Send> MutexArc<T> {
      * blocked on the mutex) will also fail immediately.
      */
     #[inline]
-    pub unsafe fn unsafe_access<U>(&self, blk: |x: &mut T| -> U) -> U {
+    pub fn access<U>(&self, blk: |x: &mut T| -> U) -> U {
         let state = self.x.get();
-        // Borrowck would complain about this if the function were
-        // not already unsafe. See borrow_rwlock, far below.
-        (&(*state).lock).lock(|| {
-            check_poison(true, (*state).failed);
-            let _z = PoisonOnFail::new(&mut (*state).failed);
-            blk(&mut (*state).data)
-        })
+        unsafe {
+            // Borrowck would complain about this if the code were
+            // not already unsafe. See borrow_rwlock, far below.
+            (&(*state).lock).lock(|| {
+                check_poison(true, (*state).failed);
+                let _z = PoisonOnFail::new(&mut (*state).failed);
+                blk(&mut (*state).data)
+            })
+        }
     }
 
-    /// As unsafe_access(), but with a condvar, as sync::mutex.lock_cond().
+    /// As access(), but with a condvar, as sync::mutex.lock_cond().
     #[inline]
-    pub unsafe fn unsafe_access_cond<U>(&self,
-                                        blk: |x: &mut T, c: &Condvar| -> U)
-                                        -> U {
+    pub fn access_cond<U>(&self, blk: |x: &mut T, c: &Condvar| -> U) -> U {
         let state = self.x.get();
-        (&(*state).lock).lock_cond(|cond| {
-            check_poison(true, (*state).failed);
-            let _z = PoisonOnFail::new(&mut (*state).failed);
-            blk(&mut (*state).data,
-                &Condvar {is_mutex: true,
-                          failed: &(*state).failed,
-                          cond: cond })
-        })
-    }
-}
-
-impl<T:Freeze + Send> MutexArc<T> {
-
-    /**
-     * As unsafe_access.
-     *
-     * The difference between access and unsafe_access is that the former
-     * forbids mutexes to be nested. While unsafe_access can be used on
-     * MutexArcs without freezable interiors, this safe version of access
-     * requires the Freeze bound, which prohibits access on MutexArcs which
-     * might contain nested MutexArcs inside.
-     *
-     * The purpose of this is to offer a safe implementation of MutexArc to be
-     * used instead of RWArc in cases where no readers are needed and slightly
-     * better performance is required.
-     *
-     * Both methods have the same failure behaviour as unsafe_access and
-     * unsafe_access_cond.
-     */
-    #[inline]
-    pub fn access<U>(&self, blk: |x: &mut T| -> U) -> U {
-        unsafe { self.unsafe_access(blk) }
-    }
-
-    /// As unsafe_access_cond but safe and Freeze.
-    #[inline]
-    pub fn access_cond<U>(&self,
-                          blk: |x: &mut T, c: &Condvar| -> U)
-                          -> U {
-        unsafe { self.unsafe_access_cond(blk) }
+        unsafe {
+            (&(*state).lock).lock_cond(|cond| {
+                check_poison(true, (*state).failed);
+                let _z = PoisonOnFail::new(&mut (*state).failed);
+                blk(&mut (*state).data,
+                    &Condvar {is_mutex: true,
+                            failed: &(*state).failed,
+                            cond: cond })
+            })
+        }
     }
 }
 
@@ -590,7 +554,6 @@ impl<T:Clone+Send+Freeze> CowArc<T> {
 
 impl<T:Clone+Send+Freeze> Clone for CowArc<T> {
     /// Duplicate a Copy-on-write Arc. See arc::clone for more details.
-    #[inline]
     fn clone(&self) -> CowArc<T> {
         CowArc { x: self.x.clone() }
     }
@@ -692,20 +655,18 @@ mod tests {
     }
 
     #[test]
-    fn test_unsafe_mutex_arc_nested() {
-        unsafe {
-            // Tests nested mutexes and access
-            // to underlaying data.
-            let arc = ~MutexArc::new(1);
-            let arc2 = ~MutexArc::new(*arc);
-            task::spawn(proc() {
-                (*arc2).unsafe_access(|mutex| {
-                    (*mutex).access(|one| {
-                        assert!(*one == 1);
-                    })
+    fn test_mutex_arc_nested() {
+        // Tests nested mutexes and access
+        // to underlaying data.
+        let arc = ~MutexArc::new(1);
+        let arc2 = ~MutexArc::new(*arc);
+        task::spawn(proc() {
+            (*arc2).access(|mutex| {
+                (*mutex).access(|one| {
+                    assert!(*one == 1);
                 })
-            });
-        }
+            })
+        });
     }
 
     #[test]