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;
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    });
18    let sender = Sender {
19        shared: shared.clone(),
20    };
21    let receiver = Receiver { shared };
22    (sender, receiver)
23}
24
25#[derive(Debug)]
26struct Shared<T> {
27    buffer: VecDeque<T>,
28    blocked_recv: LocalWaker,
29    has_receiver: bool,
30}
31
32/// The transmission end of a channel.
33///
34/// This is created by the `channel` function.
35#[derive(Debug)]
36pub struct Sender<T> {
37    shared: Cell<Shared<T>>,
38}
39
40impl<T> Unpin for Sender<T> {}
41
42impl<T> Sender<T> {
43    /// Sends the provided message along this channel.
44    pub fn send(&self, item: T) -> Result<(), SendError<T>> {
45        let shared = self.shared.get_mut();
46        if !shared.has_receiver {
47            return Err(SendError(item)); // receiver was dropped
48        }
49        shared.buffer.push_back(item);
50        shared.blocked_recv.wake();
51        Ok(())
52    }
53
54    /// Closes the channel for every sender.
55    ///
56    /// This prevents any further messages from being sent on the channel, by
57    /// this sender or any of its clones, while still enabling the receiver to
58    /// drain messages that are buffered.
59    pub fn close(&self) {
60        let shared = self.shared.get_mut();
61        shared.has_receiver = false;
62        shared.blocked_recv.wake();
63    }
64
65    /// Returns `true` if the channel is closed or the receiver has been dropped.
66    pub fn is_closed(&self) -> bool {
67        self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
68    }
69}
70
71impl<T> Clone for Sender<T> {
72    fn clone(&self) -> Self {
73        Sender {
74            shared: self.shared.clone(),
75        }
76    }
77}
78
79impl<T> Drop for Sender<T> {
80    fn drop(&mut self) {
81        let count = self.shared.strong_count();
82        let shared = self.shared.get_mut();
83
84        // check is last sender is about to drop
85        if shared.has_receiver && count == 2 {
86            // Wake up receiver as its stream has ended
87            shared.blocked_recv.wake();
88        }
89    }
90}
91
92/// The receiving end of a channel which implements the `Stream` trait.
93///
94/// This is created by the `channel` function.
95#[derive(Debug)]
96pub struct Receiver<T> {
97    shared: Cell<Shared<T>>,
98}
99
100impl<T> Receiver<T> {
101    /// Creates an additional sender for this channel.
102    pub fn sender(&self) -> Sender<T> {
103        Sender {
104            shared: self.shared.clone(),
105        }
106    }
107
108    /// Closes the receiving half of a channel, without dropping it.
109    ///
110    /// This prevents any further messages from being sent on the channel
111    /// while still enabling the receiver to drain messages that are buffered.
112    pub fn close(&self) {
113        let shared = self.shared.get_mut();
114        shared.has_receiver = false;
115        shared.blocked_recv.wake();
116    }
117
118    /// Returns whether this channel is closed.
119    pub fn is_closed(&self) -> bool {
120        self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
121    }
122
123    /// Waits for the next message.
124    ///
125    /// Returns `None` once the channel is closed or every sender has been
126    /// dropped, and every buffered message has been received.
127    pub async fn recv(&self) -> Option<T> {
128        poll_fn(|cx| self.poll_recv(cx)).await
129    }
130
131    /// Polls for the next message.
132    ///
133    /// Returns `Ready(None)` once the channel is closed or every sender has
134    /// been dropped, and every buffered message has been received.
135    pub fn poll_recv(&self, cx: &mut Context<'_>) -> Poll<Option<T>> {
136        let shared = self.shared.get_mut();
137
138        if let Some(msg) = shared.buffer.pop_front() {
139            Poll::Ready(Some(msg))
140        } else if shared.has_receiver {
141            shared.blocked_recv.register(cx.waker());
142            if self.shared.strong_count() == 1 {
143                // All senders have been dropped, so drain the buffer and end the
144                // stream.
145                Poll::Ready(None)
146            } else {
147                Poll::Pending
148            }
149        } else {
150            Poll::Ready(None)
151        }
152    }
153}
154
155impl<T> Unpin for Receiver<T> {}
156
157impl<T> Stream for Receiver<T> {
158    type Item = T;
159
160    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
161        self.poll_recv(cx)
162    }
163}
164
165impl<T> FusedStream for Receiver<T> {
166    fn is_terminated(&self) -> bool {
167        self.is_closed()
168    }
169}
170
171impl<T> UnwindSafe for Receiver<T> {}
172
173impl<T> Drop for Receiver<T> {
174    fn drop(&mut self) {
175        let shared = self.shared.get_mut();
176        shared.buffer.clear();
177        shared.has_receiver = false;
178    }
179}
180
181/// Error type for sending, used when the receiving end of a channel is
182/// dropped
183pub struct SendError<T>(T);
184
185impl<T> std::error::Error for SendError<T> {}
186
187impl<T> fmt::Debug for SendError<T> {
188    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
189        fmt.debug_tuple("SendError").field(&"...").finish()
190    }
191}
192
193impl<T> fmt::Display for SendError<T> {
194    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
195        write!(fmt, "send failed because receiver is gone")
196    }
197}
198
199impl<T> SendError<T> {
200    /// Returns the message that was attempted to be sent but failed.
201    pub fn into_inner(self) -> T {
202        self.0
203    }
204}
205
206#[cfg(test)]
207mod tests {
208    use super::*;
209    use crate::{future::lazy, future::stream_recv};
210
211    #[ntex::test]
212    async fn test_mpsc() {
213        let (tx, mut rx) = channel();
214        assert!(format!("{tx:?}").contains("Sender"));
215        assert!(format!("{rx:?}").contains("Receiver"));
216
217        tx.send("test").unwrap();
218        assert_eq!(stream_recv(&mut rx).await.unwrap(), "test");
219
220        let tx2 = tx.clone();
221        tx2.send("test2").unwrap();
222        assert_eq!(stream_recv(&mut rx).await.unwrap(), "test2");
223
224        assert_eq!(
225            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
226            Poll::Pending
227        );
228        drop(tx2);
229        assert_eq!(
230            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
231            Poll::Pending
232        );
233        drop(tx);
234
235        let (tx, mut rx) = channel::<String>();
236        tx.close();
237        assert_eq!(stream_recv(&mut rx).await, None);
238
239        let (tx, rx) = channel();
240        tx.send("test").unwrap();
241        drop(rx);
242        assert!(tx.send("test").is_err());
243
244        let (tx, _) = channel();
245        let tx2 = tx.clone();
246        tx.close();
247        assert!(tx.send("test").is_err());
248        assert!(tx2.send("test").is_err());
249
250        let err = SendError("test");
251        assert!(format!("{err:?}").contains("SendError"));
252        assert!(format!("{err}").contains("send failed because receiver is gone"));
253        assert_eq!(err.into_inner(), "test");
254    }
255
256    #[ntex::test]
257    async fn test_close() {
258        let (tx, rx) = channel::<()>();
259        assert!(!tx.is_closed());
260        assert!(!rx.is_closed());
261        assert!(!rx.is_terminated());
262
263        tx.close();
264        assert!(tx.is_closed());
265        assert!(rx.is_closed());
266        assert!(rx.is_terminated());
267
268        let (tx, rx) = channel::<()>();
269        assert_eq!(lazy(|cx| rx.poll_recv(cx)).await, Poll::Pending);
270        assert!(rx.shared.get_ref().blocked_recv.is_set());
271        rx.close();
272        assert!(tx.is_closed());
273        assert!(!rx.shared.get_ref().blocked_recv.is_set());
274        assert_eq!(lazy(|cx| rx.poll_recv(cx)).await, Poll::Ready(None));
275
276        let (tx, rx) = channel::<()>();
277        drop(tx);
278        assert!(rx.is_closed());
279        assert!(rx.is_terminated());
280        let _tx = rx.sender();
281        assert!(!rx.is_closed());
282        assert!(!rx.is_terminated());
283    }
284}