1use std::future::{Future, IntoFuture};
10use std::ops::Drop;
11use std::pin::Pin;
12use std::sync::{Arc, Mutex, OnceLock, Weak};
13use std::task::{Context, Poll, Waker, ready};
14
15use slotmap_careful::DenseSlotMap;
16
17slotmap_careful::new_key_type! { struct WakerKey; }
18
19#[derive(Debug)]
21pub struct Sender<T> {
22 shared: Weak<Shared<T>>,
24}
25
26#[derive(Clone, Debug)]
52pub struct Receiver<T> {
53 shared: Arc<Shared<T>>,
55}
56
57#[derive(Debug)]
80struct Shared<T> {
81 msg: OnceLock<Result<T, SenderDropped>>,
83 wakers: Mutex<Result<DenseSlotMap<WakerKey, Waker>, WakersAlreadyWoken>>,
89}
90
91#[derive(Debug)]
96pub struct BorrowedReceiverFuture<'a, T> {
97 shared: &'a Shared<T>,
99 waker_key: Option<WakerKey>,
101}
102
103#[derive(Debug)]
114pub struct ReceiverFuture<T> {
115 shared: Arc<Shared<T>>,
117 waker_key: Option<WakerKey>,
119}
120
121#[derive(Copy, Clone, Debug)]
128struct WakersAlreadyWoken;
129
130#[derive(Copy, Clone, Debug, thiserror::Error)]
132#[error("the message was already set")]
133struct MessageAlreadySet;
134
135#[derive(Copy, Clone, Debug, PartialEq, Eq, thiserror::Error)]
137#[error("the sender was dropped")]
138#[allow(clippy::exhaustive_structs)]
139pub struct SenderDropped;
140
141pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
155 let shared = Arc::new(Shared {
156 msg: OnceLock::new(),
157 wakers: Mutex::new(Ok(DenseSlotMap::with_key())),
158 });
159
160 let sender = Sender {
161 shared: Arc::downgrade(&shared),
162 };
163
164 let receiver = Receiver { shared };
165
166 (sender, receiver)
167}
168
169impl<T> Sender<T> {
170 pub fn send(self, msg: T) {
174 Self::send_and_wake(&self.shared, Ok(msg))
176 .expect("could not set the message");
180 }
181
182 fn send_and_wake(
188 shared: &Weak<Shared<T>>,
189 msg: Result<T, SenderDropped>,
190 ) -> Result<(), MessageAlreadySet> {
191 let Some(shared) = shared.upgrade() else {
196 return Ok(());
198 };
199
200 shared.msg.set(msg).or(Err(MessageAlreadySet))?;
202
203 let mut wakers = {
204 let mut wakers = shared.wakers.lock().expect("poisoned");
205 std::mem::replace(&mut *wakers, Err(WakersAlreadyWoken))
214 .expect("wakers were taken more than once")
215 };
216
217 for (_key, waker) in wakers.drain() {
227 waker.wake();
228 }
229
230 Ok(())
231 }
232
233 pub fn is_cancelled(&self) -> bool {
243 self.shared.strong_count() == 0
244 }
245}
246
247impl<T> Drop for Sender<T> {
248 fn drop(&mut self) {
249 let _ = Self::send_and_wake(&self.shared, Err(SenderDropped));
253 }
254}
255
256impl<T> Receiver<T> {
257 pub fn borrowed(&self) -> BorrowedReceiverFuture<'_, T> {
264 BorrowedReceiverFuture {
265 shared: &self.shared,
266 waker_key: None,
267 }
268 }
269
270 pub fn is_ready(&self) -> bool {
274 self.shared.msg.get().is_some()
275 }
276}
277
278impl<T: Clone> IntoFuture for Receiver<T> {
279 type Output = Result<T, SenderDropped>;
280 type IntoFuture = ReceiverFuture<T>;
281
282 fn into_future(self) -> Self::IntoFuture {
284 ReceiverFuture {
285 shared: self.shared,
286 waker_key: None,
287 }
288 }
289}
290
291impl<'a, T> Future for BorrowedReceiverFuture<'a, T> {
292 type Output = Result<&'a T, SenderDropped>;
293
294 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
295 let self_ = self.get_mut();
296 receiver_fut_poll(self_.shared, &mut self_.waker_key, cx.waker())
297 }
298}
299
300impl<T> Drop for BorrowedReceiverFuture<'_, T> {
301 fn drop(&mut self) {
302 receiver_fut_drop(self.shared, &mut self.waker_key);
303 }
304}
305
306impl<T: Clone> Future for ReceiverFuture<T> {
307 type Output = Result<T, SenderDropped>;
308
309 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
310 let self_ = self.get_mut();
311 let poll = receiver_fut_poll(&self_.shared, &mut self_.waker_key, cx.waker());
312 Poll::Ready(ready!(poll)).map_ok(Clone::clone)
313 }
314}
315
316impl<T> Drop for ReceiverFuture<T> {
317 fn drop(&mut self) {
318 receiver_fut_drop(&self.shared, &mut self.waker_key);
319 }
320}
321
322fn receiver_fut_poll<'a, T>(
324 shared: &'a Shared<T>,
325 waker_key: &mut Option<WakerKey>,
326 new_waker: &Waker,
327) -> Poll<Result<&'a T, SenderDropped>> {
328 if let Some(msg) = shared.msg.get() {
330 return Poll::Ready(msg.as_ref().or(Err(SenderDropped)));
331 }
332
333 let mut wakers = shared.wakers.lock().expect("poisoned");
334
335 if let Some(msg) = shared.msg.get() {
337 return Poll::Ready(msg.as_ref().or(Err(SenderDropped)));
338 }
339
340 let wakers = wakers.as_mut().expect("wakers were already woken");
344
345 match waker_key {
346 Some(waker_key) => {
348 let waker = wakers
350 .get_mut(*waker_key)
351 .expect("waker key is missing from map");
354 waker.clone_from(new_waker);
355 }
356 None => {
358 let new_key = wakers.insert(new_waker.clone());
360 *waker_key = Some(new_key);
361 }
362 }
363
364 Poll::Pending
365}
366
367fn receiver_fut_drop<T>(shared: &Shared<T>, waker_key: &mut Option<WakerKey>) {
369 if let Some(waker_key) = waker_key.take() {
370 let mut wakers = shared.wakers.lock().expect("poisoned");
371 if let Ok(wakers) = wakers.as_mut() {
372 let waker = wakers.remove(waker_key);
373 debug_assert!(waker.is_some(), "the waker key was not found");
376 }
377 }
378}
379
380#[cfg(test)]
381mod test {
382 #![allow(clippy::unwrap_used)]
383
384 use super::*;
385
386 use futures::future::FutureExt;
387 use tor_rtcompat::SpawnExt;
388
389 impl<T> Shared<T> {
390 fn count_wakers(&self) -> usize {
392 self.wakers
393 .lock()
394 .expect("poisoned")
395 .as_ref()
396 .map(|x| x.len())
397 .unwrap_or(0)
398 }
399 }
400
401 #[test]
402 fn standard_usage() {
403 tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
404 let (tx, rx) = channel();
405 tx.send(0_u8);
406 assert_eq!(rx.borrowed().await, Ok(&0));
407
408 let (tx, rx) = channel();
409 tx.send(0_u8);
410 assert_eq!(rx.await, Ok(0));
411 });
412 }
413
414 #[test]
415 fn immediate_drop() {
416 let _ = channel::<()>();
417
418 let (tx, rx) = channel::<()>();
419 drop(tx);
420 drop(rx);
421
422 let (tx, rx) = channel::<()>();
423 drop(rx);
424 drop(tx);
425 }
426
427 #[test]
428 fn drop_sender() {
429 tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
430 let (tx, rx_1) = channel::<u8>();
431
432 let rx_2 = rx_1.clone();
433 drop(tx);
434 let rx_3 = rx_1.clone();
435 assert_eq!(rx_1.borrowed().await, Err(SenderDropped));
436 assert_eq!(rx_2.borrowed().await, Err(SenderDropped));
437 assert_eq!(rx_3.borrowed().await, Err(SenderDropped));
438 });
439 }
440
441 #[test]
442 fn clone_before_send() {
443 tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
444 let (tx, rx_1) = channel();
445
446 let rx_2 = rx_1.clone();
447 tx.send(0_u8);
448 assert_eq!(rx_1.borrowed().await, Ok(&0));
449 assert_eq!(rx_2.borrowed().await, Ok(&0));
450 });
451 }
452
453 #[test]
454 fn clone_after_send() {
455 tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
456 let (tx, rx_1) = channel();
457
458 tx.send(0_u8);
459 let rx_2 = rx_1.clone();
460 assert_eq!(rx_1.borrowed().await, Ok(&0));
461 assert_eq!(rx_2.borrowed().await, Ok(&0));
462 });
463 }
464
465 #[test]
466 fn clone_after_borrowed() {
467 tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
468 let (tx, rx_1) = channel();
469
470 tx.send(0_u8);
471 assert_eq!(rx_1.borrowed().await, Ok(&0));
472 let rx_2 = rx_1.clone();
473 assert_eq!(rx_2.borrowed().await, Ok(&0));
474 });
475 }
476
477 #[test]
478 fn drop_one_receiver() {
479 tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
480 let (tx, rx_1) = channel();
481
482 let rx_2 = rx_1.clone();
483 drop(rx_1);
484 tx.send(0_u8);
485 assert_eq!(rx_2.borrowed().await, Ok(&0));
486 });
487 }
488
489 #[test]
490 fn drop_all_receivers() {
491 let (tx, rx_1) = channel();
492
493 let rx_2 = rx_1.clone();
494 drop(rx_1);
495 drop(rx_2);
496 tx.send(0_u8);
497 }
498
499 #[test]
500 fn drop_fut() {
501 let (_tx, rx) = channel::<u8>();
502 let fut = rx.borrowed();
503 assert_eq!(rx.shared.count_wakers(), 0);
504 drop(fut);
505 assert_eq!(rx.shared.count_wakers(), 0);
506
507 let (tx, rx) = channel();
509 tx.send(0_u8);
510 let fut = rx.borrowed();
511 assert_eq!(rx.shared.count_wakers(), 0);
512 drop(fut);
513 assert_eq!(rx.shared.count_wakers(), 0);
514
515 let (_tx, rx) = channel::<u8>();
517 let mut fut = Box::pin(rx.borrowed());
518 assert_eq!(rx.shared.count_wakers(), 0);
519 assert_eq!(fut.as_mut().now_or_never(), None);
520 assert_eq!(rx.shared.count_wakers(), 1);
521 drop(fut);
522 assert_eq!(rx.shared.count_wakers(), 0);
523
524 let (tx, rx) = channel();
526 let mut fut = Box::pin(rx.borrowed());
527 assert_eq!(rx.shared.count_wakers(), 0);
528 assert_eq!(fut.as_mut().now_or_never(), None);
529 assert_eq!(rx.shared.count_wakers(), 1);
530 tx.send(0_u8);
531 assert_eq!(rx.shared.count_wakers(), 0);
532 drop(fut);
533 }
534
535 #[test]
536 fn drop_owned_fut() {
537 let (_tx, rx) = channel::<u8>();
538 let fut = rx.clone().into_future();
539 assert_eq!(rx.shared.count_wakers(), 0);
540 drop(fut);
541 assert_eq!(rx.shared.count_wakers(), 0);
542
543 let (tx, rx) = channel();
545 tx.send(0_u8);
546 let fut = rx.clone().into_future();
547 assert_eq!(rx.shared.count_wakers(), 0);
548 drop(fut);
549 assert_eq!(rx.shared.count_wakers(), 0);
550
551 let (_tx, rx) = channel::<u8>();
553 let mut fut = Box::pin(rx.clone().into_future());
554 assert_eq!(rx.shared.count_wakers(), 0);
555 assert_eq!(fut.as_mut().now_or_never(), None);
556 assert_eq!(rx.shared.count_wakers(), 1);
557 drop(fut);
558 assert_eq!(rx.shared.count_wakers(), 0);
559
560 let (tx, rx) = channel();
562 let mut fut = Box::pin(rx.clone().into_future());
563 assert_eq!(rx.shared.count_wakers(), 0);
564 assert_eq!(fut.as_mut().now_or_never(), None);
565 assert_eq!(rx.shared.count_wakers(), 1);
566 tx.send(0_u8);
567 assert_eq!(rx.shared.count_wakers(), 0);
568 drop(fut);
569 }
570
571 #[test]
572 fn is_ready_after_send() {
573 let (tx, rx_1) = channel();
574 assert!(!rx_1.is_ready());
575 let rx_2 = rx_1.clone();
576 assert!(!rx_2.is_ready());
577
578 tx.send(0_u8);
579
580 assert!(rx_1.is_ready());
581 assert!(rx_2.is_ready());
582
583 let rx_3 = rx_1.clone();
584 assert!(rx_3.is_ready());
585 }
586
587 #[test]
588 fn is_ready_after_drop() {
589 let (tx, rx_1) = channel::<u8>();
590 assert!(!rx_1.is_ready());
591 let rx_2 = rx_1.clone();
592 assert!(!rx_2.is_ready());
593
594 drop(tx);
595
596 assert!(rx_1.is_ready());
597 assert!(rx_2.is_ready());
598
599 let rx_3 = rx_1.clone();
600 assert!(rx_3.is_ready());
601 }
602
603 #[test]
604 fn is_cancelled() {
605 let (tx, rx) = channel::<u8>();
606 assert!(!tx.is_cancelled());
607 drop(rx);
608 assert!(tx.is_cancelled());
609
610 let (tx, rx_1) = channel::<u8>();
611 assert!(!tx.is_cancelled());
612 let rx_2 = rx_1.clone();
613 drop(rx_1);
614 assert!(!tx.is_cancelled());
615 drop(rx_2);
616 assert!(tx.is_cancelled());
617 }
618
619 #[test]
620 fn recv_in_task() {
621 tor_rtmock::MockRuntime::test_with_various(|rt| async move {
622 let (tx, rx) = channel();
623
624 let join = rt
625 .spawn_with_handle(async move {
626 assert_eq!(rx.borrowed().await, Ok(&0));
627 assert_eq!(rx.await, Ok(0));
628 })
629 .unwrap();
630
631 tx.send(0_u8);
632
633 join.await;
634 });
635 }
636
637 #[test]
638 fn recv_multiple_in_task() {
639 tor_rtmock::MockRuntime::test_with_various(|rt| async move {
640 let (tx, rx) = channel();
641 let rx_1 = rx.clone();
642 let rx_2 = rx.clone();
643
644 let join_1 = rt
645 .spawn_with_handle(async move {
646 assert_eq!(rx_1.borrowed().await, Ok(&0));
647 })
648 .unwrap();
649 let join_2 = rt
650 .spawn_with_handle(async move {
651 assert_eq!(rx_2.await, Ok(0));
652 })
653 .unwrap();
654
655 tx.send(0_u8);
656
657 join_1.await;
658 join_2.await;
659 assert_eq!(rx.borrowed().await, Ok(&0));
660 });
661 }
662
663 #[test]
664 fn recv_multiple_times() {
665 tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
666 let (tx, rx) = channel();
667
668 tx.send(0_u8);
669 assert_eq!(rx.borrowed().await, Ok(&0));
670 assert_eq!(rx.borrowed().await, Ok(&0));
671 assert_eq!(rx.clone().await, Ok(0));
672 assert_eq!(rx.await, Ok(0));
673 });
674 }
675
676 #[test]
677 fn stress() {
678 tor_rtmock::MockRuntime::test_with_various(|rt| async move {
692 let (tx, rx) = channel();
693
694 rt.spawn(async move {
695 for _ in 0..20 {
698 tor_rtcompat::task::yield_now().await;
699 }
700 tx.send(0_u8);
701 })
702 .unwrap();
703
704 let mut joins = vec![];
705 for _ in 0..100 {
706 let rx_clone = rx.clone();
707 let join = rt
708 .spawn_with_handle(async move { rx_clone.borrowed().await.cloned() })
709 .unwrap();
710 joins.push(join);
711 tor_rtcompat::task::yield_now().await;
713 }
714
715 for join in joins {
716 assert!(matches!(join.await, Ok(0)));
717 }
718 });
719 }
720}