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    /// See [`poll_closed`](Self::poll_closed).
104    pub async fn closed(&self) {
105        poll_fn(|cx| self.poll_closed(cx)).await;
106    }
107}
108
109impl<T> Clone for Sender<T> {
110    fn clone(&self) -> Self {
111        Sender {
112            shared: self.shared.clone(),
113        }
114    }
115}
116
117impl<T> Drop for Sender<T> {
118    fn drop(&mut self) {
119        let count = self.shared.strong_count();
120        let waker = {
121            let shared = self.shared.get_mut();
122
123            // check is last sender is about to drop
124            if shared.has_receiver && count == 2 {
125                // Wake up receiver as its stream has ended
126                shared.blocked_recv.take_local()
127            } else {
128                None
129            }
130        };
131        wake(waker);
132    }
133}
134
135/// The receiving end of a channel which implements the `Stream` trait.
136///
137/// This is created by the `channel` function.
138#[derive(Debug)]
139pub struct Receiver<T> {
140    shared: Cell<Shared<T>>,
141}
142
143impl<T> Receiver<T> {
144    /// Creates an additional sender for this channel.
145    pub fn sender(&self) -> Sender<T> {
146        Sender {
147            shared: self.shared.clone(),
148        }
149    }
150
151    /// Closes the receiving half of a channel, without dropping it.
152    ///
153    /// This prevents any further messages from being sent on the channel
154    /// while still enabling the receiver to drain messages that are buffered.
155    pub fn close(&self) {
156        close(&self.shared);
157    }
158
159    /// Returns whether this channel is closed.
160    pub fn is_closed(&self) -> bool {
161        self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
162    }
163
164    /// Waits for the next message.
165    ///
166    /// Returns `None` once the channel is closed or every sender has been
167    /// dropped, and every buffered message has been received.
168    pub async fn recv(&self) -> Option<T> {
169        poll_fn(|cx| self.poll_recv(cx)).await
170    }
171
172    /// Polls for the next message.
173    ///
174    /// Returns `Ready(None)` once the channel is closed or every sender has
175    /// been dropped, and every buffered message has been received.
176    pub fn poll_recv(&self, cx: &mut Context<'_>) -> Poll<Option<T>> {
177        if let Poll::Ready(msg) = self.try_recv() {
178            return Poll::Ready(msg);
179        }
180        LocalWaker::register_in(|| &self.shared.get_ref().blocked_recv, cx.waker());
181
182        // the waker callbacks may have sent a message or closed the channel
183        self.try_recv()
184    }
185
186    fn try_recv(&self) -> Poll<Option<T>> {
187        let shared = self.shared.get_mut();
188        if let Some(msg) = shared.buffer.pop_front() {
189            Poll::Ready(Some(msg))
190        } else if !shared.has_receiver || self.shared.strong_count() == 1 {
191            // The channel is closed or all senders have been dropped, and the
192            // buffer is drained, so end the stream.
193            Poll::Ready(None)
194        } else {
195            Poll::Pending
196        }
197    }
198}
199
200impl<T> Unpin for Receiver<T> {}
201
202impl<T> Stream for Receiver<T> {
203    type Item = T;
204
205    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
206        self.poll_recv(cx)
207    }
208}
209
210impl<T> FusedStream for Receiver<T> {
211    /// Returns `true` once the channel is closed and every buffered message
212    /// has been received.
213    fn is_terminated(&self) -> bool {
214        self.is_closed() && self.shared.get_ref().buffer.is_empty()
215    }
216}
217
218impl<T> UnwindSafe for Receiver<T> {}
219
220impl<T> Drop for Receiver<T> {
221    fn drop(&mut self) {
222        let (buffer, waker) = {
223            let shared = self.shared.get_mut();
224            shared.has_receiver = false;
225            (
226                std::mem::take(&mut shared.buffer),
227                shared.closed.take_local(),
228            )
229        };
230        wake(waker);
231
232        // queued messages may send on this channel from their `Drop`
233        drop(buffer);
234    }
235}
236
237/// Error type for sending, used when the receiving end of a channel is
238/// dropped
239pub struct SendError<T>(T);
240
241impl<T> std::error::Error for SendError<T> {}
242
243impl<T> fmt::Debug for SendError<T> {
244    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
245        fmt.debug_tuple("SendError").field(&"...").finish()
246    }
247}
248
249impl<T> fmt::Display for SendError<T> {
250    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
251        write!(fmt, "send failed because receiver is gone")
252    }
253}
254
255impl<T> SendError<T> {
256    /// Returns the message that was attempted to be sent but failed.
257    pub fn into_inner(self) -> T {
258        self.0
259    }
260}
261
262#[cfg(test)]
263mod tests {
264    use super::*;
265    use crate::task::hooks::{ON_CLONE, hook_waker};
266    use crate::{future::lazy, future::stream_recv};
267
268    /// STATEMENT: MPSC sender clones share delivery and closure state.
269    ///
270    /// HOW:
271    /// - Send from original and cloned handles and verify an empty live channel remains pending.
272    /// - Close or drop endpoints, check failed sends, and recover the value from `SendError`.
273    #[ntex::test]
274    async fn test_mpsc() {
275        let (tx, mut rx) = channel();
276        assert!(format!("{tx:?}").contains("Sender"));
277        assert!(format!("{rx:?}").contains("Receiver"));
278
279        tx.send("test").unwrap();
280        assert_eq!(stream_recv(&mut rx).await.unwrap(), "test");
281
282        let tx2 = tx.clone();
283        tx2.send("test2").unwrap();
284        assert_eq!(stream_recv(&mut rx).await.unwrap(), "test2");
285
286        assert_eq!(
287            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
288            Poll::Pending
289        );
290        drop(tx2);
291        assert_eq!(
292            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
293            Poll::Pending
294        );
295        drop(tx);
296
297        let (tx, mut rx) = channel::<String>();
298        tx.close();
299        assert_eq!(stream_recv(&mut rx).await, None);
300
301        let (tx, rx) = channel();
302        tx.send("test").unwrap();
303        drop(rx);
304        assert!(tx.send("test").is_err());
305
306        let (tx, _) = channel();
307        let tx2 = tx.clone();
308        tx.close();
309        assert!(tx.send("test").is_err());
310        assert!(tx2.send("test").is_err());
311
312        let err = SendError("test");
313        assert!(format!("{err:?}").contains("SendError"));
314        assert!(format!("{err}").contains("send failed because receiver is gone"));
315        assert_eq!(err.into_inner(), "test");
316    }
317
318    /// STATEMENT: Explicit closure wakes receivers, while sender exhaustion can be reversed.
319    ///
320    /// HOW:
321    /// - Close from each endpoint and check closed, terminated, and registered-waker state.
322    /// - Drop the last sender, then create one through the receiver and check the channel reopens.
323    #[ntex::test]
324    async fn test_close() {
325        let (tx, rx) = channel::<()>();
326        assert!(!tx.is_closed());
327        assert!(!rx.is_closed());
328        assert!(!rx.is_terminated());
329
330        tx.close();
331        assert!(tx.is_closed());
332        assert!(rx.is_closed());
333        assert!(rx.is_terminated());
334
335        let (tx, rx) = channel::<()>();
336        assert_eq!(lazy(|cx| rx.poll_recv(cx)).await, Poll::Pending);
337        assert!(rx.shared.get_ref().blocked_recv.is_set());
338        rx.close();
339        assert!(tx.is_closed());
340        assert!(!rx.shared.get_ref().blocked_recv.is_set());
341        assert_eq!(lazy(|cx| rx.poll_recv(cx)).await, Poll::Ready(None));
342
343        let (tx, rx) = channel::<()>();
344        drop(tx);
345        assert!(rx.is_closed());
346        assert!(rx.is_terminated());
347        let _tx = rx.sender();
348        assert!(!rx.is_closed());
349        assert!(!rx.is_terminated());
350    }
351
352    /// STATEMENT: Sender closure waiters complete when either endpoint closes the channel.
353    ///
354    /// HOW:
355    /// - Register closure waiters before receiver drop, receiver close, and sender close.
356    /// - Verify stored wakers are consumed and closure futures complete for cloned handles too.
357    #[ntex::test]
358    async fn test_poll_closed() {
359        let (tx, rx) = channel::<()>();
360        assert_eq!(lazy(|cx| tx.poll_closed(cx)).await, Poll::Pending);
361        assert!(tx.shared.get_ref().closed.is_set());
362        drop(rx);
363        assert!(!tx.shared.get_ref().closed.is_set());
364        assert_eq!(lazy(|cx| tx.poll_closed(cx)).await, Poll::Ready(()));
365        tx.closed().await;
366
367        let (tx, rx) = channel::<()>();
368        assert_eq!(lazy(|cx| tx.poll_closed(cx)).await, Poll::Pending);
369        rx.close();
370        assert!(!tx.shared.get_ref().closed.is_set());
371        tx.closed().await;
372
373        let (tx, _rx) = channel::<()>();
374        let tx2 = tx.clone();
375        assert_eq!(lazy(|cx| tx2.poll_closed(cx)).await, Poll::Pending);
376        tx.close();
377        assert!(!tx.shared.get_ref().closed.is_set());
378        tx2.closed().await;
379    }
380
381    /// STATEMENT: Dropping an MPSC receiver safely rejects reentrant sends from message destructors.
382    ///
383    /// HOW:
384    /// - Queue four values whose destructors attempt another send and count all drops.
385    /// - Drop the receiver and verify eight drops and a closed sender.
386    #[test]
387    fn test_drop_receiver_reentrant_send() {
388        use std::rc::Rc;
389
390        struct Msg(Option<Sender<Msg>>, Rc<std::cell::Cell<usize>>);
391
392        impl Drop for Msg {
393            fn drop(&mut self) {
394                self.1.set(self.1.get() + 1);
395                if let Some(tx) = self.0.take() {
396                    assert!(tx.send(Msg(None, self.1.clone())).is_err());
397                }
398            }
399        }
400
401        let drops = Rc::new(std::cell::Cell::new(0));
402        let (tx, rx) = channel();
403        for _ in 0..4 {
404            tx.send(Msg(Some(tx.clone()), drops.clone())).unwrap();
405        }
406        drop(rx);
407        assert_eq!(drops.get(), 8);
408        assert!(tx.is_closed());
409    }
410
411    /// STATEMENT: A closed MPSC stream is terminated only after its buffered messages are drained.
412    ///
413    /// HOW:
414    /// - Queue values, drop the sender, and check ordered delivery before termination.
415    /// - Repeat with explicit receiver closure and verify the queued value remains readable.
416    #[ntex::test]
417    async fn test_fused_drains_buffer() {
418        let (tx, mut rx) = channel();
419        tx.send(1).unwrap();
420        tx.send(2).unwrap();
421        drop(tx);
422
423        assert!(!rx.is_terminated());
424        assert_eq!(stream_recv(&mut rx).await, Some(1));
425        assert_eq!(stream_recv(&mut rx).await, Some(2));
426        assert!(rx.is_terminated());
427        assert_eq!(stream_recv(&mut rx).await, None);
428
429        let (tx, mut rx) = channel();
430        tx.send(1).unwrap();
431        rx.close();
432        assert!(!rx.is_terminated());
433        assert_eq!(stream_recv(&mut rx).await, Some(1));
434        assert!(rx.is_terminated());
435    }
436
437    /// STATEMENT: Direct MPSC receive returns a sent value and then ends after sender drop.
438    ///
439    /// HOW:
440    /// - Send and receive one value, drop the sender, and verify the next receive returns `None`.
441    #[ntex::test]
442    async fn test_mpsc_recv() {
443        let (tx, rx) = channel();
444        tx.send(1).unwrap();
445        assert_eq!(rx.recv().await, Some(1));
446        drop(tx);
447        assert_eq!(rx.recv().await, None);
448    }
449
450    /// STATEMENT: `poll_recv` returns a message sent by its waker's clone callback instead of missing it.
451    ///
452    /// HOW:
453    /// - Set an `ON_CLONE` hook that sends `1` through a sender clone.
454    /// - Poll the empty receiver with `hook_waker` and check it returns `Ready(Some(1))`.
455    #[test]
456    fn miri_poll_recv_with_reentrant_clone() {
457        let (tx, rx) = channel();
458        let tx2 = tx.clone();
459        ON_CLONE.set(Some(Box::new(move || tx2.send(1).unwrap())));
460
461        let waker = hook_waker();
462        let mut cx = Context::from_waker(&waker);
463        assert_eq!(rx.poll_recv(&mut cx), Poll::Ready(Some(1)));
464        drop(tx);
465    }
466}