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