Skip to main content

ntex_util/channel/
mpsc.rs

1//! A multi-producer, single-consumer, futures-aware, FIFO queue.
2use std::collections::VecDeque;
3use std::future::poll_fn;
4use std::{fmt, panic::UnwindSafe, pin::Pin, task::Context, task::Poll};
5
6use futures_core::{FusedStream, Stream};
7
8use super::cell::{Cell, wake};
9use crate::task::LocalWaker;
10
11/// Creates an unbounded in-memory channel.
12pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
13    let shared = Cell::new(Shared {
14        has_receiver: true,
15        buffer: VecDeque::new(),
16        blocked_recv: LocalWaker::new(),
17        closed: LocalWaker::new(),
18    });
19    let sender = Sender {
20        shared: shared.clone(),
21    };
22    let receiver = Receiver { shared };
23    (sender, receiver)
24}
25
26#[derive(Debug)]
27struct Shared<T> {
28    buffer: VecDeque<T>,
29    blocked_recv: LocalWaker,
30    closed: LocalWaker,
31    has_receiver: bool,
32}
33
34fn close<T>(shared: &Cell<Shared<T>>) {
35    let (recv, closed) = {
36        let shared = shared.get_mut();
37        shared.has_receiver = false;
38        (shared.blocked_recv.take_local(), shared.closed.take_local())
39    };
40    wake(recv);
41    wake(closed);
42}
43
44/// The transmission end of a channel.
45///
46/// This is created by the `channel` function.
47#[derive(Debug)]
48pub struct Sender<T> {
49    shared: Cell<Shared<T>>,
50}
51
52impl<T> Unpin for Sender<T> {}
53
54impl<T> Sender<T> {
55    /// Sends the provided message along this channel.
56    pub fn send(&self, item: T) -> Result<(), SendError<T>> {
57        let waker = {
58            let shared = self.shared.get_mut();
59            if !shared.has_receiver {
60                return Err(SendError(item)); // receiver was dropped
61            }
62            shared.buffer.push_back(item);
63            shared.blocked_recv.take_local()
64        };
65        wake(waker);
66        Ok(())
67    }
68
69    /// Closes the channel for every sender.
70    ///
71    /// This prevents any further messages from being sent on the channel, by
72    /// this sender or any of its clones, while still enabling the receiver to
73    /// drain messages that are buffered.
74    pub fn close(&self) {
75        close(&self.shared);
76    }
77
78    /// Returns `true` if the channel is closed or the receiver has been dropped.
79    pub fn is_closed(&self) -> bool {
80        self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
81    }
82
83    /// Polls whether the channel is closed or the receiver has been dropped.
84    ///
85    /// Only the task from the most recent call is woken, across this sender
86    /// and all of its clones.
87    pub fn poll_closed(&self, cx: &mut Context<'_>) -> Poll<()> {
88        if !self.shared.get_ref().has_receiver {
89            return Poll::Ready(());
90        }
91        LocalWaker::register_in(|| &self.shared.get_ref().closed, cx.waker());
92
93        // the waker callbacks may have closed the channel
94        if self.shared.get_ref().has_receiver {
95            Poll::Pending
96        } else {
97            Poll::Ready(())
98        }
99    }
100
101    /// Waits until the channel is closed or the receiver has been dropped.
102    ///
103    /// Only one task may wait at a time, across this sender and all of its
104    /// clones; see [`poll_closed`](Self::poll_closed).
105    pub async fn closed(&self) {
106        poll_fn(|cx| self.poll_closed(cx)).await;
107    }
108}
109
110impl<T> Clone for Sender<T> {
111    fn clone(&self) -> Self {
112        Sender {
113            shared: self.shared.clone(),
114        }
115    }
116}
117
118impl<T> Drop for Sender<T> {
119    fn drop(&mut self) {
120        let count = self.shared.strong_count();
121        let waker = {
122            let shared = self.shared.get_mut();
123
124            // check is last sender is about to drop
125            if shared.has_receiver && count == 2 {
126                // the channel is closed for good, and the receiver's
127                // stream has ended
128                shared.has_receiver = false;
129                shared.blocked_recv.take_local()
130            } else {
131                None
132            }
133        };
134        wake(waker);
135    }
136}
137
138/// The receiving end of a channel which implements the `Stream` trait.
139///
140/// This is created by the `channel` function.
141///
142/// # Single waiter
143///
144/// The receiver stores one waker. [`recv`](Self::recv),
145/// [`poll_recv`](Self::poll_recv) and [`Stream::poll_next`] take `&self`, but
146/// only the task that polled most recently is woken. Wait for messages from
147/// one task at a time; an earlier concurrent waiter may stay pending even
148/// while messages are buffered.
149#[derive(Debug)]
150pub struct Receiver<T> {
151    shared: Cell<Shared<T>>,
152}
153
154impl<T> Receiver<T> {
155    /// Creates an additional sender for this channel.
156    ///
157    /// Closing is permanent: once the channel is closed, or every sender has
158    /// been dropped, the returned sender is closed too and its `send()` fails.
159    pub fn sender(&self) -> Sender<T> {
160        Sender {
161            shared: self.shared.clone(),
162        }
163    }
164
165    /// Closes the receiving half of a channel, without dropping it.
166    ///
167    /// This prevents any further messages from being sent on the channel
168    /// while still enabling the receiver to drain messages that are buffered.
169    pub fn close(&self) {
170        close(&self.shared);
171    }
172
173    /// Returns whether this channel is closed.
174    pub fn is_closed(&self) -> bool {
175        self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
176    }
177
178    /// Waits for the next message.
179    ///
180    /// Returns `None` once the channel is closed or every sender has been
181    /// dropped, and every buffered message has been received.
182    ///
183    /// Only one task may wait at a time; see [single waiter](Self#single-waiter).
184    pub async fn recv(&self) -> Option<T> {
185        poll_fn(|cx| self.poll_recv(cx)).await
186    }
187
188    /// Polls for the next message.
189    ///
190    /// Returns `Ready(None)` once the channel is closed or every sender has
191    /// been dropped, and every buffered message has been received.
192    ///
193    /// A pending poll replaces the previously registered waker; see
194    /// [single waiter](Self#single-waiter).
195    pub fn poll_recv(&self, cx: &mut Context<'_>) -> Poll<Option<T>> {
196        if let Poll::Ready(msg) = self.try_recv() {
197            return Poll::Ready(msg);
198        }
199        LocalWaker::register_in(|| &self.shared.get_ref().blocked_recv, cx.waker());
200
201        // the waker callbacks may have sent a message or closed the channel
202        self.try_recv()
203    }
204
205    fn try_recv(&self) -> Poll<Option<T>> {
206        let shared = self.shared.get_mut();
207        if let Some(msg) = shared.buffer.pop_front() {
208            Poll::Ready(Some(msg))
209        } else if !shared.has_receiver || self.shared.strong_count() == 1 {
210            // The channel is closed or all senders have been dropped, and the
211            // buffer is drained, so end the stream.
212            Poll::Ready(None)
213        } else {
214            Poll::Pending
215        }
216    }
217}
218
219impl<T> Unpin for Receiver<T> {}
220
221impl<T> Stream for Receiver<T> {
222    type Item = T;
223
224    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
225        self.poll_recv(cx)
226    }
227}
228
229impl<T> FusedStream for Receiver<T> {
230    /// Returns `true` once the channel is closed and every buffered message
231    /// has been received.
232    fn is_terminated(&self) -> bool {
233        self.is_closed() && self.shared.get_ref().buffer.is_empty()
234    }
235}
236
237impl<T> UnwindSafe for Receiver<T> {}
238
239impl<T> Drop for Receiver<T> {
240    fn drop(&mut self) {
241        let (buffer, waker) = {
242            let shared = self.shared.get_mut();
243            shared.has_receiver = false;
244            (
245                std::mem::take(&mut shared.buffer),
246                shared.closed.take_local(),
247            )
248        };
249        wake(waker);
250
251        // queued messages may send on this channel from their `Drop`
252        drop(buffer);
253    }
254}
255
256/// Error type for sending, used when the receiving end of a channel is
257/// dropped
258pub struct SendError<T>(T);
259
260impl<T> std::error::Error for SendError<T> {}
261
262impl<T> fmt::Debug for SendError<T> {
263    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
264        fmt.debug_tuple("SendError").field(&"...").finish()
265    }
266}
267
268impl<T> fmt::Display for SendError<T> {
269    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
270        write!(fmt, "send failed because receiver is gone")
271    }
272}
273
274impl<T> SendError<T> {
275    /// Returns the message that was attempted to be sent but failed.
276    pub fn into_inner(self) -> T {
277        self.0
278    }
279}
280
281#[cfg(test)]
282mod tests {
283    use super::*;
284    use crate::task::hooks::{ON_CLONE, hook_waker};
285    use crate::{future::lazy, future::stream_recv};
286
287    /// STATEMENT: MPSC sender clones share delivery and closure state.
288    ///
289    /// HOW:
290    /// - Send from original and cloned handles and verify an empty live channel remains pending.
291    /// - Close or drop endpoints, check failed sends, and recover the value from `SendError`.
292    #[ntex::test]
293    async fn test_mpsc() {
294        let (tx, mut rx) = channel();
295        assert!(format!("{tx:?}").contains("Sender"));
296        assert!(format!("{rx:?}").contains("Receiver"));
297
298        tx.send("test").unwrap();
299        assert_eq!(stream_recv(&mut rx).await.unwrap(), "test");
300
301        let tx2 = tx.clone();
302        tx2.send("test2").unwrap();
303        assert_eq!(stream_recv(&mut rx).await.unwrap(), "test2");
304
305        assert_eq!(
306            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
307            Poll::Pending
308        );
309        drop(tx2);
310        assert_eq!(
311            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
312            Poll::Pending
313        );
314        drop(tx);
315
316        let (tx, mut rx) = channel::<String>();
317        tx.close();
318        assert_eq!(stream_recv(&mut rx).await, None);
319
320        let (tx, rx) = channel();
321        tx.send("test").unwrap();
322        drop(rx);
323        assert!(tx.send("test").is_err());
324
325        let (tx, _) = channel();
326        let tx2 = tx.clone();
327        tx.close();
328        assert!(tx.send("test").is_err());
329        assert!(tx2.send("test").is_err());
330
331        let err = SendError("test");
332        assert!(format!("{err:?}").contains("SendError"));
333        assert!(format!("{err}").contains("send failed because receiver is gone"));
334        assert_eq!(err.into_inner(), "test");
335    }
336
337    /// STATEMENT: Explicit closure wakes receivers, and closure by dropping the last
338    /// sender is permanent.
339    ///
340    /// HOW:
341    /// - Close from each endpoint and check closed, terminated, and registered-waker state.
342    /// - Drop the last sender, then create one through the receiver and check the channel
343    ///   stays closed and terminated, `send()` fails, and `recv()` returns `None`.
344    #[ntex::test]
345    async fn test_close() {
346        let (tx, rx) = channel::<()>();
347        assert!(!tx.is_closed());
348        assert!(!rx.is_closed());
349        assert!(!rx.is_terminated());
350
351        tx.close();
352        assert!(tx.is_closed());
353        assert!(rx.is_closed());
354        assert!(rx.is_terminated());
355
356        let (tx, rx) = channel::<()>();
357        assert_eq!(lazy(|cx| rx.poll_recv(cx)).await, Poll::Pending);
358        assert!(rx.shared.get_ref().blocked_recv.is_set());
359        rx.close();
360        assert!(tx.is_closed());
361        assert!(!rx.shared.get_ref().blocked_recv.is_set());
362        assert_eq!(lazy(|cx| rx.poll_recv(cx)).await, Poll::Ready(None));
363
364        let (tx, rx) = channel::<()>();
365        drop(tx);
366        assert!(rx.is_closed());
367        assert!(rx.is_terminated());
368        let tx = rx.sender();
369        assert!(tx.is_closed());
370        assert!(rx.is_closed());
371        assert!(rx.is_terminated());
372        assert!(tx.send(()).is_err());
373        assert_eq!(rx.recv().await, None);
374    }
375
376    /// STATEMENT: Sender closure waiters complete when either endpoint closes the channel.
377    ///
378    /// HOW:
379    /// - Register closure waiters before receiver drop, receiver close, and sender close.
380    /// - Verify stored wakers are consumed and closure futures complete for cloned handles too.
381    #[ntex::test]
382    async fn test_poll_closed() {
383        let (tx, rx) = channel::<()>();
384        assert_eq!(lazy(|cx| tx.poll_closed(cx)).await, Poll::Pending);
385        assert!(tx.shared.get_ref().closed.is_set());
386        drop(rx);
387        assert!(!tx.shared.get_ref().closed.is_set());
388        assert_eq!(lazy(|cx| tx.poll_closed(cx)).await, Poll::Ready(()));
389        tx.closed().await;
390
391        let (tx, rx) = channel::<()>();
392        assert_eq!(lazy(|cx| tx.poll_closed(cx)).await, Poll::Pending);
393        rx.close();
394        assert!(!tx.shared.get_ref().closed.is_set());
395        tx.closed().await;
396
397        let (tx, _rx) = channel::<()>();
398        let tx2 = tx.clone();
399        assert_eq!(lazy(|cx| tx2.poll_closed(cx)).await, Poll::Pending);
400        tx.close();
401        assert!(!tx.shared.get_ref().closed.is_set());
402        tx2.closed().await;
403    }
404
405    /// STATEMENT: A receiver and the closure state shared by sender clones each wake
406    /// only the most recently registered task, and a superseded waiter still
407    /// observes the result when polled again.
408    ///
409    /// HOW:
410    /// - Poll `poll_recv` with two distinct counted wakers, then send two messages.
411    /// - Check only the second waker was woken once, and re-polling with the first
412    ///   returns the first message.
413    /// - Poll `poll_closed` on two sender clones with distinct wakers, drop the
414    ///   receiver, and check only the second waker was woken while both polls are ready.
415    #[test]
416    fn single_waiter_wakes_latest_task_only() {
417        use crate::task::hooks::counted_waker;
418
419        let (tx, rx) = channel::<u32>();
420        let (first, first_waker) = counted_waker();
421        let (second, second_waker) = counted_waker();
422        let mut first_cx = Context::from_waker(&first_waker);
423        let mut second_cx = Context::from_waker(&second_waker);
424
425        assert_eq!(rx.poll_recv(&mut first_cx), Poll::Pending);
426        assert_eq!(rx.poll_recv(&mut second_cx), Poll::Pending);
427        tx.send(1).unwrap();
428        tx.send(2).unwrap();
429        assert_eq!((first.get(), second.get()), (0, 1));
430        assert_eq!(rx.poll_recv(&mut first_cx), Poll::Ready(Some(1)));
431
432        let tx2 = tx.clone();
433        let (first, first_waker) = counted_waker();
434        let (second, second_waker) = counted_waker();
435        let mut first_cx = Context::from_waker(&first_waker);
436        let mut second_cx = Context::from_waker(&second_waker);
437
438        assert_eq!(tx.poll_closed(&mut first_cx), Poll::Pending);
439        assert_eq!(tx2.poll_closed(&mut second_cx), Poll::Pending);
440        drop(rx);
441        assert_eq!((first.get(), second.get()), (0, 1));
442        assert_eq!(tx.poll_closed(&mut first_cx), Poll::Ready(()));
443        assert_eq!(tx2.poll_closed(&mut second_cx), Poll::Ready(()));
444    }
445
446    /// STATEMENT: Dropping an MPSC receiver safely rejects reentrant sends from message destructors.
447    ///
448    /// HOW:
449    /// - Queue four values whose destructors attempt another send and count all drops.
450    /// - Drop the receiver and verify eight drops and a closed sender.
451    #[test]
452    fn test_drop_receiver_reentrant_send() {
453        use std::rc::Rc;
454
455        struct Msg(Option<Sender<Msg>>, Rc<std::cell::Cell<usize>>);
456
457        impl Drop for Msg {
458            fn drop(&mut self) {
459                self.1.set(self.1.get() + 1);
460                if let Some(tx) = self.0.take() {
461                    assert!(tx.send(Msg(None, self.1.clone())).is_err());
462                }
463            }
464        }
465
466        let drops = Rc::new(std::cell::Cell::new(0));
467        let (tx, rx) = channel();
468        for _ in 0..4 {
469            tx.send(Msg(Some(tx.clone()), drops.clone())).unwrap();
470        }
471        drop(rx);
472        assert_eq!(drops.get(), 8);
473        assert!(tx.is_closed());
474    }
475
476    /// STATEMENT: A closed MPSC stream is terminated only after its buffered messages are drained.
477    ///
478    /// HOW:
479    /// - Queue values, drop the sender, and check ordered delivery before termination.
480    /// - Repeat with explicit receiver closure and verify the queued value remains readable.
481    #[ntex::test]
482    async fn test_fused_drains_buffer() {
483        let (tx, mut rx) = channel();
484        tx.send(1).unwrap();
485        tx.send(2).unwrap();
486        drop(tx);
487
488        assert!(!rx.is_terminated());
489        assert_eq!(stream_recv(&mut rx).await, Some(1));
490        assert_eq!(stream_recv(&mut rx).await, Some(2));
491        assert!(rx.is_terminated());
492        assert_eq!(stream_recv(&mut rx).await, None);
493
494        let (tx, mut rx) = channel();
495        tx.send(1).unwrap();
496        rx.close();
497        assert!(!rx.is_terminated());
498        assert_eq!(stream_recv(&mut rx).await, Some(1));
499        assert!(rx.is_terminated());
500    }
501
502    /// STATEMENT: Direct MPSC receive returns a sent value and then ends after sender drop.
503    ///
504    /// HOW:
505    /// - Send and receive one value, drop the sender, and verify the next receive returns `None`.
506    #[ntex::test]
507    async fn test_mpsc_recv() {
508        let (tx, rx) = channel();
509        tx.send(1).unwrap();
510        assert_eq!(rx.recv().await, Some(1));
511        drop(tx);
512        assert_eq!(rx.recv().await, None);
513    }
514
515    /// STATEMENT: `poll_recv` returns a message sent by its waker's clone callback instead of missing it.
516    ///
517    /// HOW:
518    /// - Set an `ON_CLONE` hook that sends `1` through a sender clone.
519    /// - Poll the empty receiver with `hook_waker` and check it returns `Ready(Some(1))`.
520    #[test]
521    fn miri_poll_recv_with_reentrant_clone() {
522        let (tx, rx) = channel();
523        let tx2 = tx.clone();
524        ON_CLONE.set(Some(Box::new(move || tx2.send(1).unwrap())));
525
526        let waker = hook_waker();
527        let mut cx = Context::from_waker(&waker);
528        assert_eq!(rx.poll_recv(&mut cx), Poll::Ready(Some(1)));
529        drop(tx);
530    }
531}