1use alloc::boxed::Box;
2use core::{marker::PhantomData, ptr::null_mut};
3
4use crossbeam_utils::CachePadded;
5
6use crate::{
7 MPMCQueue,
8 Resize,
9 core::{
10 AsPackedValue,
11 queue::QueueCore,
12 slots::{Auto, SlotType},
13 },
14 growable::NewSized,
15 owned::buffer::BoxedBuffer,
16 sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering},
17 utils::Backoff,
18};
19
20pub(crate) struct GrowableQueueCore<T, Q, S = Auto> {
22 cores: [AtomicPtr<Q>; 2],
23 push_epoch: CachePadded<AtomicUsize>,
24 pop_epoch: CachePadded<AtomicUsize>,
25 active_pushes: CachePadded<[AtomicUsize; 2]>,
26 active_reads: CachePadded<[AtomicUsize; 2]>,
27 is_resizing: AtomicBool,
28 _slot: PhantomData<(S, T)>,
29}
30
31impl<T, Q> GrowableQueueCore<T, Q, Auto>
32where
33 Q: NewSized,
34{
35 pub(crate) fn with_slot<S>(size: usize) -> GrowableQueueCore<T, Q, S> {
38 GrowableQueueCore {
39 cores: [
40 AtomicPtr::new(Box::into_raw(Box::new(Q::with_size(size)))),
41 AtomicPtr::new(Box::into_raw(Box::new(Q::with_size(1)))),
42 ],
43 active_pushes: [AtomicUsize::new(0), AtomicUsize::new(0)].into(),
44 active_reads: [AtomicUsize::new(0), AtomicUsize::new(0)].into(),
45 push_epoch: AtomicUsize::new(0).into(),
46 pop_epoch: AtomicUsize::new(0).into(),
47 is_resizing: AtomicBool::new(false),
48 _slot: PhantomData,
49 }
50 }
51}
52
53impl<T, Q, S> Drop for GrowableQueueCore<T, Q, S> {
54 fn drop(&mut self) {
55 let left = self.cores[0].swap(null_mut(), Ordering::Acquire);
56 _ = unsafe { Box::from_raw(left) };
60
61 let right = self.cores[1].swap(null_mut(), Ordering::Acquire);
62 _ = unsafe { Box::from_raw(right) };
66 }
67}
68
69impl<T, Q, S> Resize for GrowableQueueCore<T, Q, S>
70where
71 Q: NewSized + MPMCQueue<Item = T>,
72{
73 fn resize(&self, size: usize) -> bool {
74 if size == 0 {
75 return false;
76 }
77 let pop_epoch = self.pop_epoch.load(Ordering::Acquire);
78 let push_epoch = self.push_epoch.load(Ordering::Acquire);
79
80 if pop_epoch != push_epoch {
81 return false;
82 }
83
84 if self.active_reads[(push_epoch + 1) % 2].load(Ordering::Acquire) != 0 {
85 return false;
87 }
88
89 if self.is_resizing.swap(true, Ordering::AcqRel) {
90 return false;
91 }
92
93 if self.push_epoch.load(Ordering::Acquire) != push_epoch {
94 self.is_resizing.store(false, Ordering::Release);
96 return false;
97 }
98
99 let old_idx = (push_epoch + 1) % 2;
105 let mut backoff = Backoff::new();
106
107 while self.active_reads[old_idx].load(Ordering::Acquire) != 0 {
108 backoff.backoff();
109 }
110
111 debug_assert_eq!(
112 self.active_pushes[(push_epoch + 1) % 2].load(Ordering::SeqCst),
113 0
114 );
115
116 let new_queue = Box::into_raw(Box::new(Q::with_size(size)));
117
118 let old_queue = self.cores[(push_epoch + 1) % 2].swap(new_queue, Ordering::AcqRel);
122 self.push_epoch.fetch_add(1, Ordering::Release);
123
124 let q = unsafe { Box::from_raw(old_queue) };
127
128 debug_assert!(q.pop().is_none());
129
130 self.is_resizing.store(false, Ordering::Release);
131 true
132 }
133}
134
135impl<T, Q, S> GrowableQueueCore<T, Q, S> {
136 fn get_queue(&self, epoch: usize) -> &Q {
137 let queue = self.cores[epoch % 2].load(Ordering::Acquire);
138 unsafe { &*queue }
142 }
143
144 fn register_reader(&self, target_epoch: usize) -> bool {
145 self.active_reads[target_epoch % 2].fetch_add(1, Ordering::Release);
146
147 let current_push = self.push_epoch.load(Ordering::SeqCst);
148 let current_pop = self.pop_epoch.load(Ordering::SeqCst);
149
150 if target_epoch != current_push && target_epoch != current_pop {
152 self.deregister_reader(target_epoch);
153 return false;
154 }
155 true
156 }
157
158 fn deregister_reader(&self, epoch: usize) {
159 self.active_reads[epoch % 2].fetch_sub(1, Ordering::Release);
160 }
161}
162
163impl<T, Q, S> MPMCQueue for GrowableQueueCore<T, Q, S>
164where
165 Q: MPMCQueue<Item = T>,
166{
167 type Item = T;
168
169 fn push(&self, item: Self::Item) -> Result<(), Self::Item> {
170 loop {
171 let push_epoch = self.push_epoch.load(Ordering::Acquire);
172 self.active_pushes[push_epoch % 2].fetch_add(1, Ordering::Release);
173
174 if self.push_epoch.load(Ordering::SeqCst) == push_epoch {
175 let r = self.get_queue(push_epoch).push(item);
176
177 self.active_pushes[push_epoch % 2].fetch_sub(1, Ordering::Release);
178 return r;
179 }
180 self.active_pushes[push_epoch % 2].fetch_sub(1, Ordering::Release);
181 }
182 }
183
184 fn pop(&self) -> Option<Self::Item> {
185 loop {
186 let pop_epoch = self.pop_epoch.load(Ordering::Acquire);
187 let push_epoch = self.push_epoch.load(Ordering::Acquire);
188
189 if pop_epoch != push_epoch {
190 if !self.register_reader(pop_epoch) {
193 continue;
194 }
195
196 let item = self.get_queue(pop_epoch).pop();
198
199 self.deregister_reader(pop_epoch);
200
201 if item.is_some() {
202 return item;
203 }
204
205 if self.active_pushes[pop_epoch % 2].load(Ordering::Acquire) == 0 {
206 if !self.register_reader(pop_epoch) {
207 continue;
208 }
209
210 let final_item = self.get_queue(pop_epoch).pop();
211
212 self.deregister_reader(pop_epoch);
213
214 if final_item.is_some() {
215 return final_item;
216 }
217
218 _ = self.pop_epoch.compare_exchange_weak(
219 pop_epoch,
220 pop_epoch + 1,
221 Ordering::AcqRel,
222 Ordering::Relaxed,
223 );
224
225 continue;
226 }
227
228 }
231
232 if !self.register_reader(push_epoch) {
233 continue;
234 }
235
236 let item = self.get_queue(push_epoch).pop();
237
238 self.deregister_reader(push_epoch);
239
240 return item;
241 }
242 }
243
244 fn capacity(&self) -> usize {
245 loop {
247 let push_epoch = self.push_epoch.load(Ordering::Acquire);
248 if !self.register_reader(push_epoch) {
249 continue;
250 }
251 let cap = self.get_queue(push_epoch).capacity();
252 self.deregister_reader(push_epoch);
253 return cap;
254 }
255 }
256
257 fn len(&self) -> usize {
258 loop {
260 let push_epoch = self.push_epoch.load(Ordering::Acquire);
261 if !self.register_reader(push_epoch) {
262 continue;
263 }
264
265 let pop_epoch = self.pop_epoch.load(Ordering::Acquire);
266 let pop_len = if pop_epoch != push_epoch {
267 if !self.register_reader(pop_epoch) {
268 self.deregister_reader(push_epoch);
269 continue;
270 }
271
272 let pop_len = self.get_queue(pop_epoch).len();
273 self.deregister_reader(pop_epoch);
274 pop_len
275 } else {
276 0
277 };
278
279 let len = self.get_queue(push_epoch).len() + pop_len;
280 self.deregister_reader(push_epoch);
281 return len;
282 }
283 }
284
285 fn is_empty(&self) -> bool {
286 loop {
288 let push_epoch = self.push_epoch.load(Ordering::Acquire);
289 if !self.register_reader(push_epoch) {
290 continue;
291 }
292
293 let pop_epoch = self.pop_epoch.load(Ordering::Acquire);
294 let pop_is_empty = if pop_epoch != push_epoch {
295 if !self.register_reader(pop_epoch) {
296 self.deregister_reader(push_epoch);
297 continue;
298 }
299
300 let pop_is_empty = self.get_queue(pop_epoch).is_empty();
301 self.deregister_reader(pop_epoch);
302 pop_is_empty
303 } else {
304 true
305 };
306
307 let is_empty = self.get_queue(push_epoch).is_empty() && pop_is_empty;
308 self.deregister_reader(push_epoch);
309 return is_empty;
310 }
311 }
312
313 fn is_full(&self) -> bool {
314 loop {
316 let push_epoch = self.push_epoch.load(Ordering::Acquire);
317 if !self.register_reader(push_epoch) {
318 continue;
319 }
320 let is_full = self.get_queue(push_epoch).is_full();
321 self.deregister_reader(push_epoch);
322
323 return is_full;
324 }
325 }
326}
327
328impl<T, Q, S> NewSized for GrowableQueueCore<T, Q, S>
329where
330 Q: NewSized,
331{
332 fn with_size(size: usize) -> GrowableQueueCore<T, Q, S> {
333 GrowableQueueCore::with_slot(size)
334 }
335}
336
337impl<S> NewSized for QueueCore<BoxedBuffer<S>>
338where
339 S: Default,
340{
341 fn with_size(size: usize) -> Self {
342 Self::new_in(BoxedBuffer::new(size))
343 }
344}
345
346pub struct DynamicQueue<T, S = Auto>
348where
349 S: SlotType<T>,
350 T: AsPackedValue,
351{
352 inner: GrowableQueueCore<T, QueueCore<BoxedBuffer<S::Slot>>, S>,
353}
354
355impl<T> DynamicQueue<T, Auto>
356where
357 T: AsPackedValue,
358{
359 pub fn new(size: usize) -> Self {
362 Self::with_slot::<Auto>(size)
363 }
364
365 pub fn with_slot<S>(size: usize) -> DynamicQueue<T, S>
368 where
369 S: SlotType<T>,
370 {
371 DynamicQueue {
372 inner: GrowableQueueCore::with_slot::<S>(size),
373 }
374 }
375}
376
377impl<T, S> MPMCQueue for DynamicQueue<T, S>
378where
379 T: AsPackedValue,
380 S: SlotType<T>,
381{
382 type Item = T;
383
384 fn push(&self, item: Self::Item) -> Result<(), Self::Item> {
385 self.inner.push(item)
386 }
387
388 fn pop(&self) -> Option<Self::Item> {
389 self.inner.pop()
390 }
391
392 fn len(&self) -> usize {
393 self.inner.len()
394 }
395
396 fn capacity(&self) -> usize {
397 self.inner.capacity()
398 }
399
400 fn is_empty(&self) -> bool {
401 self.inner.is_empty()
402 }
403
404 fn is_full(&self) -> bool {
405 self.inner.is_full()
406 }
407}
408
409impl<T, S> Resize for DynamicQueue<T, S>
410where
411 T: AsPackedValue,
412 S: SlotType<T>,
413{
414 fn resize(&self, size: usize) -> bool {
415 self.inner.resize(size)
416 }
417}