|
#![feature(core)] |
|
#![feature(test)] |
|
|
|
extern crate test; |
|
|
|
use std::intrinsics::abort; |
|
use std::thread; |
|
use std::sync::Arc; |
|
use std::sync::atomic::{AtomicIsize, Ordering}; |
|
|
|
const N: isize = 1000; |
|
const M: isize = 5; |
|
|
|
fn cas_inc(slot: &AtomicIsize) { |
|
loop { |
|
let val = slot.load(Ordering::SeqCst); |
|
if slot.compare_and_swap(val, val + 1, Ordering::SeqCst) == val { |
|
break |
|
} |
|
} |
|
} |
|
|
|
fn atomic_inc(slot: &AtomicIsize) { |
|
slot.fetch_add(1, Ordering::SeqCst); |
|
} |
|
|
|
fn atomic_inc_check(slot: &AtomicIsize) { |
|
let x = slot.fetch_add(1, Ordering::SeqCst); |
|
if x < 0 { |
|
unsafe { abort(); } |
|
} |
|
} |
|
|
|
fn doit(inc: fn(&AtomicIsize)) { |
|
let n = Arc::new(AtomicIsize::new(0)); |
|
let children = (0..M).map(|_| { |
|
let n = n.clone(); |
|
thread::spawn(move || { |
|
for _ in 0..N { |
|
inc(&n); |
|
} |
|
}) |
|
}).collect::<Vec<_>>(); |
|
for child in children { |
|
let _ = child.join(); |
|
} |
|
assert_eq!(n.load(Ordering::SeqCst), N * M); |
|
} |
|
|
|
#[bench] |
|
fn cas(b: &mut test::Bencher) { |
|
b.iter(|| doit(cas_inc)); |
|
} |
|
|
|
#[bench] |
|
fn inc(b: &mut test::Bencher) { |
|
b.iter(|| doit(atomic_inc)); |
|
} |
|
|
|
#[bench] |
|
fn check(b: &mut test::Bencher) { |
|
b.iter(|| doit(atomic_inc_check)); |
|
} |