diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs index fd92bf2bdc6..fce8e003e90 100644 --- a/src/libstd/unstable/atomics.rs +++ b/src/libstd/unstable/atomics.rs @@ -15,6 +15,8 @@ use unstable::intrinsics; use cast; use option::{Option,Some,None}; +use libc::c_void; +use ops::Drop; pub struct AtomicFlag { priv v: int @@ -36,6 +38,10 @@ pub struct AtomicPtr { priv p: *mut T } +pub struct AtomicOption { + priv p: *mut c_void +} + pub enum Ordering { Release, Acquire, @@ -53,7 +59,7 @@ impl AtomicFlag { * Clears the atomic flag */ #[inline(always)] - fn clear(&mut self, order:Ordering) { + fn clear(&mut self, order: Ordering) { unsafe {atomic_store(&mut self.v, 0, order)} } @@ -62,37 +68,37 @@ impl AtomicFlag { * Sets the flag if it was previously unset, returns the previous value of the * flag. */ - fn test_and_set(&mut self, order:Ordering) -> bool { + fn test_and_set(&mut self, order: Ordering) -> bool { unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0} } } impl AtomicBool { - fn new(v:bool) -> AtomicBool { + fn new(v: bool) -> AtomicBool { AtomicBool { v: if v { 1 } else { 0 } } } #[inline(always)] - fn load(&self, order:Ordering) -> bool { + fn load(&self, order: Ordering) -> bool { unsafe { atomic_load(&self.v, order) > 0 } } #[inline(always)] - fn store(&mut self, val:bool, order:Ordering) { + fn store(&mut self, val: bool, order: Ordering) { let val = if val { 1 } else { 0 }; unsafe { atomic_store(&mut self.v, val, order); } } #[inline(always)] - fn swap(&mut self, val:bool, order:Ordering) -> bool { + fn swap(&mut self, val: bool, order: Ordering) -> bool { let val = if val { 1 } else { 0 }; unsafe { atomic_swap(&mut self.v, val, order) > 0} } #[inline(always)] - fn compare_and_swap(&mut self, old: bool, new: bool, order:Ordering) -> bool { + fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool { let old = if old { 1 } else { 0 }; let new = if new { 1 } else { 0 }; @@ -101,100 +107,153 @@ impl AtomicBool { } impl AtomicInt { - fn new(v:int) -> AtomicInt { + fn new(v: int) -> AtomicInt { AtomicInt { v:v } } #[inline(always)] - fn load(&self, order:Ordering) -> int { + fn load(&self, order: Ordering) -> int { unsafe { atomic_load(&self.v, order) } } #[inline(always)] - fn store(&mut self, val:int, order:Ordering) { + fn store(&mut self, val: int, order: Ordering) { unsafe { atomic_store(&mut self.v, val, order); } } #[inline(always)] - fn swap(&mut self, val:int, order:Ordering) -> int { + fn swap(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_swap(&mut self.v, val, order) } } #[inline(always)] - fn compare_and_swap(&mut self, old: int, new: int, order:Ordering) -> int { + fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int { unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } } #[inline(always)] - fn fetch_add(&mut self, val:int, order:Ordering) -> int { + fn fetch_add(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_add(&mut self.v, val, order) } } #[inline(always)] - fn fetch_sub(&mut self, val:int, order:Ordering) -> int { + fn fetch_sub(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_sub(&mut self.v, val, order) } } } impl AtomicUint { - fn new(v:uint) -> AtomicUint { + fn new(v: uint) -> AtomicUint { AtomicUint { v:v } } #[inline(always)] - fn load(&self, order:Ordering) -> uint { + fn load(&self, order: Ordering) -> uint { unsafe { atomic_load(&self.v, order) } } #[inline(always)] - fn store(&mut self, val:uint, order:Ordering) { + fn store(&mut self, val: uint, order: Ordering) { unsafe { atomic_store(&mut self.v, val, order); } } #[inline(always)] - fn swap(&mut self, val:uint, order:Ordering) -> uint { + fn swap(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_swap(&mut self.v, val, order) } } #[inline(always)] - fn compare_and_swap(&mut self, old: uint, new: uint, order:Ordering) -> uint { + fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint { unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } } #[inline(always)] - fn fetch_add(&mut self, val:uint, order:Ordering) -> uint { + fn fetch_add(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_add(&mut self.v, val, order) } } #[inline(always)] - fn fetch_sub(&mut self, val:uint, order:Ordering) -> uint { + fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_sub(&mut self.v, val, order) } } } impl AtomicPtr { - fn new(p:*mut T) -> AtomicPtr { + fn new(p: *mut T) -> AtomicPtr { AtomicPtr { p:p } } #[inline(always)] - fn load(&self, order:Ordering) -> *mut T { + fn load(&self, order: Ordering) -> *mut T { unsafe { atomic_load(&self.p, order) } } #[inline(always)] - fn store(&mut self, ptr:*mut T, order:Ordering) { + fn store(&mut self, ptr: *mut T, order: Ordering) { unsafe { atomic_store(&mut self.p, ptr, order); } } #[inline(always)] - fn swap(&mut self, ptr:*mut T, order:Ordering) -> *mut T { + fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(&mut self.p, ptr, order) } } #[inline(always)] - fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order:Ordering) -> *mut T { - unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } + fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T { + unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) } + } +} + +impl AtomicOption { + fn new(p: ~T) -> AtomicOption { + unsafe { + AtomicOption { + p: cast::transmute(p) + } + } + } + + fn empty() -> AtomicOption { + unsafe { + AtomicOption { + p: cast::transmute(0) + } + } + } + + #[inline(always)] + fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> { + unsafe { + let val = cast::transmute(val); + + let p = atomic_swap(&mut self.p, val, order); + let pv : &uint = cast::transmute(&p); + + if *pv == 0 { + None + } else { + Some(cast::transmute(p)) + } + } + } + + #[inline(always)] + fn take(&mut self, order: Ordering) -> Option<~T> { + unsafe { + self.swap(cast::transmute(0), order) + } + } +} + +#[unsafe_destructor] +impl Drop for AtomicOption { + fn finalize(&self) { + // This will ensure that the contained data is + // destroyed, unless it's null. + unsafe { + let this : &mut AtomicOption = cast::transmute(self); + let _ = this.take(SeqCst); + } } } @@ -284,8 +343,8 @@ mod test { } #[test] - fn pointer_swap() { - let mut p = AtomicPtr::new(~1); + fn option_swap() { + let mut p = AtomicOption::new(~1); let a = ~2; let b = p.swap(a, SeqCst); @@ -295,15 +354,14 @@ mod test { } #[test] - fn pointer_take() { - let mut p = AtomicPtr::new(~1); + fn option_take() { + let mut p = AtomicOption::new(~1); assert_eq!(p.take(SeqCst), Some(~1)); assert_eq!(p.take(SeqCst), None); - assert!(p.taken(SeqCst)); let p2 = ~2; - p.give(p2, SeqCst); + p.swap(p2, SeqCst); assert_eq!(p.take(SeqCst), Some(~2)); }