crossbeam_channel/flavors/
list.rs1use std::alloc::{alloc_zeroed, handle_alloc_error, Layout};
4use std::boxed::Box;
5use std::cell::UnsafeCell;
6use std::marker::PhantomData;
7use std::mem::MaybeUninit;
8use std::ptr;
9use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
10use std::time::Instant;
11
12use crossbeam_utils::{Backoff, CachePadded};
13
14use crate::context::Context;
15use crate::err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
16use crate::select::{Operation, SelectHandle, Selected, Token};
17use crate::waker::SyncWaker;
18
19#[cfg(target_has_atomic = "64")]
24type AtomicIndex = core::sync::atomic::AtomicU64;
25#[cfg(target_has_atomic = "64")]
26type Index = u64;
27#[cfg(not(target_has_atomic = "64"))]
28type AtomicIndex = core::sync::atomic::AtomicUsize;
29#[cfg(not(target_has_atomic = "64"))]
30type Index = usize;
31
32const WRITE: usize = 1;
43const READ: usize = 2;
44const DESTROY: usize = 4;
45
46const LAP: Index = 32;
48const BLOCK_CAP: usize = LAP as usize - 1;
50const SHIFT: usize = 1;
52const MARK_BIT: Index = 1;
56
57struct Slot<T> {
59 msg: UnsafeCell<MaybeUninit<T>>,
61
62 state: AtomicUsize,
64}
65
66impl<T> Slot<T> {
67 fn wait_write(&self) {
69 let backoff = Backoff::new();
70 while self.state.load(Ordering::Acquire) & WRITE == 0 {
71 backoff.snooze();
72 }
73 }
74}
75
76struct Block<T> {
80 next: AtomicPtr<Block<T>>,
82
83 slots: [Slot<T>; BLOCK_CAP],
85}
86
87impl<T> Block<T> {
88 const LAYOUT: Layout = {
89 let layout = Layout::new::<Self>();
90 assert!(
91 layout.size() != 0,
92 "Block should never be zero-sized, as it has an AtomicPtr field"
93 );
94 layout
95 };
96
97 fn new() -> Box<Self> {
99 let ptr = unsafe { alloc_zeroed(Self::LAYOUT) };
101 if ptr.is_null() {
103 handle_alloc_error(Self::LAYOUT)
104 }
105 unsafe { Box::from_raw(ptr.cast()) }
113 }
114
115 fn wait_next(&self) -> *mut Block<T> {
117 let backoff = Backoff::new();
118 loop {
119 let next = self.next.load(Ordering::Acquire);
120 if !next.is_null() {
121 return next;
122 }
123 backoff.snooze();
124 }
125 }
126
127 unsafe fn destroy(this: *mut Block<T>, start: usize) {
129 for i in start..BLOCK_CAP - 1 {
132 let slot = (*this).slots.get_unchecked(i);
133
134 if slot.state.load(Ordering::Acquire) & READ == 0
136 && slot.state.fetch_or(DESTROY, Ordering::AcqRel) & READ == 0
137 {
138 return;
140 }
141 }
142
143 drop(Box::from_raw(this));
145 }
146}
147
148#[derive(Debug)]
150struct Position<T> {
151 index: AtomicIndex,
153
154 block: AtomicPtr<Block<T>>,
156}
157
158#[derive(Debug)]
160pub(crate) struct ListToken {
161 block: *const u8,
163
164 offset: usize,
166}
167
168impl Default for ListToken {
169 #[inline]
170 fn default() -> Self {
171 ListToken {
172 block: ptr::null(),
173 offset: 0,
174 }
175 }
176}
177
178pub(crate) struct Channel<T> {
186 head: CachePadded<Position<T>>,
188
189 tail: CachePadded<Position<T>>,
191
192 receivers: SyncWaker,
194
195 _marker: PhantomData<T>,
197}
198
199impl<T> Channel<T> {
200 pub(crate) fn new() -> Self {
202 Channel {
203 head: CachePadded::new(Position {
204 block: AtomicPtr::new(ptr::null_mut()),
205 index: AtomicIndex::new(0),
206 }),
207 tail: CachePadded::new(Position {
208 block: AtomicPtr::new(ptr::null_mut()),
209 index: AtomicIndex::new(0),
210 }),
211 receivers: SyncWaker::new(),
212 _marker: PhantomData,
213 }
214 }
215
216 pub(crate) fn receiver(&self) -> Receiver<'_, T> {
218 Receiver(self)
219 }
220
221 pub(crate) fn sender(&self) -> Sender<'_, T> {
223 Sender(self)
224 }
225
226 fn start_send(&self, token: &mut Token) -> bool {
228 let backoff = Backoff::new();
229 let mut tail = self.tail.index.load(Ordering::Acquire);
230 let mut block = self.tail.block.load(Ordering::Acquire);
231 let mut next_block = None;
232
233 loop {
234 if tail & MARK_BIT != 0 {
236 token.list.block = ptr::null();
237 return true;
238 }
239
240 let offset = ((tail >> SHIFT) % LAP) as usize;
242
243 if offset == BLOCK_CAP {
245 backoff.snooze();
246 tail = self.tail.index.load(Ordering::Acquire);
247 block = self.tail.block.load(Ordering::Acquire);
248 continue;
249 }
250
251 if offset + 1 == BLOCK_CAP && next_block.is_none() {
254 next_block = Some(Block::<T>::new());
255 }
256
257 if block.is_null() {
260 let new = Box::into_raw(Block::<T>::new());
261
262 if self
263 .tail
264 .block
265 .compare_exchange(block, new, Ordering::Release, Ordering::Relaxed)
266 .is_ok()
267 {
268 self.head.block.store(new, Ordering::Release);
269 block = new;
270 } else {
271 next_block = unsafe { Some(Box::from_raw(new)) };
272 tail = self.tail.index.load(Ordering::Acquire);
273 block = self.tail.block.load(Ordering::Acquire);
274 continue;
275 }
276 }
277
278 let new_tail = tail + (1 << SHIFT);
279
280 match self.tail.index.compare_exchange_weak(
282 tail,
283 new_tail,
284 Ordering::SeqCst,
285 Ordering::Acquire,
286 ) {
287 Ok(_) => unsafe {
288 if offset + 1 == BLOCK_CAP {
290 let next_block = Box::into_raw(next_block.unwrap());
291 self.tail.block.store(next_block, Ordering::Release);
292 self.tail.index.fetch_add(1 << SHIFT, Ordering::Release);
293 (*block).next.store(next_block, Ordering::Release);
294 }
295
296 token.list.block = block as *const u8;
297 token.list.offset = offset;
298 return true;
299 },
300 Err(t) => {
301 tail = t;
302 block = self.tail.block.load(Ordering::Acquire);
303 backoff.spin();
304 }
305 }
306 }
307 }
308
309 pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
311 if token.list.block.is_null() {
313 return Err(msg);
314 }
315
316 let block = token.list.block.cast::<Block<T>>();
318 let offset = token.list.offset;
319 let slot = (*block).slots.get_unchecked(offset);
320 slot.msg.get().write(MaybeUninit::new(msg));
321 slot.state.fetch_or(WRITE, Ordering::Release);
322
323 self.receivers.notify();
325 Ok(())
326 }
327
328 fn start_recv(&self, token: &mut Token) -> bool {
330 let backoff = Backoff::new();
331 let mut head = self.head.index.load(Ordering::Acquire);
332 let mut block = self.head.block.load(Ordering::Acquire);
333
334 loop {
335 let offset = ((head >> SHIFT) % LAP) as usize;
337
338 if offset == BLOCK_CAP {
340 backoff.snooze();
341 head = self.head.index.load(Ordering::Acquire);
342 block = self.head.block.load(Ordering::Acquire);
343 continue;
344 }
345
346 let mut new_head = head + (1 << SHIFT);
347
348 if new_head & MARK_BIT == 0 {
349 atomic::fence(Ordering::SeqCst);
350 let tail = self.tail.index.load(Ordering::Relaxed);
351
352 if head >> SHIFT == tail >> SHIFT {
354 if tail & MARK_BIT != 0 {
356 token.list.block = ptr::null();
358 return true;
359 } else {
360 return false;
362 }
363 }
364
365 if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP {
367 new_head |= MARK_BIT;
368 }
369 }
370
371 if block.is_null() {
374 backoff.snooze();
375 head = self.head.index.load(Ordering::Acquire);
376 block = self.head.block.load(Ordering::Acquire);
377 continue;
378 }
379
380 match self.head.index.compare_exchange_weak(
382 head,
383 new_head,
384 Ordering::SeqCst,
385 Ordering::Acquire,
386 ) {
387 Ok(_) => unsafe {
388 if offset + 1 == BLOCK_CAP {
390 let next = (*block).wait_next();
391 let mut next_index = (new_head & !MARK_BIT).wrapping_add(1 << SHIFT);
392 if !(*next).next.load(Ordering::Relaxed).is_null() {
393 next_index |= MARK_BIT;
394 }
395
396 self.head.block.store(next, Ordering::Release);
397 self.head.index.store(next_index, Ordering::Release);
398 }
399
400 token.list.block = block as *const u8;
401 token.list.offset = offset;
402 return true;
403 },
404 Err(h) => {
405 head = h;
406 block = self.head.block.load(Ordering::Acquire);
407 backoff.spin();
408 }
409 }
410 }
411 }
412
413 pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
415 if token.list.block.is_null() {
416 return Err(());
418 }
419
420 let block = token.list.block as *mut Block<T>;
422 let offset = token.list.offset;
423 let slot = (*block).slots.get_unchecked(offset);
424 slot.wait_write();
425 let msg = slot.msg.get().read().assume_init();
426
427 if offset + 1 == BLOCK_CAP {
430 Block::destroy(block, 0);
431 } else if slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0 {
432 Block::destroy(block, offset + 1);
433 }
434
435 Ok(msg)
436 }
437
438 pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
440 self.send(msg, None).map_err(|err| match err {
441 SendTimeoutError::Disconnected(msg) => TrySendError::Disconnected(msg),
442 SendTimeoutError::Timeout(_) => unreachable!(),
443 })
444 }
445
446 pub(crate) fn send(
448 &self,
449 msg: T,
450 _deadline: Option<Instant>,
451 ) -> Result<(), SendTimeoutError<T>> {
452 let token = &mut Token::default();
453 assert!(self.start_send(token));
454 unsafe {
455 self.write(token, msg)
456 .map_err(SendTimeoutError::Disconnected)
457 }
458 }
459
460 pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
462 let token = &mut Token::default();
463
464 if self.start_recv(token) {
465 unsafe { self.read(token).map_err(|_| TryRecvError::Disconnected) }
466 } else {
467 Err(TryRecvError::Empty)
468 }
469 }
470
471 pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
473 let token = &mut Token::default();
474 loop {
475 let backoff = Backoff::new();
477 loop {
478 if self.start_recv(token) {
479 unsafe {
480 return self.read(token).map_err(|_| RecvTimeoutError::Disconnected);
481 }
482 }
483
484 if backoff.is_completed() {
485 break;
486 } else {
487 backoff.snooze();
488 }
489 }
490
491 if let Some(d) = deadline {
492 if Instant::now() >= d {
493 return Err(RecvTimeoutError::Timeout);
494 }
495 }
496
497 Context::with(|cx| {
499 let oper = Operation::hook(token);
500 self.receivers.register(oper, cx);
501
502 if !self.is_empty() || self.is_disconnected() {
504 let _ = cx.try_select(Selected::Aborted);
505 }
506
507 let sel = cx.wait_until(deadline);
509
510 match sel {
511 Selected::Waiting => unreachable!(),
512 Selected::Aborted | Selected::Disconnected => {
513 self.receivers.unregister(oper).unwrap();
514 }
517 Selected::Operation(_) => {}
518 }
519 });
520 }
521 }
522
523 pub(crate) fn len(&self) -> usize {
525 loop {
526 let mut tail = self.tail.index.load(Ordering::SeqCst);
528 let mut head = self.head.index.load(Ordering::SeqCst);
529
530 if self.tail.index.load(Ordering::SeqCst) == tail {
532 tail &= !((1 << SHIFT) - 1);
534 head &= !((1 << SHIFT) - 1);
535
536 if (tail >> SHIFT) & (LAP - 1) == LAP - 1 {
538 tail = tail.wrapping_add(1 << SHIFT);
539 }
540 if (head >> SHIFT) & (LAP - 1) == LAP - 1 {
541 head = head.wrapping_add(1 << SHIFT);
542 }
543
544 let lap = (head >> SHIFT) / LAP;
546 tail = tail.wrapping_sub((lap * LAP) << SHIFT);
547 head = head.wrapping_sub((lap * LAP) << SHIFT);
548
549 tail >>= SHIFT;
551 head >>= SHIFT;
552
553 return (tail - head - tail / LAP) as usize;
555 }
556 }
557 }
558
559 pub(crate) fn capacity(&self) -> Option<usize> {
561 None
562 }
563
564 pub(crate) fn disconnect_senders(&self) -> bool {
568 let tail = self.tail.index.fetch_or(MARK_BIT, Ordering::SeqCst);
569
570 if tail & MARK_BIT == 0 {
571 self.receivers.disconnect();
572 true
573 } else {
574 false
575 }
576 }
577
578 pub(crate) fn disconnect_receivers(&self) -> bool {
582 let tail = self.tail.index.fetch_or(MARK_BIT, Ordering::SeqCst);
583
584 if tail & MARK_BIT == 0 {
585 self.discard_all_messages();
588 true
589 } else {
590 false
591 }
592 }
593
594 fn discard_all_messages(&self) {
598 let backoff = Backoff::new();
599 let mut tail = self.tail.index.load(Ordering::Acquire);
600 loop {
601 let offset = ((tail >> SHIFT) % LAP) as usize;
602 if offset != BLOCK_CAP {
603 break;
604 }
605
606 backoff.snooze();
610 tail = self.tail.index.load(Ordering::Acquire);
611 }
612
613 let mut head = self.head.index.load(Ordering::Acquire);
614 let mut block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel);
618
619 if head >> SHIFT != tail >> SHIFT {
621 while block.is_null() {
626 backoff.snooze();
627 block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel);
628 }
629 }
630
631 unsafe {
632 while head >> SHIFT != tail >> SHIFT {
634 let offset = ((head >> SHIFT) % LAP) as usize;
635
636 if offset < BLOCK_CAP {
637 let slot = (*block).slots.get_unchecked(offset);
639 slot.wait_write();
640 (*slot.msg.get()).assume_init_drop();
641 } else {
642 (*block).wait_next();
643 let next = (*block).next.load(Ordering::Acquire);
645 drop(Box::from_raw(block));
646 block = next;
647 }
648
649 head = head.wrapping_add(1 << SHIFT);
650 }
651
652 if !block.is_null() {
654 drop(Box::from_raw(block));
655 }
656 }
657 head &= !MARK_BIT;
658 self.head.index.store(head, Ordering::Release);
659 }
660
661 pub(crate) fn is_disconnected(&self) -> bool {
663 self.tail.index.load(Ordering::SeqCst) & MARK_BIT != 0
664 }
665
666 pub(crate) fn is_empty(&self) -> bool {
668 let head = self.head.index.load(Ordering::SeqCst);
669 let tail = self.tail.index.load(Ordering::SeqCst);
670 head >> SHIFT == tail >> SHIFT
671 }
672
673 pub(crate) fn is_full(&self) -> bool {
675 false
676 }
677}
678
679impl<T> Drop for Channel<T> {
680 fn drop(&mut self) {
681 let mut head = *self.head.index.get_mut();
682 let mut tail = *self.tail.index.get_mut();
683 let mut block = *self.head.block.get_mut();
684
685 head &= !((1 << SHIFT) - 1);
687 tail &= !((1 << SHIFT) - 1);
688
689 unsafe {
690 while head != tail {
692 let offset = ((head >> SHIFT) % LAP) as usize;
693
694 if offset < BLOCK_CAP {
695 let slot = (*block).slots.get_unchecked_mut(offset);
697 if *slot.state.get_mut() & WRITE != 0 {
698 (*slot.msg.get()).assume_init_drop();
699 }
700 } else {
701 let next = *(*block).next.get_mut();
703 drop(Box::from_raw(block));
704 block = next;
705 }
706
707 head = head.wrapping_add(1 << SHIFT);
708 }
709
710 if !block.is_null() {
712 drop(Box::from_raw(block));
713 }
714 }
715 }
716}
717
718pub(crate) struct Receiver<'a, T>(&'a Channel<T>);
720
721pub(crate) struct Sender<'a, T>(&'a Channel<T>);
723
724impl<T> SelectHandle for Receiver<'_, T> {
725 fn try_select(&self, token: &mut Token) -> bool {
726 self.0.start_recv(token)
727 }
728
729 fn deadline(&self) -> Option<Instant> {
730 None
731 }
732
733 fn register(&self, oper: Operation, cx: &Context) -> bool {
734 self.0.receivers.register(oper, cx);
735 self.is_ready()
736 }
737
738 fn unregister(&self, oper: Operation) {
739 self.0.receivers.unregister(oper);
740 }
741
742 fn accept(&self, token: &mut Token, _cx: &Context) -> bool {
743 self.try_select(token)
744 }
745
746 fn is_ready(&self) -> bool {
747 !self.0.is_empty() || self.0.is_disconnected()
748 }
749
750 fn watch(&self, oper: Operation, cx: &Context) -> bool {
751 self.0.receivers.watch(oper, cx);
752 self.is_ready()
753 }
754
755 fn unwatch(&self, oper: Operation) {
756 self.0.receivers.unwatch(oper);
757 }
758}
759
760impl<T> SelectHandle for Sender<'_, T> {
761 fn try_select(&self, token: &mut Token) -> bool {
762 self.0.start_send(token)
763 }
764
765 fn deadline(&self) -> Option<Instant> {
766 None
767 }
768
769 fn register(&self, _oper: Operation, _cx: &Context) -> bool {
770 self.is_ready()
771 }
772
773 fn unregister(&self, _oper: Operation) {}
774
775 fn accept(&self, token: &mut Token, _cx: &Context) -> bool {
776 self.try_select(token)
777 }
778
779 fn is_ready(&self) -> bool {
780 true
781 }
782
783 fn watch(&self, _oper: Operation, _cx: &Context) -> bool {
784 self.is_ready()
785 }
786
787 fn unwatch(&self, _oper: Operation) {}
788}