nuclei/sync/oneshot.rs
1//! A channel that carries one value from one sender to one receiver.
2//!
3//! [`channel`] returns a [`Sender`] and a [`Receiver`]. The sender sends at
4//! most one value and never waits; the receiver is a [`Future`] that
5//! completes with the value, or with a [`error::RecvError`] when
6//! the sender is dropped without sending. The API is the established async
7//! one-shot channel API; nothing here needs a runtime, and every wait is a
8//! plain [`Waker`](std::task::Waker) handshake.
9//!
10//! ```
11//! use nuclei::sync::oneshot;
12//!
13//! let (tx, rx) = oneshot::channel();
14//! std::thread::spawn(move || {
15//! tx.send(3).expect("the receiver is still there");
16//! });
17//! assert_eq!(rx.blocking_recv(), Ok(3));
18//! ```
19//!
20//! If the sender is dropped without sending, the receiver fails:
21//!
22//! ```
23//! use nuclei::sync::oneshot;
24//!
25//! let (tx, rx) = oneshot::channel::<u32>();
26//! drop(tx);
27//! assert!(rx.blocking_recv().is_err());
28//! ```
29//!
30//! A value that was sent but never received stays in the channel until the
31//! receiver is dropped, which drops it on the spot.
32//!
33//! # Progress
34//!
35//! Every operation of the channel is wait-free: it runs a bounded number of
36//! atomic read-modify-writes and loads of its own, and none of them loops
37//! because another thread got in first or waits for another thread. That
38//! covers [`Sender::send`], [`Sender::is_closed`], [`Sender::poll_closed`],
39//! every poll of the [`Receiver`], [`Receiver::try_recv`],
40//! [`Receiver::close`], [`Receiver::is_empty`], [`Receiver::is_terminated`]
41//! and the drop of either half. Three things are not counted. A [`Waker`](std::task::Waker)
42//! the channel calls is the executor's, and so is what it does; the
43//! destructor of the value runs in the call that drops it; and
44//! [`Receiver::blocking_recv`] parks the calling thread until the value
45//! arrives, which is what it is for.
46//!
47//! # How the halves agree on the value
48//!
49//! The value lives in one cell, `UnsafeCell<MaybeUninit<T>>`, and the state
50//! word has three bits: `VALUE_SENT`, `RX_CLOSED` and `TX_DROPPED`. Every
51//! bit is set once, with one `fetch_or`, so the word has one modification
52//! order that both halves read their outcome from. The cell has exactly one
53//! owner at a time:
54//!
55//! 1. Before the sender's `fetch_or`, the sender owns the cell and the
56//! receiver never reads it: the receiver reads it only after it saw
57//! `VALUE_SENT` in a word it loaded with `Acquire`, or in the word its own
58//! `fetch_or` returned.
59//! 2. `send` writes the value, then does one `fetch_or(VALUE_SENT |
60//! TX_DROPPED)` and looks at the word that came back.
61//! - `RX_CLOSED` was clear: the receiver's `fetch_or(RX_CLOSED)`, if it
62//! ever happens, comes later in the order, so the receiver's own result
63//! shows `VALUE_SENT`. The send succeeded and the cell is the
64//! receiver's.
65//! - `RX_CLOSED` was set: the receiver's `fetch_or` came first and its
66//! result showed no `VALUE_SENT`, so the receiver wrote down that its
67//! channel closed empty (`RxClose::Empty`) and never reads the cell,
68//! whatever bits show up later. The sender reads its value back out and
69//! returns it.
70//! 3. The receiver's side reads the cell exactly once, in the first of: a
71//! poll or `try_recv` that sees `VALUE_SENT` (it takes the value out and
72//! forgets the channel), or `Receiver::drop` (it drops the value if
73//! `VALUE_SENT` was set when it closed). A receiver that closed empty
74//! skips all of these.
75//!
76//! So a value is read by the sender (a failed send), by the receiver's take
77//! (a received value), or by the receiver's drop (an unreceived value), never
78//! by two of them, and never leaked while both halves honour the protocol:
79//! the cell needs no drop glue of its own.
80//!
81//! # Wakeups
82//!
83//! The receiver's task and the sender's task each have an
84//! `AtomicWaker`. A poll registers its
85//! waker and then looks at the state word again, and a state change is
86//! followed by a wake of the other side's waker, so a change is either seen
87//! by the re-check or woken: see the waker's module for the handshake.
88
89#![allow(unsafe_code)]
90
91use core::fmt;
92use core::future::Future;
93use core::mem::MaybeUninit;
94use core::pin::Pin;
95use core::task::{Context, Poll};
96
97use super::atomic_waker::AtomicWaker;
98use super::internal::{AtomicUsize, BlockArc, Ordering, UnsafeCell};
99
100/// The sender wrote the value and published it, in the same step that
101/// raised `TX_DROPPED`.
102const VALUE_SENT: usize = 0b001;
103/// The receiver closed or was dropped: no later send can succeed.
104const RX_CLOSED: usize = 0b010;
105/// The sender is gone: it sent, or it was dropped without sending.
106const TX_DROPPED: usize = 0b100;
107
108/// Error types of the one-shot channel.
109pub mod error {
110 use core::fmt;
111
112 /// Error returned by the `Future` implementation of
113 /// [`Receiver`](super::Receiver).
114 ///
115 /// The receiver gets it when the sender is dropped without sending, or
116 /// when the receiver was closed with nothing sent.
117 #[derive(Debug, Eq, PartialEq, Clone)]
118 pub struct RecvError(pub(crate) ());
119
120 /// Error returned by [`Receiver::try_recv`](super::Receiver::try_recv).
121 #[derive(Debug, Eq, PartialEq, Clone)]
122 pub enum TryRecvError {
123 /// The send half of the channel has not yet sent a value.
124 Empty,
125
126 /// The send half of the channel was dropped without sending a value,
127 /// or the value has already been received.
128 Closed,
129 }
130
131 impl fmt::Display for RecvError {
132 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(fmt, "channel closed")
134 }
135 }
136
137 impl std::error::Error for RecvError {}
138
139 impl fmt::Display for TryRecvError {
140 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
141 match self {
142 TryRecvError::Empty => write!(fmt, "channel empty"),
143 TryRecvError::Closed => write!(fmt, "channel closed"),
144 }
145 }
146 }
147
148 impl std::error::Error for TryRecvError {}
149}
150
151use self::error::{RecvError, TryRecvError};
152
153/// What the receiver wrote down about its own close; see the module docs for
154/// why it must (the state word alone cannot say who owns the cell once the
155/// receiver closed).
156#[derive(Clone, Copy, PartialEq, Eq)]
157enum RxClose {
158 /// The receiver has not closed.
159 Open,
160 /// It closed after the value was sent: the cell is the receiver's.
161 WithValue,
162 /// It closed before any value was sent: the cell is never the receiver's.
163 Empty,
164}
165
166struct Inner<T> {
167 state: AtomicUsize,
168 /// Written once by the sender before it raises `VALUE_SENT`; read once by
169 /// the receiver after it saw the bit. Ownership: see the module docs.
170 value: UnsafeCell<MaybeUninit<T>>,
171 /// The receiver's task, woken when the state changes in its favour.
172 rx_waker: AtomicWaker,
173 /// The sender's task, woken when the receiver closes.
174 tx_waker: AtomicWaker,
175}
176
177// SAFETY: the cell is accessed by one side at a time (module docs), and a `T`
178// crosses from the sender's thread to the receiver's, so `T: Send` is the
179// whole requirement; no `&T` is ever shared.
180unsafe impl<T: Send> Send for Inner<T> {}
181// SAFETY: as above.
182unsafe impl<T: Send> Sync for Inner<T> {}
183
184impl<T> Inner<T> {
185 fn new() -> Self {
186 Self {
187 state: AtomicUsize::new(0),
188 value: UnsafeCell::new(MaybeUninit::uninit()),
189 rx_waker: AtomicWaker::new(),
190 tx_waker: AtomicWaker::new(),
191 }
192 }
193
194 /// Moves the value out of the cell.
195 ///
196 /// # Safety
197 ///
198 /// The caller owns the cell (module docs) and the value is initialised
199 /// and not yet read.
200 unsafe fn read_value(&self) -> T {
201 // SAFETY: the caller's contract.
202 self.value
203 .with_mut(|slot| unsafe { (*slot).assume_init_read() })
204 }
205
206 /// The receiver's outcome against `state`, a word it loaded with
207 /// `Acquire`: `Some(Some(value))`, `Some(None)` when nothing will ever
208 /// come, or `None` while the channel is open and empty.
209 ///
210 /// # Safety
211 ///
212 /// Called by the receiver, once per value: the caller drops its handle
213 /// when this returns `Some`.
214 unsafe fn resolve(&self, close: RxClose, state: usize) -> Option<Option<T>> {
215 // SAFETY: the caller's contract, passed on.
216 unsafe { self.resolve_if(close, state, || true) }.ok()?
217 }
218
219 /// [`resolve`](Self::resolve) that asks `admit` once the receive would
220 /// complete and before it reads the value: `Err(())` when `admit` says
221 /// no, the cell untouched.
222 ///
223 /// # Safety
224 ///
225 /// As for [`resolve`](Self::resolve), for an answer that is not `Err`.
226 #[inline]
227 unsafe fn resolve_if(
228 &self,
229 close: RxClose,
230 state: usize,
231 admit: impl FnOnce() -> bool,
232 ) -> Result<Option<Option<T>>, ()> {
233 let completes = close == RxClose::Empty || state & (VALUE_SENT | TX_DROPPED) != 0;
234 if completes && !admit() {
235 return Err(());
236 }
237 Ok(if close == RxClose::Empty {
238 Some(None)
239 } else if state & VALUE_SENT != 0 {
240 // SAFETY: the sender raised VALUE_SENT after writing the value, and
241 // the receiver did not close empty, so the cell is the receiver's
242 // (module docs, rule 2). The caller retires the handle on `Some`.
243 Some(Some(unsafe { self.read_value() }))
244 } else if state & TX_DROPPED != 0 {
245 Some(None)
246 } else {
247 None
248 })
249 }
250}
251
252/// Creates a one-shot channel for sending a single value between tasks.
253///
254/// The [`Sender`] sends the value; the [`Receiver`] awaits it.
255///
256/// ```
257/// use nuclei::sync::oneshot;
258///
259/// let (tx, mut rx) = oneshot::channel();
260/// assert!(rx.try_recv().is_err());
261/// tx.send("hello").expect("the receiver is still there");
262/// assert_eq!(rx.try_recv(), Ok("hello"));
263/// ```
264pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
265 let inner = BlockArc::new(Inner::new());
266 let tx = Sender {
267 inner: Some(BlockArc::clone(&inner)),
268 };
269 let rx = Receiver {
270 inner: Some(inner),
271 close: RxClose::Open,
272 };
273 (tx, rx)
274}
275
276/// Sends a value to the associated [`Receiver`].
277///
278/// A [`Sender`] and a [`Receiver`] are created together by [`channel`].
279/// Every operation is wait-free; see the [module docs](self).
280///
281/// ```
282/// use nuclei::sync::oneshot;
283///
284/// let (tx, rx) = oneshot::channel();
285/// tx.send(3).expect("the receiver is still there");
286/// assert_eq!(rx.blocking_recv(), Ok(3));
287/// ```
288///
289/// To use a `Sender` from a destructor, put it in an [`Option`] and call
290/// [`Option::take`].
291pub struct Sender<T> {
292 /// `None` only after `send` took it.
293 inner: Option<BlockArc<Inner<T>>>,
294}
295
296impl<T> Sender<T> {
297 /// Attempts to send a value on this channel, returning it back if it
298 /// could not be sent.
299 ///
300 /// This method consumes `self`, since only one value may ever be sent on
301 /// a `oneshot` channel. It never waits, so it can be used in both
302 /// synchronous and asynchronous code.
303 ///
304 /// A successful send means the other end had not hung up when the value
305 /// was published; an unsuccessful one means the [`Receiver`] was already
306 /// closed or dropped, and the value comes back in the `Err`. `Ok` does
307 /// *not* promise the value will be received: the receiver can hang up
308 /// right after this returns.
309 ///
310 /// Wait-free: one write and one atomic read-modify-write, plus the wake
311 /// of the receiver's task.
312 ///
313 /// ```
314 /// use nuclei::sync::oneshot;
315 ///
316 /// let (tx, rx) = oneshot::channel();
317 /// drop(rx);
318 /// assert_eq!(tx.send(3), Err(3));
319 /// ```
320 pub fn send(mut self, value: T) -> Result<(), T> {
321 let Some(inner) = self.inner.take() else {
322 return Err(value);
323 };
324 // SAFETY: VALUE_SENT is raised only below, and this consumes the only
325 // `Sender`, so the receiver cannot be reading the cell (module docs,
326 // rule 1).
327 inner.value.with_mut(|slot| unsafe {
328 (*slot).write(value);
329 });
330 // AcqRel: the release publishes the write above to the receiver's
331 // acquire loads; the acquire orders this word after the receiver's
332 // close when it won the race.
333 let prev = inner
334 .state
335 .fetch_or(VALUE_SENT | TX_DROPPED, Ordering::AcqRel);
336 if prev & RX_CLOSED != 0 {
337 // SAFETY: the receiver closed first and wrote down that no value
338 // was there (module docs, rule 2), so the cell is still ours and
339 // holds the value written above.
340 return Err(unsafe { inner.read_value() });
341 }
342 inner.rx_waker.wake();
343 Ok(())
344 }
345
346 /// Waits for the associated [`Receiver`] to close.
347 ///
348 /// A receiver closes by [`Receiver::close`] or by being dropped. This is
349 /// useful with a select to abort a computation whose result nobody wants
350 /// any more.
351 ///
352 /// ```
353 /// use nuclei::sync::oneshot;
354 /// use std::future::Future;
355 /// use std::pin::pin;
356 /// use std::task::{Context, Poll, Waker};
357 ///
358 /// let (mut tx, rx) = oneshot::channel::<()>();
359 /// let mut cx = Context::from_waker(Waker::noop());
360 /// {
361 /// let mut closed = pin!(tx.closed());
362 /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Pending);
363 /// drop(rx);
364 /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Ready(()));
365 /// }
366 /// ```
367 pub async fn closed(&mut self) {
368 std::future::poll_fn(|cx| self.poll_closed(cx)).await;
369 }
370
371 /// Whether the associated [`Receiver`] has closed or been dropped.
372 ///
373 /// When this is `true`, a call to [`send`](Self::send) always fails.
374 ///
375 /// ```
376 /// use nuclei::sync::oneshot;
377 ///
378 /// let (tx, rx) = oneshot::channel::<u8>();
379 /// assert!(!tx.is_closed());
380 /// drop(rx);
381 /// assert!(tx.is_closed());
382 /// ```
383 pub fn is_closed(&self) -> bool {
384 self.inner
385 .as_ref()
386 .is_none_or(|inner| inner.state.load(Ordering::Acquire) & RX_CLOSED != 0)
387 }
388
389 /// Checks whether the channel is closed and, if it is not, arranges for
390 /// the waker of `cx` to be woken when it closes.
391 ///
392 /// Only the waker of the most recent call is kept.
393 ///
394 /// Returns [`Poll::Pending`] while the channel is open and
395 /// [`Poll::Ready`] once the receiver closed. Wait-free.
396 pub fn poll_closed(&mut self, cx: &mut Context<'_>) -> Poll<()> {
397 let Some(inner) = self.inner.as_ref() else {
398 return Poll::Ready(());
399 };
400 if inner.state.load(Ordering::Acquire) & RX_CLOSED != 0 {
401 return Poll::Ready(());
402 }
403 inner.tx_waker.register(cx.waker());
404 // The re-check after the registration is what makes a close that
405 // raced the registration visible; see the waker's handshake.
406 if inner.state.load(Ordering::Acquire) & RX_CLOSED != 0 {
407 Poll::Ready(())
408 } else {
409 Poll::Pending
410 }
411 }
412}
413
414impl<T> Drop for Sender<T> {
415 fn drop(&mut self) {
416 let Some(inner) = self.inner.as_ref() else {
417 return;
418 };
419 // AcqRel: the release hands the receiver this word; the acquire is for
420 // the close it may have raised first.
421 let prev = inner.state.fetch_or(TX_DROPPED, Ordering::AcqRel);
422 // A receiver that closed polls to an answer without waiting.
423 if prev & RX_CLOSED == 0 {
424 inner.rx_waker.wake();
425 }
426 }
427}
428
429impl<T> fmt::Debug for Sender<T> {
430 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
431 f.debug_struct("Sender")
432 .field("is_closed", &self.is_closed())
433 .finish()
434 }
435}
436
437/// Receives a value from the associated [`Sender`].
438///
439/// A [`Sender`] and a [`Receiver`] are created together by [`channel`]. The
440/// receiver is itself a [`Future`]: await it to get a
441/// `Result<T, `[`error::RecvError`]`>`. There is no `recv`
442/// method.
443///
444/// Polling a receiver never fails spuriously: a value sent before a poll
445/// starts is returned by that poll.
446///
447/// # Cancel safety
448///
449/// Awaiting a `&mut Receiver<T>` is cancel safe. If it is a branch of a
450/// select and another branch completes first, no value was received on this
451/// channel.
452///
453/// # Panics
454///
455/// Polling a receiver again after it completed (it returned `Ready`, or
456/// [`try_recv`](Self::try_recv) returned a value or
457/// [`TryRecvError::Closed`]) panics with `called after complete`. Check
458/// [`is_terminated`](Self::is_terminated) first.
459///
460/// ```
461/// use nuclei::sync::oneshot;
462/// use std::future::Future;
463/// use std::pin::Pin;
464/// use std::task::{Context, Poll, Waker};
465///
466/// let (tx, mut rx) = oneshot::channel();
467/// let mut cx = Context::from_waker(Waker::noop());
468/// assert_eq!(Pin::new(&mut rx).poll(&mut cx), Poll::Pending);
469/// tx.send(7).expect("the receiver is still there");
470/// assert_eq!(Pin::new(&mut rx).poll(&mut cx), Poll::Ready(Ok(7)));
471/// assert!(rx.is_terminated());
472/// ```
473pub struct Receiver<T> {
474 /// `None` once the receiver completed: it returned its value or an error.
475 inner: Option<BlockArc<Inner<T>>>,
476 close: RxClose,
477}
478
479impl<T> Receiver<T> {
480 /// Prevents the associated [`Sender`] from sending a value.
481 ///
482 /// Any `send` that happens after `close` returns fails. A value sent
483 /// *before* `close` can still be taken with [`try_recv`](Self::try_recv)
484 /// (or by polling). This makes a graceful shutdown possible: close, then
485 /// drain.
486 ///
487 /// `close` does nothing if the value was already received or the
488 /// channel is already closed. Wait-free.
489 ///
490 /// ```
491 /// use nuclei::sync::oneshot;
492 ///
493 /// let (tx, mut rx) = oneshot::channel();
494 /// tx.send("sent before").expect("the receiver is still there");
495 /// rx.close();
496 /// assert_eq!(rx.try_recv(), Ok("sent before"));
497 ///
498 /// let (tx, mut rx) = oneshot::channel();
499 /// rx.close();
500 /// assert!(tx.is_closed());
501 /// assert_eq!(tx.send("too late"), Err("too late"));
502 /// ```
503 pub fn close(&mut self) {
504 let Some(inner) = self.inner.as_ref() else {
505 return;
506 };
507 if self.close != RxClose::Open {
508 return;
509 }
510 // AcqRel: the acquire pairs with the sender's release, so a value
511 // that this word shows is visible; the release is for the sender.
512 let prev = inner.state.fetch_or(RX_CLOSED, Ordering::AcqRel);
513 self.close = if prev & VALUE_SENT != 0 {
514 RxClose::WithValue
515 } else {
516 RxClose::Empty
517 };
518 // A sender that is gone has nobody to wake.
519 if prev & TX_DROPPED == 0 {
520 inner.tx_waker.wake();
521 }
522 }
523
524 /// Whether this receiver already completed: it returned its value or an
525 /// error, so it must not be polled again.
526 ///
527 /// ```
528 /// use nuclei::sync::oneshot;
529 ///
530 /// let (tx, mut rx) = oneshot::channel();
531 /// assert!(!rx.is_terminated());
532 /// tx.send(0).expect("the receiver is still there");
533 /// assert!(!rx.is_terminated(), "a value that was sent but not read");
534 /// assert_eq!(rx.try_recv(), Ok(0));
535 /// assert!(rx.is_terminated());
536 /// ```
537 pub fn is_terminated(&self) -> bool {
538 self.inner.is_none()
539 }
540
541 /// Whether the channel holds no value.
542 ///
543 /// `true` before a send, after the sender was dropped, and after the
544 /// receiver completed. It is not a promise that polling is safe: use
545 /// [`is_terminated`](Self::is_terminated) for that.
546 ///
547 /// ```
548 /// use nuclei::sync::oneshot;
549 ///
550 /// let (tx, rx) = oneshot::channel();
551 /// assert!(rx.is_empty());
552 /// tx.send(0).expect("the receiver is still there");
553 /// assert!(!rx.is_empty());
554 /// ```
555 pub fn is_empty(&self) -> bool {
556 let Some(inner) = self.inner.as_ref() else {
557 return true;
558 };
559 self.close == RxClose::Empty || inner.state.load(Ordering::Acquire) & VALUE_SENT == 0
560 }
561
562 /// Attempts to receive a value without waiting.
563 ///
564 /// The current task is *not* registered for a later wake. Unlike a
565 /// poll, it cannot fail spuriously: any send or close that happened
566 /// before the call is reported. Wait-free.
567 ///
568 /// - `Ok(value)` when a value is waiting.
569 /// - `Err(TryRecvError::Empty)` when none was sent yet.
570 /// - `Err(TryRecvError::Closed)` when the sender was dropped without
571 /// sending, the channel was closed empty, or the value was received
572 /// already.
573 ///
574 /// ```
575 /// use nuclei::sync::oneshot::{self, error::TryRecvError};
576 ///
577 /// let (tx, mut rx) = oneshot::channel();
578 /// assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
579 /// tx.send("hello").expect("the receiver is still there");
580 /// assert_eq!(rx.try_recv(), Ok("hello"));
581 /// assert_eq!(rx.try_recv(), Err(TryRecvError::Closed));
582 /// ```
583 pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
584 let Some(inner) = self.inner.as_ref() else {
585 return Err(TryRecvError::Closed);
586 };
587 let state = inner.state.load(Ordering::Acquire);
588 // SAFETY: the handle is retired just below whenever this returns `Some`.
589 match unsafe { inner.resolve(self.close, state) } {
590 Some(done) => {
591 self.inner = None;
592 done.ok_or(TryRecvError::Closed)
593 }
594 None => Err(TryRecvError::Empty),
595 }
596 }
597
598 /// Receives the value on this thread, parking the thread until it
599 /// arrives.
600 ///
601 /// For use outside asynchronous code. On a nuclei shard (inside one of its tasks) it does not park the thread: it runs a nested `block_on`, so the shard keeps running its other tasks meanwhile. Inside another runtime's task
602 /// it blocks that task's executor thread, so do not. It is not wait-free:
603 /// waiting for the sender is what it does.
604 ///
605 /// # Panics
606 ///
607 /// Panics if the receiver already completed; see [`Receiver`]. On
608 /// `wasm32`, where no other thread can send, it also panics when the
609 /// value is not there already: the call could never end.
610 ///
611 /// ```
612 /// use nuclei::sync::oneshot;
613 ///
614 /// let (tx, rx) = oneshot::channel::<u8>();
615 /// let sender = std::thread::spawn(move || tx.send(10));
616 /// assert_eq!(rx.blocking_recv(), Ok(10));
617 /// sender.join().expect("sender thread").expect("the receiver was waiting");
618 /// ```
619 pub fn blocking_recv(self) -> Result<T, RecvError> {
620 super::internal::blocking(self)
621 }
622}
623
624impl<T> Drop for Receiver<T> {
625 fn drop(&mut self) {
626 let Some(inner) = self.inner.as_ref() else {
627 return;
628 };
629 let owns_value = match self.close {
630 RxClose::WithValue => true,
631 RxClose::Empty => false,
632 RxClose::Open => {
633 // AcqRel: as in `close`.
634 let prev = inner.state.fetch_or(RX_CLOSED, Ordering::AcqRel);
635 if prev & TX_DROPPED == 0 {
636 inner.tx_waker.wake();
637 }
638 prev & VALUE_SENT != 0
639 }
640 };
641 if owns_value {
642 // SAFETY: VALUE_SENT was set before this receiver closed, so the
643 // cell is the receiver's (module docs, rule 2) and nothing read it:
644 // a receiver that read it has no `inner`.
645 drop(unsafe { inner.read_value() });
646 }
647 }
648}
649
650impl<T> Future for Receiver<T> {
651 type Output = Result<T, RecvError>;
652
653 #[expect(
654 clippy::panic,
655 reason = "polled after it completed, which the `Future` contract rules out"
656 )]
657 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
658 let this = self.get_mut();
659 let Some(inner) = this.inner.as_ref() else {
660 panic!("called after complete");
661 };
662 let mut state = inner.state.load(Ordering::Acquire);
663 let mut registered = false;
664 // A receive that completes spends one operation of the poll's budget;
665 // with the budget spent it takes nothing and yields (see `coop`).
666 let admit = || crate::coop::spend(cx.waker());
667 loop {
668 // SAFETY: the handle is retired just below whenever this returns `Some`.
669 match unsafe { inner.resolve_if(this.close, state, admit) } {
670 Ok(Some(done)) => {
671 this.inner = None;
672 return Poll::Ready(done.ok_or(RecvError(())));
673 }
674 Err(()) => return Poll::Pending,
675 Ok(None) => {}
676 }
677 if registered {
678 return Poll::Pending;
679 }
680 inner.rx_waker.register(cx.waker());
681 registered = true;
682 // The re-check after the registration is what makes a send that
683 // raced the registration visible; see the waker's handshake.
684 state = inner.state.load(Ordering::Acquire);
685 }
686 }
687}
688
689impl<T> fmt::Debug for Receiver<T> {
690 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
691 f.debug_struct("Receiver")
692 .field("is_terminated", &self.is_terminated())
693 .field("is_empty", &self.is_empty())
694 .finish()
695 }
696}
697
698#[cfg(all(test, not(loom)))]
699mod tests {
700 use super::*;
701 use crate::sync::test_support::{Polled, block_on};
702 use std::sync::atomic::{AtomicUsize as StdAtomicUsize, Ordering as StdOrdering};
703
704 /// Counts how many values were dropped.
705 struct DropCount(std::sync::Arc<StdAtomicUsize>);
706
707 impl Drop for DropCount {
708 fn drop(&mut self) {
709 self.0.fetch_add(1, StdOrdering::SeqCst);
710 }
711 }
712
713 fn counted() -> (std::sync::Arc<StdAtomicUsize>, DropCount) {
714 let drops = std::sync::Arc::new(StdAtomicUsize::new(0));
715 (std::sync::Arc::clone(&drops), DropCount(drops))
716 }
717
718 #[test]
719 fn a_pending_receiver_is_woken_by_the_send() {
720 let (tx, rx) = channel();
721 let mut rx = Polled::new(rx);
722 rx.pending();
723 assert!(tx.send(5).is_ok());
724 assert_eq!(rx.wakes(), 1);
725 assert_eq!(rx.ready(), Ok(5));
726 }
727
728 #[test]
729 fn a_pending_sender_is_woken_by_the_close() {
730 let (mut tx, mut rx) = channel::<u8>();
731 let mut closed = Polled::new(std::future::poll_fn(|cx| tx.poll_closed(cx)));
732 closed.pending();
733 rx.close();
734 assert_eq!(closed.wakes(), 1);
735 closed.ready();
736 drop(closed);
737 assert_eq!(tx.send(1), Err(1));
738 }
739
740 #[test]
741 fn an_unreceived_value_is_dropped_by_the_receiver() {
742 let (drops, value) = counted();
743 let (tx, rx) = channel();
744 assert!(tx.send(value).is_ok());
745 assert_eq!(drops.load(StdOrdering::SeqCst), 0, "the channel holds it");
746 drop(rx);
747 assert_eq!(drops.load(StdOrdering::SeqCst), 1);
748 }
749
750 #[test]
751 fn a_closed_receiver_still_owns_a_value_sent_before_the_close() {
752 let (drops, value) = counted();
753 let (tx, mut rx) = channel();
754 assert!(tx.send(value).is_ok());
755 rx.close();
756 assert_eq!(drops.load(StdOrdering::SeqCst), 0);
757 drop(rx);
758 assert_eq!(drops.load(StdOrdering::SeqCst), 1);
759 }
760
761 #[test]
762 fn a_failed_send_returns_the_value_and_drops_it_once() {
763 let (drops, value) = counted();
764 let (tx, mut rx) = channel();
765 rx.close();
766 let back = tx.send(value).expect_err("the receiver closed");
767 assert_eq!(drops.load(StdOrdering::SeqCst), 0, "returned, not dropped");
768 drop(back);
769 drop(rx);
770 assert_eq!(drops.load(StdOrdering::SeqCst), 1);
771 }
772
773 #[test]
774 fn a_received_value_is_not_dropped_by_the_channel() {
775 let (drops, value) = counted();
776 let (tx, mut rx) = channel();
777 assert!(tx.send(value).is_ok());
778 let value = rx.try_recv().expect("sent");
779 drop(rx);
780 assert_eq!(drops.load(StdOrdering::SeqCst), 0);
781 drop(value);
782 assert_eq!(drops.load(StdOrdering::SeqCst), 1);
783 }
784
785 #[test]
786 fn a_value_sent_across_threads_arrives_and_drops_once() {
787 for _ in 0..if cfg!(miri) { 5 } else { 500 } {
788 let (drops, value) = counted();
789 let (tx, rx) = channel();
790 let sender = std::thread::spawn(move || tx.send(value).is_ok());
791 let got = block_on(rx);
792 assert!(sender.join().expect("sender"));
793 drop(got);
794 assert_eq!(drops.load(StdOrdering::SeqCst), 1);
795 }
796 }
797
798 #[test]
799 #[should_panic(expected = "called after complete")]
800 fn polling_a_completed_receiver_panics() {
801 let (tx, rx) = channel();
802 assert!(tx.send(1).is_ok());
803 let mut rx = Polled::new(rx);
804 assert_eq!(rx.ready(), Ok(1));
805 let _ = rx.poll();
806 }
807}