Skip to content
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