Skip to content

Move LittleLock to using RAII #10660

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 26, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/libstd/unstable/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ impl 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.
///
Expand Down Expand Up @@ -117,8 +126,10 @@ impl Mutex {
/// 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 {
Expand Down Expand Up @@ -333,4 +344,12 @@ mod test {
t.join();
}
}

#[test]
fn destroy_immediately() {
unsafe {
let mut m = Mutex::empty();
m.destroy();
}
}
}
119 changes: 50 additions & 69 deletions src/libstd/unstable/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down Expand Up @@ -431,15 +413,14 @@ impl<T:Send> 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]
Expand All @@ -452,28 +433,28 @@ impl<T:Send> Exclusive<T> {
#[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();
}
}

Expand Down