diff options
| author | Kevin Ballard <kevin@sb.org> | 2014-02-16 20:23:05 -0800 |
|---|---|---|
| committer | Kevin Ballard <kevin@sb.org> | 2014-02-16 21:14:15 -0800 |
| commit | 66bed17641a348ec4f531135c33c6e76eb11527f (patch) | |
| tree | b66cc1c6e58a52c9bc4b19419e611eafcf9f99f2 | |
| parent | c8489069b43191c5298f17430933b3b88fb79c3c (diff) | |
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.
| -rw-r--r-- | src/libsync/arc.rs | 105 |
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] |
