]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | extern crate crossbeam_queue; |
2 | extern crate crossbeam_utils; | |
3 | extern crate rand; | |
4 | ||
5 | use std::sync::atomic::{AtomicUsize, Ordering}; | |
6 | ||
7 | use crossbeam_queue::SegQueue; | |
8 | use crossbeam_utils::thread::scope; | |
9 | use rand::{thread_rng, Rng}; | |
10 | ||
11 | #[test] | |
12 | fn smoke() { | |
13 | let q = SegQueue::new(); | |
14 | q.push(7); | |
15 | assert_eq!(q.pop(), Ok(7)); | |
16 | ||
17 | q.push(8); | |
18 | assert_eq!(q.pop(), Ok(8)); | |
19 | assert!(q.pop().is_err()); | |
20 | } | |
21 | ||
22 | #[test] | |
23 | fn len_empty_full() { | |
24 | let q = SegQueue::new(); | |
25 | ||
26 | assert_eq!(q.len(), 0); | |
27 | assert_eq!(q.is_empty(), true); | |
28 | ||
29 | q.push(()); | |
30 | ||
31 | assert_eq!(q.len(), 1); | |
32 | assert_eq!(q.is_empty(), false); | |
33 | ||
34 | q.pop().unwrap(); | |
35 | ||
36 | assert_eq!(q.len(), 0); | |
37 | assert_eq!(q.is_empty(), true); | |
38 | } | |
39 | ||
40 | #[test] | |
41 | fn len() { | |
42 | let q = SegQueue::new(); | |
43 | ||
44 | assert_eq!(q.len(), 0); | |
45 | ||
46 | for i in 0..50 { | |
47 | q.push(i); | |
48 | assert_eq!(q.len(), i + 1); | |
49 | } | |
50 | ||
51 | for i in 0..50 { | |
52 | q.pop().unwrap(); | |
53 | assert_eq!(q.len(), 50 - i - 1); | |
54 | } | |
55 | ||
56 | assert_eq!(q.len(), 0); | |
57 | } | |
58 | ||
59 | #[test] | |
60 | fn spsc() { | |
61 | const COUNT: usize = 100_000; | |
62 | ||
63 | let q = SegQueue::new(); | |
64 | ||
65 | scope(|scope| { | |
66 | scope.spawn(|_| { | |
67 | for i in 0..COUNT { | |
68 | loop { | |
69 | if let Ok(x) = q.pop() { | |
70 | assert_eq!(x, i); | |
71 | break; | |
72 | } | |
73 | } | |
74 | } | |
75 | assert!(q.pop().is_err()); | |
76 | }); | |
77 | scope.spawn(|_| { | |
78 | for i in 0..COUNT { | |
79 | q.push(i); | |
80 | } | |
81 | }); | |
f035d41b XL |
82 | }) |
83 | .unwrap(); | |
416331ca XL |
84 | } |
85 | ||
86 | #[test] | |
87 | fn mpmc() { | |
88 | const COUNT: usize = 25_000; | |
89 | const THREADS: usize = 4; | |
90 | ||
91 | let q = SegQueue::<usize>::new(); | |
92 | let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>(); | |
93 | ||
94 | scope(|scope| { | |
95 | for _ in 0..THREADS { | |
96 | scope.spawn(|_| { | |
97 | for _ in 0..COUNT { | |
98 | let n = loop { | |
99 | if let Ok(x) = q.pop() { | |
100 | break x; | |
101 | } | |
102 | }; | |
103 | v[n].fetch_add(1, Ordering::SeqCst); | |
104 | } | |
105 | }); | |
106 | } | |
107 | for _ in 0..THREADS { | |
108 | scope.spawn(|_| { | |
109 | for i in 0..COUNT { | |
110 | q.push(i); | |
111 | } | |
112 | }); | |
113 | } | |
f035d41b XL |
114 | }) |
115 | .unwrap(); | |
416331ca XL |
116 | |
117 | for c in v { | |
118 | assert_eq!(c.load(Ordering::SeqCst), THREADS); | |
119 | } | |
120 | } | |
121 | ||
122 | #[test] | |
123 | fn drops() { | |
124 | static DROPS: AtomicUsize = AtomicUsize::new(0); | |
125 | ||
126 | #[derive(Debug, PartialEq)] | |
127 | struct DropCounter; | |
128 | ||
129 | impl Drop for DropCounter { | |
130 | fn drop(&mut self) { | |
131 | DROPS.fetch_add(1, Ordering::SeqCst); | |
132 | } | |
133 | } | |
134 | ||
135 | let mut rng = thread_rng(); | |
136 | ||
137 | for _ in 0..100 { | |
138 | let steps = rng.gen_range(0, 10_000); | |
139 | let additional = rng.gen_range(0, 1000); | |
140 | ||
141 | DROPS.store(0, Ordering::SeqCst); | |
142 | let q = SegQueue::new(); | |
143 | ||
144 | scope(|scope| { | |
145 | scope.spawn(|_| { | |
146 | for _ in 0..steps { | |
147 | while q.pop().is_err() {} | |
148 | } | |
149 | }); | |
150 | ||
151 | scope.spawn(|_| { | |
152 | for _ in 0..steps { | |
153 | q.push(DropCounter); | |
154 | } | |
155 | }); | |
f035d41b XL |
156 | }) |
157 | .unwrap(); | |
416331ca XL |
158 | |
159 | for _ in 0..additional { | |
160 | q.push(DropCounter); | |
161 | } | |
162 | ||
163 | assert_eq!(DROPS.load(Ordering::SeqCst), steps); | |
164 | drop(q); | |
165 | assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional); | |
166 | } | |
167 | } |