crossbeam_channel/flavors/
array.rs1use std::boxed::Box;
12use std::cell::UnsafeCell;
13use std::mem::{self, MaybeUninit};
14use std::ptr;
15use std::sync::atomic::{self, Ordering};
16use std::time::Instant;
17
18use crossbeam_utils::{Backoff, CachePadded};
19
20use crate::context::Context;
21use crate::err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
22use crate::select::{Operation, SelectHandle, Selected, Token};
23use crate::waker::SyncWaker;
24
25#[cfg(target_has_atomic = "64")]
30type AtomicIndex = core::sync::atomic::AtomicU64;
31#[cfg(target_has_atomic = "64")]
32type Index = u64;
33#[cfg(not(target_has_atomic = "64"))]
34type AtomicIndex = core::sync::atomic::AtomicUsize;
35#[cfg(not(target_has_atomic = "64"))]
36type Index = usize;
37
38struct Slot<T> {
40 stamp: AtomicIndex,
42
43 msg: UnsafeCell<MaybeUninit<T>>,
45}
46
47#[derive(Debug)]
49pub(crate) struct ArrayToken {
50 slot: *const u8,
52
53 stamp: Index,
55}
56
57impl Default for ArrayToken {
58 #[inline]
59 fn default() -> Self {
60 ArrayToken {
61 slot: ptr::null(),
62 stamp: 0,
63 }
64 }
65}
66
67pub(crate) struct Channel<T> {
69 head: CachePadded<AtomicIndex>,
77
78 tail: CachePadded<AtomicIndex>,
86
87 buffer: Box<[Slot<T>]>,
89
90 cap: usize,
92
93 one_lap: Index,
95
96 mark_bit: Index,
98
99 senders: SyncWaker,
101
102 receivers: SyncWaker,
104}
105
106impl<T> Channel<T> {
107 pub(crate) fn with_capacity(cap: usize) -> Self {
109 assert!(cap > 0, "capacity must be positive");
110
111 let mark_bit = (cap as Index)
113 .checked_add(1)
114 .and_then(Index::checked_next_power_of_two)
115 .expect("bounded channel capacity is too large");
116 let one_lap = mark_bit
117 .checked_mul(2)
118 .expect("bounded channel capacity is too large");
119
120 let head = 0;
122 let tail = 0;
124
125 let buffer: Box<[Slot<T>]> = (0..cap)
128 .map(|i| {
129 Slot {
131 stamp: AtomicIndex::new(i as Index),
132 msg: UnsafeCell::new(MaybeUninit::uninit()),
133 }
134 })
135 .collect();
136
137 Channel {
138 buffer,
139 cap,
140 one_lap,
141 mark_bit,
142 head: CachePadded::new(AtomicIndex::new(head)),
143 tail: CachePadded::new(AtomicIndex::new(tail)),
144 senders: SyncWaker::new(),
145 receivers: SyncWaker::new(),
146 }
147 }
148
149 pub(crate) fn receiver(&self) -> Receiver<'_, T> {
151 Receiver(self)
152 }
153
154 pub(crate) fn sender(&self) -> Sender<'_, T> {
156 Sender(self)
157 }
158
159 fn start_send(&self, token: &mut Token) -> bool {
161 let backoff = Backoff::new();
162 let mut tail = self.tail.load(Ordering::Relaxed);
163
164 loop {
165 if tail & self.mark_bit != 0 {
167 token.array.slot = ptr::null();
168 token.array.stamp = 0;
169 return true;
170 }
171
172 let index = (tail & (self.mark_bit - 1)) as usize;
174 let lap = tail & !(self.one_lap - 1);
175
176 debug_assert!(index < self.buffer.len());
178 let slot = unsafe { self.buffer.get_unchecked(index) };
179 let stamp = slot.stamp.load(Ordering::Acquire);
180
181 if tail == stamp {
183 let new_tail = if index + 1 < self.cap {
184 tail + 1
187 } else {
188 lap.wrapping_add(self.one_lap)
191 };
192
193 match self.tail.compare_exchange_weak(
195 tail,
196 new_tail,
197 Ordering::SeqCst,
198 Ordering::Relaxed,
199 ) {
200 Ok(_) => {
201 token.array.slot = slot as *const Slot<T> as *const u8;
203 token.array.stamp = tail + 1;
204 return true;
205 }
206 Err(t) => {
207 tail = t;
208 backoff.spin();
209 }
210 }
211 } else if stamp.wrapping_add(self.one_lap) == tail + 1 {
212 atomic::fence(Ordering::SeqCst);
213 let head = self.head.load(Ordering::Relaxed);
214
215 if head.wrapping_add(self.one_lap) == tail {
217 return false;
219 }
220
221 backoff.spin();
222 tail = self.tail.load(Ordering::Relaxed);
223 } else {
224 backoff.snooze();
226 tail = self.tail.load(Ordering::Relaxed);
227 }
228 }
229 }
230
231 pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
233 if token.array.slot.is_null() {
235 return Err(msg);
236 }
237
238 let slot: &Slot<T> = &*token.array.slot.cast::<Slot<T>>();
239
240 slot.msg.get().write(MaybeUninit::new(msg));
242 slot.stamp.store(token.array.stamp, Ordering::Release);
243
244 self.receivers.notify();
246 Ok(())
247 }
248
249 fn start_recv(&self, token: &mut Token) -> bool {
251 let backoff = Backoff::new();
252 let mut head = self.head.load(Ordering::Relaxed);
253
254 loop {
255 let index = (head & (self.mark_bit - 1)) as usize;
257 let lap = head & !(self.one_lap - 1);
258
259 debug_assert!(index < self.buffer.len());
261 let slot = unsafe { self.buffer.get_unchecked(index) };
262 let stamp = slot.stamp.load(Ordering::Acquire);
263
264 if head + 1 == stamp {
266 let new = if index + 1 < self.cap {
267 head + 1
270 } else {
271 lap.wrapping_add(self.one_lap)
274 };
275
276 match self.head.compare_exchange_weak(
278 head,
279 new,
280 Ordering::SeqCst,
281 Ordering::Relaxed,
282 ) {
283 Ok(_) => {
284 token.array.slot = slot as *const Slot<T> as *const u8;
286 token.array.stamp = head.wrapping_add(self.one_lap);
287 return true;
288 }
289 Err(h) => {
290 head = h;
291 backoff.spin();
292 }
293 }
294 } else if stamp == head {
295 atomic::fence(Ordering::SeqCst);
296 let tail = self.tail.load(Ordering::Relaxed);
297
298 if (tail & !self.mark_bit) == head {
300 if tail & self.mark_bit != 0 {
302 token.array.slot = ptr::null();
304 token.array.stamp = 0;
305 return true;
306 } else {
307 return false;
309 }
310 }
311
312 backoff.spin();
313 head = self.head.load(Ordering::Relaxed);
314 } else {
315 backoff.snooze();
317 head = self.head.load(Ordering::Relaxed);
318 }
319 }
320 }
321
322 pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
324 if token.array.slot.is_null() {
325 return Err(());
327 }
328
329 let slot: &Slot<T> = &*token.array.slot.cast::<Slot<T>>();
330
331 let msg = slot.msg.get().read().assume_init();
333 slot.stamp.store(token.array.stamp, Ordering::Release);
334
335 self.senders.notify();
337 Ok(msg)
338 }
339
340 pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
342 let token = &mut Token::default();
343 if self.start_send(token) {
344 unsafe { self.write(token, msg).map_err(TrySendError::Disconnected) }
345 } else {
346 Err(TrySendError::Full(msg))
347 }
348 }
349
350 pub(crate) fn send(
352 &self,
353 msg: T,
354 deadline: Option<Instant>,
355 ) -> Result<(), SendTimeoutError<T>> {
356 let token = &mut Token::default();
357 loop {
358 let backoff = Backoff::new();
360 loop {
361 if self.start_send(token) {
362 let res = unsafe { self.write(token, msg) };
363 return res.map_err(SendTimeoutError::Disconnected);
364 }
365
366 if backoff.is_completed() {
367 break;
368 } else {
369 backoff.snooze();
370 }
371 }
372
373 if let Some(d) = deadline {
374 if Instant::now() >= d {
375 return Err(SendTimeoutError::Timeout(msg));
376 }
377 }
378
379 Context::with(|cx| {
380 let oper = Operation::hook(token);
382 self.senders.register(oper, cx);
383
384 if !self.is_full() || self.is_disconnected() {
386 let _ = cx.try_select(Selected::Aborted);
387 }
388
389 let sel = cx.wait_until(deadline);
391
392 match sel {
393 Selected::Waiting => unreachable!(),
394 Selected::Aborted | Selected::Disconnected => {
395 self.senders.unregister(oper).unwrap();
396 }
397 Selected::Operation(_) => {}
398 }
399 });
400 }
401 }
402
403 pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
405 let token = &mut Token::default();
406
407 if self.start_recv(token) {
408 unsafe { self.read(token).map_err(|_| TryRecvError::Disconnected) }
409 } else {
410 Err(TryRecvError::Empty)
411 }
412 }
413
414 pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
416 let token = &mut Token::default();
417 loop {
418 let backoff = Backoff::new();
420 loop {
421 if self.start_recv(token) {
422 let res = unsafe { self.read(token) };
423 return res.map_err(|_| RecvTimeoutError::Disconnected);
424 }
425
426 if backoff.is_completed() {
427 break;
428 } else {
429 backoff.snooze();
430 }
431 }
432
433 if let Some(d) = deadline {
434 if Instant::now() >= d {
435 return Err(RecvTimeoutError::Timeout);
436 }
437 }
438
439 Context::with(|cx| {
440 let oper = Operation::hook(token);
442 self.receivers.register(oper, cx);
443
444 if !self.is_empty() || self.is_disconnected() {
446 let _ = cx.try_select(Selected::Aborted);
447 }
448
449 let sel = cx.wait_until(deadline);
451
452 match sel {
453 Selected::Waiting => unreachable!(),
454 Selected::Aborted | Selected::Disconnected => {
455 self.receivers.unregister(oper).unwrap();
456 }
459 Selected::Operation(_) => {}
460 }
461 });
462 }
463 }
464
465 pub(crate) fn len(&self) -> usize {
467 loop {
468 let tail = self.tail.load(Ordering::SeqCst);
470 let head = self.head.load(Ordering::SeqCst);
471
472 if self.tail.load(Ordering::SeqCst) == tail {
474 let hix = (head & (self.mark_bit - 1)) as usize;
475 let tix = (tail & (self.mark_bit - 1)) as usize;
476
477 return if hix < tix {
478 tix - hix
479 } else if hix > tix {
480 self.cap - hix + tix
481 } else if (tail & !self.mark_bit) == head {
482 0
483 } else {
484 self.cap
485 };
486 }
487 }
488 }
489
490 pub(crate) fn capacity(&self) -> Option<usize> {
492 Some(self.cap)
493 }
494
495 pub(crate) fn disconnect(&self) -> bool {
499 let tail = self.tail.fetch_or(self.mark_bit, Ordering::SeqCst);
500
501 if tail & self.mark_bit == 0 {
502 self.senders.disconnect();
503 self.receivers.disconnect();
504 true
505 } else {
506 false
507 }
508 }
509
510 pub(crate) fn is_disconnected(&self) -> bool {
512 self.tail.load(Ordering::SeqCst) & self.mark_bit != 0
513 }
514
515 pub(crate) fn is_empty(&self) -> bool {
517 let head = self.head.load(Ordering::SeqCst);
518 let tail = self.tail.load(Ordering::SeqCst);
519
520 (tail & !self.mark_bit) == head
525 }
526
527 pub(crate) fn is_full(&self) -> bool {
529 let tail = self.tail.load(Ordering::SeqCst);
530 let head = self.head.load(Ordering::SeqCst);
531
532 head.wrapping_add(self.one_lap) == tail & !self.mark_bit
537 }
538}
539
540impl<T> Drop for Channel<T> {
541 fn drop(&mut self) {
542 if mem::needs_drop::<T>() {
543 let head = *self.head.get_mut();
545 let tail = *self.tail.get_mut();
546
547 let hix = (head & (self.mark_bit - 1)) as usize;
548 let tix = (tail & (self.mark_bit - 1)) as usize;
549
550 let len = if hix < tix {
551 tix - hix
552 } else if hix > tix {
553 self.cap - hix + tix
554 } else if (tail & !self.mark_bit) == head {
555 0
556 } else {
557 self.cap
558 };
559
560 for i in 0..len {
562 let index = if hix + i < self.cap {
564 hix + i
565 } else {
566 hix + i - self.cap
567 };
568
569 unsafe {
570 debug_assert!(index < self.buffer.len());
571 let slot = self.buffer.get_unchecked_mut(index);
572 (*slot.msg.get()).assume_init_drop();
573 }
574 }
575 }
576 }
577}
578
579pub(crate) struct Receiver<'a, T>(&'a Channel<T>);
581
582pub(crate) struct Sender<'a, T>(&'a Channel<T>);
584
585impl<T> SelectHandle for Receiver<'_, T> {
586 fn try_select(&self, token: &mut Token) -> bool {
587 self.0.start_recv(token)
588 }
589
590 fn deadline(&self) -> Option<Instant> {
591 None
592 }
593
594 fn register(&self, oper: Operation, cx: &Context) -> bool {
595 self.0.receivers.register(oper, cx);
596 self.is_ready()
597 }
598
599 fn unregister(&self, oper: Operation) {
600 self.0.receivers.unregister(oper);
601 }
602
603 fn accept(&self, token: &mut Token, _cx: &Context) -> bool {
604 self.try_select(token)
605 }
606
607 fn is_ready(&self) -> bool {
608 !self.0.is_empty() || self.0.is_disconnected()
609 }
610
611 fn watch(&self, oper: Operation, cx: &Context) -> bool {
612 self.0.receivers.watch(oper, cx);
613 self.is_ready()
614 }
615
616 fn unwatch(&self, oper: Operation) {
617 self.0.receivers.unwatch(oper);
618 }
619}
620
621impl<T> SelectHandle for Sender<'_, T> {
622 fn try_select(&self, token: &mut Token) -> bool {
623 self.0.start_send(token)
624 }
625
626 fn deadline(&self) -> Option<Instant> {
627 None
628 }
629
630 fn register(&self, oper: Operation, cx: &Context) -> bool {
631 self.0.senders.register(oper, cx);
632 self.is_ready()
633 }
634
635 fn unregister(&self, oper: Operation) {
636 self.0.senders.unregister(oper);
637 }
638
639 fn accept(&self, token: &mut Token, _cx: &Context) -> bool {
640 self.try_select(token)
641 }
642
643 fn is_ready(&self) -> bool {
644 !self.0.is_full() || self.0.is_disconnected()
645 }
646
647 fn watch(&self, oper: Operation, cx: &Context) -> bool {
648 self.0.senders.watch(oper, cx);
649 self.is_ready()
650 }
651
652 fn unwatch(&self, oper: Operation) {
653 self.0.senders.unwatch(oper);
654 }
655}