ntex_util/channel/
mpsc.rs1use 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
11pub 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#[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 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)); }
49 shared.buffer.push_back(item);
50 shared.blocked_recv.wake();
51 Ok(())
52 }
53
54 pub fn close(&self) {
60 let shared = self.shared.get_mut();
61 shared.has_receiver = false;
62 shared.blocked_recv.wake();
63 }
64
65 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 if shared.has_receiver && count == 2 {
86 shared.blocked_recv.wake();
88 }
89 }
90}
91
92#[derive(Debug)]
96pub struct Receiver<T> {
97 shared: Cell<Shared<T>>,
98}
99
100impl<T> Receiver<T> {
101 pub fn sender(&self) -> Sender<T> {
103 Sender {
104 shared: self.shared.clone(),
105 }
106 }
107
108 pub fn close(&self) {
113 let shared = self.shared.get_mut();
114 shared.has_receiver = false;
115 shared.blocked_recv.wake();
116 }
117
118 pub fn is_closed(&self) -> bool {
120 self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
121 }
122
123 pub async fn recv(&self) -> Option<T> {
128 poll_fn(|cx| self.poll_recv(cx)).await
129 }
130
131 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 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
181pub 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 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}