]>
Commit | Line | Data |
---|---|---|
5869c6ff XL |
1 | extern crate crossbeam_epoch as epoch; |
2 | extern crate rand; | |
3 | ||
4 | use std::sync::atomic::AtomicUsize; | |
5 | use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed}; | |
6 | use std::sync::Arc; | |
7 | use std::thread; | |
8 | use std::time::{Duration, Instant}; | |
9 | ||
10 | use epoch::{Atomic, Collector, LocalHandle, Owned, Shared}; | |
11 | use rand::Rng; | |
12 | ||
13 | fn worker(a: Arc<Atomic<AtomicUsize>>, handle: LocalHandle) -> usize { | |
14 | let mut rng = rand::thread_rng(); | |
15 | let mut sum = 0; | |
16 | ||
17 | if rng.gen() { | |
18 | thread::sleep(Duration::from_millis(1)); | |
19 | } | |
20 | let timeout = Duration::from_millis(rng.gen_range(0, 10)); | |
21 | let now = Instant::now(); | |
22 | ||
23 | while now.elapsed() < timeout { | |
24 | for _ in 0..100 { | |
25 | let guard = &handle.pin(); | |
26 | guard.flush(); | |
27 | ||
28 | let val = if rng.gen() { | |
29 | let p = a.swap(Owned::new(AtomicUsize::new(sum)), AcqRel, guard); | |
30 | unsafe { | |
31 | guard.defer_destroy(p); | |
32 | guard.flush(); | |
33 | p.deref().load(Relaxed) | |
34 | } | |
35 | } else { | |
36 | let p = a.load(Acquire, guard); | |
37 | unsafe { p.deref().fetch_add(sum, Relaxed) } | |
38 | }; | |
39 | ||
40 | sum = sum.wrapping_add(val); | |
41 | } | |
42 | } | |
43 | ||
44 | sum | |
45 | } | |
46 | ||
47 | fn main() { | |
48 | for _ in 0..100 { | |
49 | let collector = Collector::new(); | |
50 | let a = Arc::new(Atomic::new(AtomicUsize::new(777))); | |
51 | ||
52 | let threads = (0..16) | |
53 | .map(|_| { | |
54 | let a = a.clone(); | |
55 | let c = collector.clone(); | |
56 | thread::spawn(move || worker(a, c.register())) | |
57 | }) | |
58 | .collect::<Vec<_>>(); | |
59 | ||
60 | for t in threads { | |
61 | t.join().unwrap(); | |
62 | } | |
63 | ||
64 | unsafe { | |
65 | a.swap(Shared::null(), AcqRel, epoch::unprotected()) | |
66 | .into_owned(); | |
67 | } | |
68 | } | |
69 | } |