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, wake};
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 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#[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 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)); }
62 shared.buffer.push_back(item);
63 shared.blocked_recv.take_local()
64 };
65 wake(waker);
66 Ok(())
67 }
68
69 pub fn close(&self) {
75 close(&self.shared);
76 }
77
78 pub fn is_closed(&self) -> bool {
80 self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
81 }
82
83 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 if self.shared.get_ref().has_receiver {
95 Poll::Pending
96 } else {
97 Poll::Ready(())
98 }
99 }
100
101 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 if shared.has_receiver && count == 2 {
125 shared.blocked_recv.take_local()
127 } else {
128 None
129 }
130 };
131 wake(waker);
132 }
133}
134
135#[derive(Debug)]
139pub struct Receiver<T> {
140 shared: Cell<Shared<T>>,
141}
142
143impl<T> Receiver<T> {
144 pub fn sender(&self) -> Sender<T> {
146 Sender {
147 shared: self.shared.clone(),
148 }
149 }
150
151 pub fn close(&self) {
156 close(&self.shared);
157 }
158
159 pub fn is_closed(&self) -> bool {
161 self.shared.strong_count() == 1 || !self.shared.get_ref().has_receiver
162 }
163
164 pub async fn recv(&self) -> Option<T> {
169 poll_fn(|cx| self.poll_recv(cx)).await
170 }
171
172 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 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 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 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 drop(buffer);
234 }
235}
236
237pub 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 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}