提交 4fe12965 编写于 作者: B bors

auto merge of #10660 : alexcrichton/rust/little-scope, r=pcwalton

This moves the locking/waiting methods to returning an RAII struct instead of
relying on closures. Additionally, this changes the methods to all take
'&mut self' to discourage recursive locking. The new method to block is to call
`wait` on the returned RAII structure instead of calling it on the lock itself
(this enforces that the lock is held).

At the same time, this improves the Mutex interface a bit by allowing
destruction of non-initialized members and by allowing construction of an empty
mutex (nothing initialized inside).
......@@ -70,6 +70,15 @@ pub unsafe fn new() -> Mutex {
}
}
/// Creates a new mutex, with the lock/condition variable not initialized.
/// This is the same as initializing from the MUTEX_INIT static.
pub unsafe fn empty() -> Mutex {
Mutex {
lock: atomics::AtomicUint::new(0),
cond: atomics::AtomicUint::new(0),
}
}
/// Creates a new copy of this mutex. This is an unsafe operation because
/// there is no reference counting performed on this type.
///
......@@ -117,8 +126,10 @@ pub unsafe fn signal(&mut self) { imp::signal(self.getcond()) }
/// that no other thread is currently holding the lock or waiting on the
/// condition variable contained inside.
pub unsafe fn destroy(&mut self) {
imp::free_lock(self.lock.swap(0, atomics::Relaxed));
imp::free_cond(self.cond.swap(0, atomics::Relaxed));
let lock = self.lock.swap(0, atomics::Relaxed);
let cond = self.cond.swap(0, atomics::Relaxed);
if lock != 0 { imp::free_lock(lock) }
if cond != 0 { imp::free_cond(cond) }
}
unsafe fn getlock(&mut self) -> *c_void {
......@@ -333,4 +344,12 @@ fn somke_cond() {
t.join();
}
}
#[test]
fn destroy_immediately() {
unsafe {
let mut m = Mutex::empty();
m.destroy();
}
}
}
......@@ -319,67 +319,49 @@ pub struct LittleLock {
priv l: Mutex,
}
pub struct LittleGuard<'a> {
priv l: &'a mut Mutex,
}
impl Drop for LittleLock {
fn drop(&mut self) {
unsafe {
self.l.destroy();
}
unsafe { self.l.destroy(); }
}
}
#[unsafe_destructor]
impl<'a> Drop for LittleGuard<'a> {
fn drop(&mut self) {
unsafe { self.l.unlock(); }
}
}
impl LittleLock {
pub fn new() -> LittleLock {
unsafe {
LittleLock {
l: Mutex::new()
}
}
unsafe { LittleLock { l: Mutex::new() } }
}
pub unsafe fn lock<T>(&self, f: || -> T) -> T {
let this = cast::transmute_mut(self);
do atomically {
this.l.lock();
do (|| {
f()
}).finally {
this.l.unlock();
}
}
pub unsafe fn lock<'a>(&'a mut self) -> LittleGuard<'a> {
self.l.lock();
LittleGuard { l: &mut self.l }
}
pub unsafe fn try_lock<T>(&self, f: || -> T) -> Option<T> {
let this = cast::transmute_mut(self);
do atomically {
if this.l.trylock() {
Some(do (|| {
f()
}).finally {
this.l.unlock();
})
} else {
None
}
pub unsafe fn try_lock<'a>(&'a mut self) -> Option<LittleGuard<'a>> {
if self.l.trylock() {
Some(LittleGuard { l: &mut self.l })
} else {
None
}
}
pub unsafe fn signal(&self) {
let this = cast::transmute_mut(self);
this.l.signal();
pub unsafe fn signal(&mut self) {
self.l.signal();
}
}
pub unsafe fn lock_and_wait(&self, f: || -> bool) {
let this = cast::transmute_mut(self);
do atomically {
this.l.lock();
do (|| {
if f() {
this.l.wait();
}
}).finally {
this.l.unlock();
}
}
impl<'a> LittleGuard<'a> {
pub unsafe fn wait(&mut self) {
self.l.wait();
}
}
......@@ -431,15 +413,14 @@ pub fn new(user_data: T) -> Exclusive<T> {
#[inline]
pub unsafe fn with<U>(&self, f: |x: &mut T| -> U) -> U {
let rec = self.x.get();
do (*rec).lock.lock {
if (*rec).failed {
fail!("Poisoned Exclusive::new - another task failed inside!");
}
(*rec).failed = true;
let result = f(&mut (*rec).data);
(*rec).failed = false;
result
let _l = (*rec).lock.lock();
if (*rec).failed {
fail!("Poisoned Exclusive::new - another task failed inside!");
}
(*rec).failed = true;
let result = f(&mut (*rec).data);
(*rec).failed = false;
result
}
#[inline]
......@@ -452,28 +433,28 @@ pub unsafe fn with_imm<U>(&self, f: |x: &T| -> U) -> U {
#[inline]
pub unsafe fn hold_and_signal(&self, f: |x: &mut T|) {
let rec = self.x.get();
do (*rec).lock.lock {
if (*rec).failed {
fail!("Poisoned Exclusive::new - another task failed inside!");
}
(*rec).failed = true;
f(&mut (*rec).data);
(*rec).failed = false;
(*rec).lock.signal();
let _l = (*rec).lock.lock();
if (*rec).failed {
fail!("Poisoned Exclusive::new - another task failed inside!");
}
(*rec).failed = true;
f(&mut (*rec).data);
(*rec).failed = false;
(*rec).lock.signal();
}
#[inline]
pub unsafe fn hold_and_wait(&self, f: |x: &T| -> bool) {
let rec = self.x.get();
do (*rec).lock.lock_and_wait {
if (*rec).failed {
fail!("Poisoned Exclusive::new - another task failed inside!");
}
(*rec).failed = true;
let result = f(&(*rec).data);
(*rec).failed = false;
result
let mut l = (*rec).lock.lock();
if (*rec).failed {
fail!("Poisoned Exclusive::new - another task failed inside!");
}
(*rec).failed = true;
let result = f(&(*rec).data);
(*rec).failed = false;
if result {
l.wait();
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册