Skip to main content

nuclei/sync/mpsc/
receiver.rs

1//! The receiving half of the bounded channel.
2
3use core::fmt;
4use core::future::{Future, poll_fn};
5use core::marker::PhantomPinned;
6use core::task::{Context, Poll};
7
8use super::bounded::Bounded;
9use super::chan::Chan;
10use super::error::TryRecvError;
11use crate::sync::internal::{self, Arc};
12
13/// Receives values from the associated [`Sender`](super::Sender)s.
14///
15/// Created by [`channel`](super::channel). There is exactly one receiver.
16///
17/// # Progress
18///
19/// Wait-free: [`is_closed`](Self::is_closed), [`is_empty`](Self::is_empty),
20/// [`len`](Self::len), [`capacity`](Self::capacity),
21/// [`max_capacity`](Self::max_capacity),
22/// [`sender_strong_count`](Self::sender_strong_count) and
23/// [`sender_weak_count`](Self::sender_weak_count): each is a load.
24///
25/// Lock-free: [`recv`](Self::recv), [`recv_many`](Self::recv_many),
26/// [`try_recv`](Self::try_recv) and the two `poll_` forms. Registering the
27/// waker is wait-free (the cell runs two read-modify-writes and no loop).
28/// Taking a value off the message queue is a compare-and-swap no other thread
29/// contends for, and never waits for a sender: a value whose send claimed its
30/// place and has not written it yet is not there, and its sender wakes the
31/// receiver once it is (see the [Progress](super#progress) notes of the
32/// module). Giving the slot back to the senders is a semaphore release
33/// that, when senders wait, serves the queue and is lock-free.
34/// [`close`](Self::close) is lock-free; the drop is the same as a receive per
35/// value left, since it drops every value still queued, and so takes time
36/// proportional to them.
37///
38/// `blocking_recv` and `blocking_recv_many` park the calling thread until a
39/// value arrives.
40pub struct Receiver<T> {
41    chan: Arc<Chan<T, Bounded>>,
42}
43
44impl<T> Receiver<T> {
45    pub(super) fn new(chan: Arc<Chan<T, Bounded>>) -> Self {
46        Self { chan }
47    }
48
49    /// Receives the next value.
50    ///
51    /// Returns `None` once the channel is closed and no buffered value is
52    /// left, which means no value can ever be received again. The channel is
53    /// closed when every sender has been dropped, or when
54    /// [`close`](Self::close) is called. If the buffer is empty and the
55    /// channel is open, it waits for a send or a close.
56    ///
57    /// If [`close`](Self::close) was called while a [`Permit`](super::Permit)
58    /// or an [`OwnedPermit`](super::OwnedPermit) was still held, the channel
59    /// does not count as finished for `recv` until the permit is sent or
60    /// dropped.
61    ///
62    /// # Cancel safety
63    ///
64    /// Cancel safe. If the future is dropped (for instance when another branch
65    /// of a `select` wins), no value was taken from the channel.
66    ///
67    /// ```
68    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
69    /// # fn now<F: Future>(f: F) -> F::Output {
70    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
71    /// #         Poll::Ready(out) => out,
72    /// #         Poll::Pending => panic!("not ready"),
73    /// #     }
74    /// # }
75    /// use nuclei::sync::mpsc;
76    ///
77    /// let (tx, mut rx) = mpsc::channel(100);
78    /// tx.try_send("hello").unwrap();
79    /// tx.try_send("world").unwrap();
80    /// drop(tx);
81    /// assert_eq!(now(rx.recv()), Some("hello"));
82    /// assert_eq!(now(rx.recv()), Some("world"));
83    /// assert_eq!(now(rx.recv()), None);
84    /// ```
85    pub fn recv(&mut self) -> impl Future<Output = Option<T>> + '_ {
86        // The poll itself, with no state of an `async fn` around it; not
87        // `Unpin`, as the established API's receive future is not.
88        let pinned = PhantomPinned;
89        poll_fn(move |cx| {
90            let _ = &pinned;
91            self.poll_recv(cx)
92        })
93    }
94
95    /// Receives the next values and appends them to `buffer`, taking at most
96    /// `limit` of them in one call.
97    ///
98    /// Returns how many values it added. A `limit` of zero returns `0` at
99    /// once. Otherwise it waits like [`recv`](Self::recv) until at least one
100    /// value is there, then takes everything that is ready up to `limit`
101    /// without waiting again, and returns `0` only when the channel is closed
102    /// and empty. The capacity of `buffer` grows as needed.
103    ///
104    /// # Cancel safety
105    ///
106    /// Cancel safe, as [`recv`](Self::recv): a dropped future took nothing.
107    ///
108    /// ```
109    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
110    /// # fn now<F: Future>(f: F) -> F::Output {
111    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
112    /// #         Poll::Ready(out) => out,
113    /// #         Poll::Pending => panic!("not ready"),
114    /// #     }
115    /// # }
116    /// use nuclei::sync::mpsc;
117    ///
118    /// let (tx, mut rx) = mpsc::channel(100);
119    /// for word in ["first", "second", "third"] {
120    ///     tx.try_send(word).unwrap();
121    /// }
122    /// let mut buffer = Vec::new();
123    /// assert_eq!(now(rx.recv_many(&mut buffer, 2)), 2);
124    /// assert_eq!(buffer, ["first", "second"]);
125    /// assert_eq!(now(rx.recv_many(&mut buffer, 2)), 1);
126    /// drop(tx);
127    /// assert_eq!(now(rx.recv_many(&mut buffer, 2)), 0);
128    /// ```
129    pub async fn recv_many(&mut self, buffer: &mut Vec<T>, limit: usize) -> usize {
130        poll_fn(|cx| self.poll_recv_many(cx, buffer, limit)).await
131    }
132
133    /// Tries to receive the next value without waiting.
134    ///
135    /// # Errors
136    ///
137    /// [`TryRecvError::Empty`] if the channel is empty but a sender or a
138    /// permit still exists, so a value may yet come.
139    /// [`TryRecvError::Disconnected`] if it is empty and nothing can send:
140    /// every sender is gone, or the channel was closed and no permit is held.
141    ///
142    /// A value whose send is still in progress on another thread is not in the
143    /// channel yet, nor are the values sent after it, which come out behind
144    /// it. This call does not wait for them: the sender wakes the receiver
145    /// once its value is in.
146    ///
147    /// ```
148    /// use nuclei::sync::mpsc::{self, error::TryRecvError};
149    ///
150    /// let (tx, mut rx) = mpsc::channel(100);
151    /// tx.try_send("hello").unwrap();
152    /// assert_eq!(rx.try_recv(), Ok("hello"));
153    /// assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
154    ///
155    /// tx.try_send("hello").unwrap();
156    /// drop(tx);
157    /// assert_eq!(rx.try_recv(), Ok("hello"));
158    /// assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
159    /// ```
160    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
161        // SAFETY: `&mut self` of the channel's one receiver.
162        unsafe { self.chan.try_recv() }
163    }
164
165    /// Receives the next value from a thread that may block.
166    ///
167    /// Like [`recv`](Self::recv), but it parks the calling thread while the
168    /// channel is empty and open. 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 it
169    /// blocks that task's thread. It works whether or not the senders use
170    /// [`Sender::blocking_send`](super::Sender::blocking_send).
171    ///
172    /// # Panics
173    ///
174    /// On `wasm32`, where no other thread can send, when the channel is empty
175    /// and open: the call could never end.
176    ///
177    /// ```
178    /// use nuclei::sync::mpsc;
179    ///
180    /// let (tx, mut rx) = mpsc::channel::<u8>(10);
181    /// let receiver = std::thread::spawn(move || {
182    ///     assert_eq!(rx.blocking_recv(), Some(10));
183    ///     assert_eq!(rx.blocking_recv(), None);
184    /// });
185    /// tx.blocking_send(10).unwrap();
186    /// drop(tx);
187    /// receiver.join().unwrap();
188    /// ```
189    pub fn blocking_recv(&mut self) -> Option<T> {
190        internal::blocking(self.recv())
191    }
192
193    /// [`recv_many`](Self::recv_many) for a thread that may block; see
194    /// [`blocking_recv`](Self::blocking_recv).
195    ///
196    /// # Panics
197    ///
198    /// As for [`blocking_recv`](Self::blocking_recv).
199    pub fn blocking_recv_many(&mut self, buffer: &mut Vec<T>, limit: usize) -> usize {
200        internal::blocking(self.recv_many(buffer, limit))
201    }
202
203    /// Closes the receiving half without dropping it.
204    ///
205    /// No further value can be sent: a send fails and returns its value. A
206    /// slot reserved before the close can still be used, and the values
207    /// already buffered stay receivable, so a clean shutdown closes, then
208    /// calls [`recv`](Self::recv) until it returns `None`. That happens once
209    /// every reserved slot is sent or dropped.
210    ///
211    /// ```
212    /// use nuclei::sync::mpsc::{self, error::TrySendError};
213    ///
214    /// let (tx, mut rx) = mpsc::channel(20);
215    /// tx.try_send(1).unwrap();
216    /// rx.close();
217    /// assert!(matches!(tx.try_send(2), Err(TrySendError::Closed(2))));
218    /// assert_eq!(rx.try_recv(), Ok(1), "the buffered value is still there");
219    /// ```
220    pub fn close(&mut self) {
221        self.chan.close_rx();
222    }
223
224    /// Whether the channel is closed: [`close`](Self::close) was called, or
225    /// every sender is gone. Buffered values may still be received.
226    ///
227    /// ```
228    /// use nuclei::sync::mpsc;
229    ///
230    /// let (tx, mut rx) = mpsc::channel::<()>(10);
231    /// assert!(!rx.is_closed());
232    /// rx.close();
233    /// assert!(rx.is_closed());
234    /// drop(tx);
235    /// ```
236    pub fn is_closed(&self) -> bool {
237        self.chan.rx_is_closed()
238    }
239
240    /// Whether the channel holds no value.
241    ///
242    /// ```
243    /// use nuclei::sync::mpsc;
244    ///
245    /// let (tx, rx) = mpsc::channel(10);
246    /// assert!(rx.is_empty());
247    /// tx.try_send(0).unwrap();
248    /// assert!(!rx.is_empty());
249    /// ```
250    pub fn is_empty(&self) -> bool {
251        self.chan.len() == 0
252    }
253
254    /// How many values the channel holds.
255    ///
256    /// A snapshot: it is exact while no other thread is sending, and while one
257    /// is it may be off by the values being sent at that moment.
258    ///
259    /// ```
260    /// use nuclei::sync::mpsc;
261    ///
262    /// let (tx, rx) = mpsc::channel(10);
263    /// assert_eq!(rx.len(), 0);
264    /// tx.try_send(0).unwrap();
265    /// assert_eq!(rx.len(), 1);
266    /// ```
267    pub fn len(&self) -> usize {
268        self.chan.len()
269    }
270
271    /// The channel's current capacity: the slots that are free.
272    ///
273    /// It goes down when a value is sent or a slot reserved, and up when a
274    /// value is received or a permit dropped unused. Compare
275    /// [`max_capacity`](Self::max_capacity), which never changes.
276    ///
277    /// ```
278    /// use nuclei::sync::mpsc;
279    ///
280    /// let (tx, mut rx) = mpsc::channel::<()>(5);
281    /// assert_eq!(rx.capacity(), 5);
282    /// let permit = tx.try_reserve().unwrap();
283    /// assert_eq!(rx.capacity(), 4);
284    /// assert_eq!(rx.len(), 0);
285    /// permit.send(());
286    /// assert_eq!(rx.len(), 1);
287    /// rx.try_recv().unwrap();
288    /// assert_eq!(rx.capacity(), 5);
289    /// ```
290    pub fn capacity(&self) -> usize {
291        self.chan.limit.sem.available()
292    }
293
294    /// The channel's maximum capacity: the `buffer` it was created with.
295    ///
296    /// ```
297    /// use nuclei::sync::mpsc;
298    ///
299    /// let (tx, rx) = mpsc::channel::<()>(5);
300    /// let _permit = tx.try_reserve().unwrap();
301    /// assert_eq!(rx.max_capacity(), 5);
302    /// assert_eq!(rx.capacity(), 4);
303    /// ```
304    pub fn max_capacity(&self) -> usize {
305        self.chan.limit.bound
306    }
307
308    /// Polls to receive the next value.
309    ///
310    /// Returns [`Poll::Pending`] if no value is available and the channel is
311    /// open; [`Poll::Ready`]`(Some(value))` if one is; and
312    /// [`Poll::Ready`]`(None)` if the channel is closed and every value sent
313    /// before it closed was received.
314    ///
315    /// On `Pending`, the waker of `cx` is woken when a value arrives or the
316    /// channel closes. Only the waker of the most recent call to `poll_recv`
317    /// or [`poll_recv_many`](Self::poll_recv_many) is kept.
318    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
319        // SAFETY: `&mut self` of the channel's one receiver.
320        unsafe { self.chan.poll_recv(cx) }
321    }
322
323    /// Polls to receive several values into `buffer`, at most `limit`.
324    ///
325    /// Returns [`Poll::Pending`] if no value is available and the channel is
326    /// open; [`Poll::Ready`]`(count)` with the number of values added, which
327    /// is at least one unless `limit` is zero or the channel is closed and
328    /// empty. It takes everything that is ready, up to `limit`, in one call.
329    /// The waker of `cx` is handled as for [`poll_recv`](Self::poll_recv).
330    pub fn poll_recv_many(
331        &mut self,
332        cx: &mut Context<'_>,
333        buffer: &mut Vec<T>,
334        limit: usize,
335    ) -> Poll<usize> {
336        // SAFETY: `&mut self` of the channel's one receiver.
337        unsafe { self.chan.poll_recv_many(cx, buffer, limit) }
338    }
339
340    /// How many [`Sender`](super::Sender) handles exist.
341    pub fn sender_strong_count(&self) -> usize {
342        self.chan.strong_count()
343    }
344
345    /// How many [`WeakSender`](super::WeakSender) handles exist.
346    pub fn sender_weak_count(&self) -> usize {
347        self.chan.weak_count()
348    }
349}
350
351impl<T> Drop for Receiver<T> {
352    fn drop(&mut self) {
353        // SAFETY: the channel's one receiver, dropping.
354        unsafe { self.chan.drop_rx() };
355    }
356}
357
358impl<T> fmt::Debug for Receiver<T> {
359    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360        f.debug_struct("Receiver")
361            .field("closed", &self.is_closed())
362            .field("len", &self.len())
363            .field("capacity", &self.capacity())
364            .field("max_capacity", &self.max_capacity())
365            .finish()
366    }
367}