diff --git a/src/libsync/arc.rs b/src/libsync/arc.rs index 0e53ecd416a7a..db4260a30ee11 100644 --- a/src/libsync/arc.rs +++ b/src/libsync/arc.rs @@ -192,12 +192,6 @@ impl MutexArc { * 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 MutexArc { * blocked on the mutex) will also fail immediately. */ #[inline] - pub unsafe fn unsafe_access(&self, blk: |x: &mut T| -> U) -> U { + pub fn access(&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(&self, - blk: |x: &mut T, c: &Condvar| -> U) - -> U { + pub fn access_cond(&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 MutexArc { - - /** - * 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(&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(&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 CowArc { impl Clone for CowArc { /// Duplicate a Copy-on-write Arc. See arc::clone for more details. - #[inline] fn clone(&self) -> CowArc { 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] diff --git a/src/test/compile-fail/mutex-arc-nested.rs b/src/test/compile-fail/mutex-arc-nested.rs deleted file mode 100644 index 34c56f98404d3..0000000000000 --- a/src/test/compile-fail/mutex-arc-nested.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate sync; - -use std::task; -use sync::MutexArc; - -fn test_mutex_arc_nested() { - let arc = ~MutexArc::new(1); - let arc2 = ~MutexArc::new(*arc); - - task::spawn(proc() { - (*arc2).access(|mutex| { //~ ERROR instantiating a type parameter with an incompatible type - }) - }); -} - -fn main() {}