Add AtomicOption type
This commit is contained in:
parent
008e6e5e7e
commit
30b471bf23
@ -15,6 +15,8 @@
|
|||||||
use unstable::intrinsics;
|
use unstable::intrinsics;
|
||||||
use cast;
|
use cast;
|
||||||
use option::{Option,Some,None};
|
use option::{Option,Some,None};
|
||||||
|
use libc::c_void;
|
||||||
|
use ops::Drop;
|
||||||
|
|
||||||
pub struct AtomicFlag {
|
pub struct AtomicFlag {
|
||||||
priv v: int
|
priv v: int
|
||||||
@ -36,6 +38,10 @@ pub struct AtomicPtr<T> {
|
|||||||
priv p: *mut T
|
priv p: *mut T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AtomicOption<T> {
|
||||||
|
priv p: *mut c_void
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Ordering {
|
pub enum Ordering {
|
||||||
Release,
|
Release,
|
||||||
Acquire,
|
Acquire,
|
||||||
@ -53,7 +59,7 @@ impl AtomicFlag {
|
|||||||
* Clears the atomic flag
|
* Clears the atomic flag
|
||||||
*/
|
*/
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clear(&mut self, order:Ordering) {
|
fn clear(&mut self, order: Ordering) {
|
||||||
unsafe {atomic_store(&mut self.v, 0, order)}
|
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
|
* Sets the flag if it was previously unset, returns the previous value of the
|
||||||
* flag.
|
* 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}
|
unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtomicBool {
|
impl AtomicBool {
|
||||||
fn new(v:bool) -> AtomicBool {
|
fn new(v: bool) -> AtomicBool {
|
||||||
AtomicBool { v: if v { 1 } else { 0 } }
|
AtomicBool { v: if v { 1 } else { 0 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn load(&self, order:Ordering) -> bool {
|
fn load(&self, order: Ordering) -> bool {
|
||||||
unsafe { atomic_load(&self.v, order) > 0 }
|
unsafe { atomic_load(&self.v, order) > 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 };
|
let val = if val { 1 } else { 0 };
|
||||||
|
|
||||||
unsafe { atomic_store(&mut self.v, val, order); }
|
unsafe { atomic_store(&mut self.v, val, order); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 };
|
let val = if val { 1 } else { 0 };
|
||||||
|
|
||||||
unsafe { atomic_swap(&mut self.v, val, order) > 0}
|
unsafe { atomic_swap(&mut self.v, val, order) > 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 old = if old { 1 } else { 0 };
|
||||||
let new = if new { 1 } else { 0 };
|
let new = if new { 1 } else { 0 };
|
||||||
|
|
||||||
@ -101,100 +107,153 @@ impl AtomicBool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AtomicInt {
|
impl AtomicInt {
|
||||||
fn new(v:int) -> AtomicInt {
|
fn new(v: int) -> AtomicInt {
|
||||||
AtomicInt { v:v }
|
AtomicInt { v:v }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn load(&self, order:Ordering) -> int {
|
fn load(&self, order: Ordering) -> int {
|
||||||
unsafe { atomic_load(&self.v, order) }
|
unsafe { atomic_load(&self.v, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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); }
|
unsafe { atomic_store(&mut self.v, val, order); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_swap(&mut self.v, val, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_add(&mut self.v, val, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_sub(&mut self.v, val, order) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtomicUint {
|
impl AtomicUint {
|
||||||
fn new(v:uint) -> AtomicUint {
|
fn new(v: uint) -> AtomicUint {
|
||||||
AtomicUint { v:v }
|
AtomicUint { v:v }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn load(&self, order:Ordering) -> uint {
|
fn load(&self, order: Ordering) -> uint {
|
||||||
unsafe { atomic_load(&self.v, order) }
|
unsafe { atomic_load(&self.v, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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); }
|
unsafe { atomic_store(&mut self.v, val, order); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_swap(&mut self.v, val, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_add(&mut self.v, val, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_sub(&mut self.v, val, order) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> AtomicPtr<T> {
|
impl<T> AtomicPtr<T> {
|
||||||
fn new(p:*mut T) -> AtomicPtr<T> {
|
fn new(p: *mut T) -> AtomicPtr<T> {
|
||||||
AtomicPtr { p:p }
|
AtomicPtr { p:p }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn load(&self, order:Ordering) -> *mut T {
|
fn load(&self, order: Ordering) -> *mut T {
|
||||||
unsafe { atomic_load(&self.p, order) }
|
unsafe { atomic_load(&self.p, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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); }
|
unsafe { atomic_store(&mut self.p, ptr, order); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) }
|
unsafe { atomic_swap(&mut self.p, ptr, order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order:Ordering) -> *mut T {
|
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) }
|
unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> AtomicOption<T> {
|
||||||
|
fn new(p: ~T) -> AtomicOption<T> {
|
||||||
|
unsafe {
|
||||||
|
AtomicOption {
|
||||||
|
p: cast::transmute(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty() -> AtomicOption<T> {
|
||||||
|
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<T> Drop for AtomicOption<T> {
|
||||||
|
fn finalize(&self) {
|
||||||
|
// This will ensure that the contained data is
|
||||||
|
// destroyed, unless it's null.
|
||||||
|
unsafe {
|
||||||
|
let this : &mut AtomicOption<T> = cast::transmute(self);
|
||||||
|
let _ = this.take(SeqCst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,8 +343,8 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pointer_swap() {
|
fn option_swap() {
|
||||||
let mut p = AtomicPtr::new(~1);
|
let mut p = AtomicOption::new(~1);
|
||||||
let a = ~2;
|
let a = ~2;
|
||||||
|
|
||||||
let b = p.swap(a, SeqCst);
|
let b = p.swap(a, SeqCst);
|
||||||
@ -295,15 +354,14 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pointer_take() {
|
fn option_take() {
|
||||||
let mut p = AtomicPtr::new(~1);
|
let mut p = AtomicOption::new(~1);
|
||||||
|
|
||||||
assert_eq!(p.take(SeqCst), Some(~1));
|
assert_eq!(p.take(SeqCst), Some(~1));
|
||||||
assert_eq!(p.take(SeqCst), None);
|
assert_eq!(p.take(SeqCst), None);
|
||||||
assert!(p.taken(SeqCst));
|
|
||||||
|
|
||||||
let p2 = ~2;
|
let p2 = ~2;
|
||||||
p.give(p2, SeqCst);
|
p.swap(p2, SeqCst);
|
||||||
|
|
||||||
assert_eq!(p.take(SeqCst), Some(~2));
|
assert_eq!(p.take(SeqCst), Some(~2));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user