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}