]> git.lizzy.rs Git - rust.git/commitdiff
Remove Freeze bounds from sync::MutexArc
authorKevin Ballard <kevin@sb.org>
Mon, 17 Feb 2014 04:23:05 +0000 (20:23 -0800)
committerKevin Ballard <kevin@sb.org>
Mon, 17 Feb 2014 05:14:15 +0000 (21:14 -0800)
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.

src/libsync/arc.rs

index 0e53ecd416a7ab4beab4e4e0b98452b6263b7f65..db4260a30ee113886ae7f9274520746eb590f524 100644 (file)
@@ -192,12 +192,6 @@ pub fn new_with_condvars(user_data: T, num_condvars: uint) -> 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 @@ pub fn new_with_condvars(user_data: T, num_condvars: uint) -> 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 @@ pub fn get_mut<'a>(&'a mut self) -> &'a mut 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 @@ fn test_mutex_arc_poison() {
     }
 
     #[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]