mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
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.
This commit is contained in:
parent
c8489069b4
commit
66bed17641
@ -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 {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
/// As unsafe_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 {
|
||||
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) }
|
||||
let state = self.x.get();
|
||||
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_cond but safe and Freeze.
|
||||
/// As access(), but with a condvar, as sync::mutex.lock_cond().
|
||||
#[inline]
|
||||
pub fn access_cond<U>(&self,
|
||||
blk: |x: &mut T, c: &Condvar| -> U)
|
||||
-> U {
|
||||
unsafe { self.unsafe_access_cond(blk) }
|
||||
pub fn access_cond<U>(&self, blk: |x: &mut T, c: &Condvar| -> U) -> U {
|
||||
let state = self.x.get();
|
||||
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]
|
||||
|
Loading…
Reference in New Issue
Block a user