Skip to main content

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}