1use crate::{Feedback, Unreliable};
44use commonware_runtime::{
45 Metrics,
46 telemetry::metrics::{Counter, MetricsExt as _},
47};
48use std::{
49 collections::VecDeque,
50 fmt,
51 future::poll_fn,
52 marker::PhantomData,
53 num::NonZeroUsize,
54 sync::mpsc::TryRecvError,
55 task::{Context, Poll},
56};
57
58pub trait Overflow<T>: Default {
60 fn is_empty(&self) -> bool;
62
63 fn drain<F>(&mut self, push: F)
69 where
70 F: FnMut(T) -> Option<T>;
71}
72
73impl<T> Overflow<T> for VecDeque<T> {
74 fn is_empty(&self) -> bool {
75 self.is_empty()
76 }
77
78 fn drain<F>(&mut self, mut push: F)
79 where
80 F: FnMut(T) -> Option<T>,
81 {
82 while let Some(message) = self.pop_front() {
83 if let Some(message) = push(message) {
84 self.push_front(message);
85 break;
86 }
87 }
88 }
89}
90
91pub trait Policy: Sized {
93 type Overflow: Overflow<Self>;
95
96 fn handle(overflow: &mut Self::Overflow, message: Self);
112}
113
114pub trait UnreliablePolicy: Sized {
116 type Overflow: Overflow<Self>;
118
119 fn handle(overflow: &mut Self::Overflow, message: Self) -> bool;
140}
141
142mod mode {
144 pub(super) struct Reliable;
146
147 pub(super) struct Unreliable;
149}
150
151trait Mode<T>: Sized {
152 type Overflow: Overflow<T>;
154 type Feedback;
156
157 fn handle(overflow: &mut Self::Overflow, message: T) -> bool;
159 fn ready_feedback(feedback: Feedback) -> Self::Feedback;
161 fn overflow_feedback(handled: bool) -> Self::Feedback;
163 fn is_backoff(feedback: &Self::Feedback) -> bool;
165 fn is_closed(feedback: &Self::Feedback) -> bool;
167}
168
169impl<T: Policy> Mode<T> for mode::Reliable {
170 type Overflow = T::Overflow;
171 type Feedback = Feedback;
172
173 fn handle(overflow: &mut Self::Overflow, message: T) -> bool {
174 T::handle(overflow, message);
175 true
176 }
177
178 fn ready_feedback(feedback: Feedback) -> Self::Feedback {
179 feedback
180 }
181
182 fn overflow_feedback(_handled: bool) -> Self::Feedback {
183 Feedback::Backoff
184 }
185
186 fn is_backoff(feedback: &Self::Feedback) -> bool {
187 *feedback == Feedback::Backoff
188 }
189
190 fn is_closed(feedback: &Self::Feedback) -> bool {
191 *feedback == Feedback::Closed
192 }
193}
194
195impl<T: UnreliablePolicy> Mode<T> for mode::Unreliable {
196 type Overflow = T::Overflow;
197 type Feedback = Unreliable<Feedback>;
198
199 fn handle(overflow: &mut Self::Overflow, message: T) -> bool {
200 T::handle(overflow, message)
201 }
202
203 fn ready_feedback(feedback: Feedback) -> Self::Feedback {
204 Unreliable::new(feedback)
205 }
206
207 fn overflow_feedback(handled: bool) -> Self::Feedback {
208 if handled {
209 Unreliable::new(Feedback::Backoff)
210 } else {
211 Unreliable::Rejected
212 }
213 }
214
215 fn is_backoff(feedback: &Self::Feedback) -> bool {
216 *feedback == Unreliable::new(Feedback::Backoff)
217 }
218
219 fn is_closed(feedback: &Self::Feedback) -> bool {
220 *feedback == Unreliable::new(Feedback::Closed)
221 }
222}
223
224pub struct Sender<T: Policy> {
226 state: Arc<State<T, mode::Reliable>>,
227}
228
229pub struct UnreliableSender<T: UnreliablePolicy> {
231 state: Arc<State<T, mode::Unreliable>>,
232}
233
234impl<T: Policy> Clone for Sender<T> {
235 fn clone(&self) -> Self {
236 Self {
237 state: clone_sender_state(&self.state),
238 }
239 }
240}
241
242impl<T: UnreliablePolicy> Clone for UnreliableSender<T> {
243 fn clone(&self) -> Self {
244 Self {
245 state: clone_sender_state(&self.state),
246 }
247 }
248}
249
250impl<T: Policy> Drop for Sender<T> {
251 fn drop(&mut self) {
252 drop_sender_state(&self.state);
253 }
254}
255
256impl<T: UnreliablePolicy> Drop for UnreliableSender<T> {
257 fn drop(&mut self) {
258 drop_sender_state(&self.state);
259 }
260}
261
262impl<T: Policy> fmt::Debug for Sender<T> {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 fmt_sender_state("Sender", &self.state, f)
265 }
266}
267
268impl<T: UnreliablePolicy> fmt::Debug for UnreliableSender<T> {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 fmt_sender_state("UnreliableSender", &self.state, f)
271 }
272}
273
274impl<T: Policy> Sender<T> {
275 #[must_use = "caller must handle enqueue feedback"]
277 pub fn enqueue(&self, message: T) -> Feedback {
278 self.state.enqueue(message)
279 }
280}
281
282impl<T: UnreliablePolicy> UnreliableSender<T> {
283 #[must_use = "caller must handle enqueue feedback"]
285 pub fn enqueue(&self, message: T) -> Unreliable<Feedback> {
286 self.state.enqueue(message)
287 }
288}
289
290pub struct Receiver<T: Policy> {
297 state: Arc<State<T, mode::Reliable>>,
298}
299
300pub struct UnreliableReceiver<T: UnreliablePolicy> {
307 state: Arc<State<T, mode::Unreliable>>,
308}
309
310impl<T: Policy> Receiver<T> {
311 pub async fn recv(&mut self) -> Option<T> {
316 recv_from(&self.state).await
317 }
318
319 pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
324 try_recv_from(&self.state)
325 }
326}
327
328impl<T: UnreliablePolicy> UnreliableReceiver<T> {
329 pub async fn recv(&mut self) -> Option<T> {
334 recv_from(&self.state).await
335 }
336
337 pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
342 try_recv_from(&self.state)
343 }
344}
345
346impl<T: Policy> Drop for Receiver<T> {
347 fn drop(&mut self) {
348 self.state.close();
349 }
350}
351
352impl<T: UnreliablePolicy> Drop for UnreliableReceiver<T> {
353 fn drop(&mut self) {
354 self.state.close();
355 }
356}
357
358pub fn new<T: Policy>(metrics: impl Metrics, capacity: NonZeroUsize) -> (Sender<T>, Receiver<T>) {
360 let state = new_state(metrics, capacity);
361 (
362 Sender {
363 state: state.clone(),
364 },
365 Receiver { state },
366 )
367}
368
369pub fn new_unreliable<T: UnreliablePolicy>(
371 metrics: impl Metrics,
372 capacity: NonZeroUsize,
373) -> (UnreliableSender<T>, UnreliableReceiver<T>) {
374 let state = new_state(metrics, capacity);
375 (
376 UnreliableSender {
377 state: state.clone(),
378 },
379 UnreliableReceiver { state },
380 )
381}
382
383const OVERFLOW_HAS_MESSAGES: usize = 1;
409const OVERFLOW_MUTATION: usize = 2;
410
411cfg_if::cfg_if! {
412 if #[cfg(feature = "loom")] {
413 use loom::{
414 future::AtomicWaker,
415 sync::{
416 Arc, Mutex, MutexGuard,
417 atomic::{AtomicBool, AtomicUsize, Ordering},
418 },
419 };
420
421 fn register_waker(waker: &AtomicWaker, task: &std::task::Waker) {
422 waker.register_by_ref(task);
423 }
424
425 fn lock<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
426 mutex.lock().unwrap()
427 }
428
429 struct ReadyState<T> {
430 published: VecDeque<T>,
431 reserved: usize,
432 }
433
434 struct Ready<T> {
435 state: Mutex<ReadyState<T>>,
436 capacity: usize,
437 }
438
439 impl<T> Ready<T> {
440 fn new(capacity: usize) -> Self {
441 Self {
442 state: Mutex::new(ReadyState {
443 published: VecDeque::new(),
444 reserved: 0,
445 }),
446 capacity,
447 }
448 }
449
450 const fn capacity(&self) -> usize {
451 self.capacity
452 }
453
454 fn push(&self, message: T) -> Result<(), T> {
455 {
456 let mut state = lock(&self.state);
457 if state.published.len() + state.reserved >= self.capacity {
458 return Err(message);
459 }
460 state.reserved += 1;
461 }
462
463 loom::thread::yield_now();
464
465 let mut state = lock(&self.state);
466 state.reserved -= 1;
467 state.published.push_back(message);
468 Ok(())
469 }
470
471 fn pop(&self) -> Option<T> {
472 loop {
473 let mut state = lock(&self.state);
474 if let Some(message) = state.published.pop_front() {
475 return Some(message);
476 }
477 if state.reserved == 0 {
478 return None;
479 }
480 drop(state);
481 loom::thread::yield_now();
482 }
483 }
484 }
485 } else {
486 use crossbeam_queue::ArrayQueue;
487 use futures_util::task::AtomicWaker;
488 use parking_lot::{Mutex, MutexGuard};
489 use std::sync::{
490 Arc,
491 atomic::{AtomicBool, AtomicUsize, Ordering},
492 };
493
494 fn register_waker(waker: &AtomicWaker, task: &std::task::Waker) {
495 waker.register(task);
496 }
497
498 fn lock<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
499 mutex.lock()
500 }
501
502 struct Ready<T> {
503 queue: ArrayQueue<T>,
504 }
505
506 impl<T> Ready<T> {
507 fn new(capacity: usize) -> Self {
508 Self {
509 queue: ArrayQueue::new(capacity),
510 }
511 }
512
513 fn capacity(&self) -> usize {
514 self.queue.capacity()
515 }
516
517 fn push(&self, message: T) -> Result<(), T> {
518 self.queue.push(message)
519 }
520
521 fn pop(&self) -> Option<T> {
522 self.queue.pop()
523 }
524 }
525 }
526}
527
528struct OverflowState<T, M: Mode<T>> {
529 queue: Mutex<M::Overflow>,
530 activity: AtomicUsize,
531 _phantom: PhantomData<fn() -> T>,
532}
533
534impl<T, M: Mode<T>> OverflowState<T, M> {
535 fn new() -> Self {
536 Self {
537 queue: Mutex::new(M::Overflow::default()),
538 activity: AtomicUsize::new(0),
539 _phantom: PhantomData,
540 }
541 }
542
543 fn try_ready(&self, ready: &Ready<T>, message: T) -> Result<(), T> {
544 if self.activity.load(Ordering::Relaxed) != 0 {
546 return Err(message);
547 }
548 ready.push(message)
549 }
550
551 fn enqueue_overflow(
552 &self,
553 ready: &Ready<T>,
554 message: T,
555 is_closed: impl Fn() -> bool,
556 ) -> M::Feedback {
557 let mutation = Mutation::begin(&self.activity);
559 let mut queue = lock(&self.queue);
560 if is_closed() {
561 mutation.publish(queue.is_empty());
562 return M::ready_feedback(Feedback::Closed);
563 }
564
565 let message = if queue.is_empty() {
569 match ready.push(message) {
570 Ok(()) => {
571 mutation.publish(queue.is_empty());
572 return M::ready_feedback(Feedback::Ok);
573 }
574 Err(message) => message,
575 }
576 } else {
577 message
578 };
579
580 let handled = M::handle(&mut queue, message);
582 mutation.publish(queue.is_empty());
583 M::overflow_feedback(handled)
584 }
585
586 fn refill(&self, ready: &Ready<T>) {
587 if self.activity.load(Ordering::Relaxed) & OVERFLOW_HAS_MESSAGES == 0 {
589 return;
590 }
591
592 let mutation = Mutation::begin(&self.activity);
593 let mut queue = lock(&self.queue);
594 queue.drain(|message| ready.push(message).err());
595 mutation.publish(queue.is_empty());
596 }
597
598 fn drain(&self, ready: &Ready<T>) {
599 let mutation = Mutation::begin(&self.activity);
601 while ready.pop().is_some() {}
602
603 let mut drained = Vec::new();
606 let mut queue = lock(&self.queue);
607 queue.drain(|message| {
608 drained.push(message);
609 None
610 });
611 mutation.publish(queue.is_empty());
612 drop(queue);
613 drop(drained);
614
615 while ready.pop().is_some() {}
618 }
619}
620
621struct Mutation<'a> {
622 activity: &'a AtomicUsize,
623}
624
625impl<'a> Mutation<'a> {
626 fn begin(activity: &'a AtomicUsize) -> Self {
627 activity.fetch_add(OVERFLOW_MUTATION, Ordering::Relaxed);
628 Self { activity }
629 }
630
631 fn publish(&self, is_empty: bool) {
632 if is_empty {
633 self.activity
634 .fetch_and(!OVERFLOW_HAS_MESSAGES, Ordering::Relaxed);
635 } else {
636 self.activity
637 .fetch_or(OVERFLOW_HAS_MESSAGES, Ordering::Relaxed);
638 }
639 }
640}
641
642impl Drop for Mutation<'_> {
643 fn drop(&mut self) {
644 let previous = self
645 .activity
646 .fetch_sub(OVERFLOW_MUTATION, Ordering::Relaxed);
647 assert!(previous >= OVERFLOW_MUTATION);
648 }
649}
650
651struct State<T, M: Mode<T>> {
652 ready: Ready<T>,
653 overflow: OverflowState<T, M>,
654 backoff: Counter,
655 closed: AtomicBool,
656 senders: AtomicUsize,
657 waker: AtomicWaker,
658}
659
660impl<T, M: Mode<T>> State<T, M> {
661 fn enqueue(&self, message: T) -> M::Feedback {
662 if self.closed.load(Ordering::Acquire) {
664 return M::ready_feedback(Feedback::Closed);
665 }
666
667 let message = match self.overflow.try_ready(&self.ready, message) {
669 Ok(()) => {
670 if self.closed.load(Ordering::Acquire) {
671 self.overflow.drain(&self.ready);
672 return M::ready_feedback(Feedback::Closed);
673 }
674 self.waker.wake();
675 return M::ready_feedback(Feedback::Ok);
676 }
677 Err(message) => message,
678 };
679
680 let feedback = self
682 .overflow
683 .enqueue_overflow(&self.ready, message, || self.closed.load(Ordering::Acquire));
684
685 if M::is_backoff(&feedback) {
687 self.backoff.inc();
688 }
689
690 if !M::is_closed(&feedback) {
695 self.waker.wake();
696 }
697 feedback
698 }
699
700 fn poll_recv(&self, cx: &mut Context<'_>) -> Poll<Option<T>> {
701 if let Some(message) = self.pop() {
703 return Poll::Ready(Some(message));
704 }
705
706 if self.is_disconnected() {
707 return Poll::Ready(self.pop());
708 }
709
710 register_waker(&self.waker, cx.waker());
711
712 if let Some(message) = self.pop() {
715 return Poll::Ready(Some(message));
716 }
717
718 if self.is_disconnected() {
719 Poll::Ready(self.pop())
720 } else {
721 Poll::Pending
722 }
723 }
724
725 fn pop(&self) -> Option<T> {
726 if let Some(message) = self.ready.pop() {
727 self.overflow.refill(&self.ready);
729 return Some(message);
730 }
731
732 self.overflow.refill(&self.ready);
735 self.ready.pop()
736 }
737
738 fn is_disconnected(&self) -> bool {
739 self.closed.load(Ordering::Acquire) || self.senders.load(Ordering::Acquire) == 0
740 }
741
742 fn close(&self) {
743 self.closed.store(true, Ordering::Release);
744 self.overflow.drain(&self.ready);
745 }
746}
747
748fn new_state<T, M: Mode<T>>(metrics: impl Metrics, capacity: NonZeroUsize) -> Arc<State<T, M>> {
749 Arc::new(State {
750 ready: Ready::new(capacity.get()),
751 overflow: OverflowState::new(),
752 backoff: metrics.counter("backoff", "number of enqueue calls that requested backoff"),
753 closed: AtomicBool::new(false),
754 senders: AtomicUsize::new(1),
755 waker: AtomicWaker::new(),
756 })
757}
758
759fn clone_sender_state<T, M: Mode<T>>(state: &Arc<State<T, M>>) -> Arc<State<T, M>> {
760 state.senders.fetch_add(1, Ordering::Relaxed);
762 state.clone()
763}
764
765fn drop_sender_state<T, M: Mode<T>>(state: &State<T, M>) {
766 let previous = state.senders.fetch_sub(1, Ordering::AcqRel);
767 assert!(previous > 0);
768 if previous == 1 {
770 state.waker.wake();
771 }
772}
773
774fn fmt_sender_state<T, M: Mode<T>>(
775 name: &str,
776 state: &State<T, M>,
777 f: &mut fmt::Formatter<'_>,
778) -> fmt::Result {
779 f.debug_struct(name)
780 .field("capacity", &state.ready.capacity())
781 .field("closed", &state.closed.load(Ordering::Acquire))
782 .finish()
783}
784
785async fn recv_from<T, M: Mode<T>>(state: &State<T, M>) -> Option<T> {
786 poll_fn(|cx| state.poll_recv(cx)).await
787}
788
789fn try_recv_from<T, M: Mode<T>>(state: &State<T, M>) -> Result<T, TryRecvError> {
790 if let Some(message) = state.pop() {
791 return Ok(message);
792 }
793 if state.is_disconnected() {
794 return state.pop().ok_or(TryRecvError::Disconnected);
795 }
796 Err(TryRecvError::Empty)
797}
798
799#[cfg(test)]
800mod mocks {
801 use commonware_runtime::{
802 Metrics as RuntimeMetrics, Name, Supervisor,
803 telemetry::metrics::{Metric, Registered},
804 };
805 use std::fmt;
806
807 #[derive(Clone, Copy, Debug, Default)]
808 pub(super) struct Metrics;
809
810 impl Supervisor for Metrics {
811 fn name(&self) -> Name {
812 Name::default()
813 }
814
815 fn child(&self, _label: &'static str) -> Self {
816 Self
817 }
818
819 fn with_attribute(self, _key: &'static str, _value: impl fmt::Display) -> Self {
820 self
821 }
822 }
823
824 impl RuntimeMetrics for Metrics {
825 fn register<N: Into<String>, H: Into<String>, M: Metric>(
826 &self,
827 _name: N,
828 _help: H,
829 metric: M,
830 ) -> Registered<M> {
831 Registered::detached(metric)
832 }
833
834 fn encode(&self) -> String {
835 String::new()
836 }
837 }
838}
839
840#[cfg(all(test, not(feature = "loom")))]
841mod tests {
842 use super::{mocks, *};
843 use commonware_macros::test_async;
844 use commonware_runtime::{Runner as _, Supervisor, deterministic};
845 use commonware_utils::{NZUsize, channel::oneshot};
846 use futures::{
847 FutureExt, pin_mut,
848 task::{ArcWake, waker_ref},
849 };
850 use std::sync::{
851 Arc,
852 atomic::{AtomicUsize, Ordering},
853 mpsc::TryRecvError,
854 };
855
856 fn new<T: Policy>(capacity: NonZeroUsize) -> (Sender<T>, Receiver<T>) {
857 super::new(mocks::Metrics, capacity)
858 }
859
860 fn new_unreliable<T: UnreliablePolicy>(
861 capacity: NonZeroUsize,
862 ) -> (UnreliableSender<T>, UnreliableReceiver<T>) {
863 super::new_unreliable(mocks::Metrics, capacity)
864 }
865
866 #[derive(Debug, PartialEq, Eq)]
867 enum Message {
868 Update(u64),
869 Vote(u64),
870 Required(u64),
871 Buffered(u64),
872 Hint(u64),
873 }
874
875 impl UnreliablePolicy for Message {
876 type Overflow = VecDeque<Self>;
877
878 fn handle(overflow: &mut VecDeque<Self>, message: Self) -> bool {
879 match message {
880 Self::Update(value) => {
881 if let Some(index) = overflow
882 .iter()
883 .rposition(|pending| matches!(pending, Self::Update(_)))
884 {
885 overflow.remove(index);
886 }
887 overflow.push_back(Self::Update(value));
888 true
889 }
890 Self::Required(_) | Self::Buffered(_) => {
891 overflow.push_back(message);
892 true
893 }
894 Self::Hint(value) => {
895 let Some(index) = overflow
896 .iter()
897 .rposition(|pending| matches!(pending, Self::Update(_)))
898 else {
899 return true;
900 };
901 overflow.remove(index);
902 overflow.push_back(Self::Hint(value));
903 true
904 }
905 Self::Vote(_) => false,
906 }
907 }
908 }
909
910 struct Ack {
911 _sender: oneshot::Sender<()>,
912 }
913
914 impl Policy for Ack {
915 type Overflow = VecDeque<Self>;
916
917 fn handle(overflow: &mut VecDeque<Self>, message: Self) {
918 overflow.push_back(message);
919 }
920 }
921
922 #[derive(Default)]
923 struct WakeCounter {
924 wakes: AtomicUsize,
925 }
926
927 impl WakeCounter {
928 fn count(&self) -> usize {
929 self.wakes.load(Ordering::Acquire)
930 }
931 }
932
933 impl ArcWake for WakeCounter {
934 fn wake_by_ref(arc_self: &Arc<Self>) {
935 arc_self.wakes.fetch_add(1, Ordering::AcqRel);
936 }
937 }
938
939 #[test]
940 fn vecdeque_overflow_drain_stops_after_rejected_message() {
941 let mut overflow = VecDeque::from([Message::Vote(1), Message::Vote(2), Message::Vote(3)]);
942 let mut drained = VecDeque::new();
943
944 Overflow::drain(&mut overflow, |message| {
945 drained.push_back(message);
946 if drained.len() == 2 {
947 drained.pop_back()
948 } else {
949 None
950 }
951 });
952
953 assert_eq!(drained, VecDeque::from([Message::Vote(1)]));
954 assert_eq!(
955 overflow,
956 VecDeque::from([Message::Vote(2), Message::Vote(3)])
957 );
958 }
959
960 #[test_async]
961 async fn full_inbox_replaces_stale_overflow_message() {
962 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
963 assert_eq!(
964 sender.enqueue(Message::Update(1)),
965 Unreliable::new(Feedback::Ok)
966 );
967 assert_eq!(
968 sender.enqueue(Message::Update(2)),
969 Unreliable::new(Feedback::Backoff)
970 );
971 assert_eq!(
972 sender.enqueue(Message::Update(3)),
973 Unreliable::new(Feedback::Backoff)
974 );
975
976 assert_eq!(receiver.recv().await, Some(Message::Update(1)));
977 assert_eq!(receiver.recv().await, Some(Message::Update(3)));
978 }
979
980 #[test_async]
981 async fn policy_can_replace_stale_overflow_at_back() {
982 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
983 assert_eq!(
984 sender.enqueue(Message::Vote(1)),
985 Unreliable::new(Feedback::Ok)
986 );
987 assert_eq!(
988 sender.enqueue(Message::Update(2)),
989 Unreliable::new(Feedback::Backoff)
990 );
991 assert_eq!(
992 sender.enqueue(Message::Required(3)),
993 Unreliable::new(Feedback::Backoff)
994 );
995 assert_eq!(
996 sender.enqueue(Message::Update(4)),
997 Unreliable::new(Feedback::Backoff)
998 );
999
1000 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1001 assert_eq!(receiver.recv().await, Some(Message::Required(3)));
1002 assert_eq!(receiver.recv().await, Some(Message::Update(4)));
1003 }
1004
1005 #[test_async]
1006 async fn full_inbox_rejects_non_replaceable_message() {
1007 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1008 assert_eq!(
1009 sender.enqueue(Message::Vote(1)),
1010 Unreliable::new(Feedback::Ok)
1011 );
1012 assert_eq!(sender.enqueue(Message::Vote(2)), Unreliable::Rejected);
1013
1014 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1015 }
1016
1017 #[test_async]
1018 async fn full_inbox_retains_required_message() {
1019 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1020 assert_eq!(
1021 sender.enqueue(Message::Vote(1)),
1022 Unreliable::new(Feedback::Ok)
1023 );
1024 assert_eq!(
1025 sender.enqueue(Message::Buffered(2)),
1026 Unreliable::new(Feedback::Backoff)
1027 );
1028
1029 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1030 assert_eq!(receiver.recv().await, Some(Message::Buffered(2)));
1031 }
1032
1033 #[test]
1034 fn try_recv_refills_from_overflow() {
1035 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1036 assert_eq!(
1037 sender.enqueue(Message::Vote(1)),
1038 Unreliable::new(Feedback::Ok)
1039 );
1040 assert_eq!(
1041 sender.enqueue(Message::Buffered(2)),
1042 Unreliable::new(Feedback::Backoff)
1043 );
1044
1045 assert_eq!(receiver.try_recv(), Ok(Message::Vote(1)));
1046 assert_eq!(receiver.try_recv(), Ok(Message::Buffered(2)));
1047 }
1048
1049 #[test]
1050 fn backoff_metric_counts_backoff_feedback() {
1051 let executor = deterministic::Runner::default();
1052 executor.start(|context| async move {
1053 let (sender, _receiver) = super::new_unreliable(context.child("mailbox"), NZUsize!(1));
1054 assert_eq!(
1055 sender.enqueue(Message::Vote(1)),
1056 Unreliable::new(Feedback::Ok)
1057 );
1058 assert_eq!(
1059 sender.enqueue(Message::Buffered(2)),
1060 Unreliable::new(Feedback::Backoff)
1061 );
1062 assert_eq!(
1063 sender.enqueue(Message::Buffered(3)),
1064 Unreliable::new(Feedback::Backoff)
1065 );
1066
1067 let buffer = context.encode();
1068 assert!(
1069 buffer.contains("mailbox_backoff_total 2"),
1070 "missing backoff count in metrics: {buffer}"
1071 );
1072 });
1073 }
1074
1075 #[test]
1076 fn unreliable_rejected_feedback_is_not_accepted_or_counted_as_backoff() {
1077 let executor = deterministic::Runner::default();
1078 executor.start(|context| async move {
1079 let (sender, _receiver) = super::new_unreliable(context.child("mailbox"), NZUsize!(1));
1080 assert_eq!(
1081 sender.enqueue(Message::Vote(1)),
1082 Unreliable::new(Feedback::Ok)
1083 );
1084 let feedback = sender.enqueue(Message::Vote(2));
1085
1086 assert_eq!(feedback, Unreliable::Rejected);
1087 assert!(!feedback.accepted());
1088
1089 let buffer = context.encode();
1090 assert!(
1091 buffer.contains("mailbox_backoff_total 0"),
1092 "unexpected backoff count in metrics: {buffer}"
1093 );
1094 });
1095 }
1096
1097 #[test]
1098 fn try_recv_drains_buffered_messages_after_senders_drop() {
1099 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1100 assert_eq!(
1101 sender.enqueue(Message::Vote(1)),
1102 Unreliable::new(Feedback::Ok)
1103 );
1104 assert_eq!(
1105 sender.enqueue(Message::Buffered(2)),
1106 Unreliable::new(Feedback::Backoff)
1107 );
1108 drop(sender);
1109
1110 assert_eq!(receiver.try_recv(), Ok(Message::Vote(1)));
1111 assert_eq!(receiver.try_recv(), Ok(Message::Buffered(2)));
1112 assert_eq!(receiver.try_recv(), Err(TryRecvError::Disconnected));
1113 }
1114
1115 #[test]
1116 fn poll_recv_drains_buffered_messages_after_senders_drop() {
1117 let (sender, receiver) = new_unreliable(NZUsize!(1));
1118 let wakes = Arc::new(WakeCounter::default());
1119 let waker = waker_ref(&wakes);
1120 let mut cx = Context::from_waker(&waker);
1121
1122 assert_eq!(
1123 sender.enqueue(Message::Vote(1)),
1124 Unreliable::new(Feedback::Ok)
1125 );
1126 assert_eq!(
1127 sender.enqueue(Message::Buffered(2)),
1128 Unreliable::new(Feedback::Backoff)
1129 );
1130 drop(sender);
1131
1132 assert_eq!(
1133 receiver.state.poll_recv(&mut cx),
1134 Poll::Ready(Some(Message::Vote(1)))
1135 );
1136 assert_eq!(
1137 receiver.state.poll_recv(&mut cx),
1138 Poll::Ready(Some(Message::Buffered(2)))
1139 );
1140 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Ready(None));
1141 }
1142
1143 #[test]
1144 fn enqueue_uses_ready_capacity_after_partial_drain() {
1145 let (sender, mut receiver) = new_unreliable(NZUsize!(2));
1146 assert_eq!(
1147 sender.enqueue(Message::Vote(1)),
1148 Unreliable::new(Feedback::Ok)
1149 );
1150 assert_eq!(
1151 sender.enqueue(Message::Vote(2)),
1152 Unreliable::new(Feedback::Ok)
1153 );
1154 assert_eq!(
1155 sender.enqueue(Message::Required(3)),
1156 Unreliable::new(Feedback::Backoff)
1157 );
1158
1159 assert_eq!(receiver.try_recv(), Ok(Message::Vote(1)));
1160 assert_eq!(receiver.try_recv(), Ok(Message::Vote(2)));
1161
1162 assert_eq!(
1163 sender.enqueue(Message::Vote(4)),
1164 Unreliable::new(Feedback::Ok)
1165 );
1166 assert_eq!(receiver.try_recv(), Ok(Message::Required(3)));
1167 assert_eq!(receiver.try_recv(), Ok(Message::Vote(4)));
1168 }
1169
1170 #[test]
1171 fn receiver_refills_overflow_after_partial_drain() {
1172 let (sender, mut receiver) = new_unreliable(NZUsize!(3));
1173 assert_eq!(
1174 sender.enqueue(Message::Vote(1)),
1175 Unreliable::new(Feedback::Ok)
1176 );
1177 assert_eq!(
1178 sender.enqueue(Message::Vote(2)),
1179 Unreliable::new(Feedback::Ok)
1180 );
1181 assert_eq!(
1182 sender.enqueue(Message::Vote(3)),
1183 Unreliable::new(Feedback::Ok)
1184 );
1185 assert_eq!(
1186 sender.enqueue(Message::Required(4)),
1187 Unreliable::new(Feedback::Backoff)
1188 );
1189
1190 assert_eq!(receiver.try_recv(), Ok(Message::Vote(1)));
1191 assert_eq!(receiver.try_recv(), Ok(Message::Vote(2)));
1192
1193 assert_eq!(
1194 sender.enqueue(Message::Vote(5)),
1195 Unreliable::new(Feedback::Ok)
1196 );
1197 assert_eq!(receiver.try_recv(), Ok(Message::Vote(3)));
1198 assert_eq!(receiver.try_recv(), Ok(Message::Required(4)));
1199 assert_eq!(receiver.try_recv(), Ok(Message::Vote(5)));
1200 }
1201
1202 #[test_async]
1203 async fn full_inbox_retains_unmatched_replaceable_message() {
1204 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1205 assert_eq!(
1206 sender.enqueue(Message::Vote(1)),
1207 Unreliable::new(Feedback::Ok)
1208 );
1209 assert_eq!(
1210 sender.enqueue(Message::Required(2)),
1211 Unreliable::new(Feedback::Backoff)
1212 );
1213
1214 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1215 assert_eq!(receiver.recv().await, Some(Message::Required(2)));
1216 }
1217
1218 #[test_async]
1219 async fn full_inbox_replaces_stale_overflow_after_ready_fills() {
1220 let (sender, mut receiver) = new_unreliable(NZUsize!(2));
1221 assert_eq!(
1222 sender.enqueue(Message::Vote(1)),
1223 Unreliable::new(Feedback::Ok)
1224 );
1225 assert_eq!(
1226 sender.enqueue(Message::Update(2)),
1227 Unreliable::new(Feedback::Ok)
1228 );
1229 assert_eq!(
1230 sender.enqueue(Message::Update(3)),
1231 Unreliable::new(Feedback::Backoff)
1232 );
1233 assert_eq!(
1234 sender.enqueue(Message::Update(4)),
1235 Unreliable::new(Feedback::Backoff)
1236 );
1237
1238 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1239 assert_eq!(receiver.recv().await, Some(Message::Update(2)));
1240 assert_eq!(receiver.recv().await, Some(Message::Update(4)));
1241 }
1242
1243 #[test_async]
1244 async fn mailbox_capacity_is_soft_limit_for_required_messages() {
1245 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1246 assert_eq!(
1247 sender.enqueue(Message::Vote(1)),
1248 Unreliable::new(Feedback::Ok)
1249 );
1250 assert_eq!(
1251 sender.enqueue(Message::Required(2)),
1252 Unreliable::new(Feedback::Backoff)
1253 );
1254 assert_eq!(
1255 sender.enqueue(Message::Required(3)),
1256 Unreliable::new(Feedback::Backoff)
1257 );
1258
1259 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1260 assert_eq!(receiver.recv().await, Some(Message::Required(2)));
1261 assert_eq!(receiver.recv().await, Some(Message::Required(3)));
1262 }
1263
1264 #[test_async]
1265 async fn full_inbox_rejects_hint() {
1266 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1267 assert_eq!(
1268 sender.enqueue(Message::Vote(1)),
1269 Unreliable::new(Feedback::Ok)
1270 );
1271 assert_eq!(
1272 sender.enqueue(Message::Hint(2)),
1273 Unreliable::new(Feedback::Backoff)
1274 );
1275
1276 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1277 }
1278
1279 #[test_async]
1280 async fn full_inbox_can_replace_or_drop_by_message() {
1281 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1282 assert_eq!(
1283 sender.enqueue(Message::Vote(1)),
1284 Unreliable::new(Feedback::Ok)
1285 );
1286 assert_eq!(
1287 sender.enqueue(Message::Update(2)),
1288 Unreliable::new(Feedback::Backoff)
1289 );
1290 assert_eq!(
1291 sender.enqueue(Message::Hint(3)),
1292 Unreliable::new(Feedback::Backoff)
1293 );
1294
1295 assert_eq!(receiver.recv().await, Some(Message::Vote(1)));
1296 assert_eq!(receiver.recv().await, Some(Message::Hint(3)));
1297 }
1298
1299 #[test_async]
1300 async fn empty_inbox_wakes_on_enqueue() {
1301 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1302
1303 let next = receiver.recv();
1304 pin_mut!(next);
1305 assert!(next.as_mut().now_or_never().is_none());
1306
1307 assert_eq!(
1308 sender.enqueue(Message::Vote(1)),
1309 Unreliable::new(Feedback::Ok)
1310 );
1311 assert_eq!(next.await, Some(Message::Vote(1)));
1312 }
1313
1314 #[test]
1315 fn pending_recv_wakes_when_senders_drop() {
1316 let (sender, receiver) = new_unreliable::<Message>(NZUsize!(1));
1317 let wakes = Arc::new(WakeCounter::default());
1318 let waker = waker_ref(&wakes);
1319 let mut cx = Context::from_waker(&waker);
1320
1321 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Pending);
1322 assert_eq!(wakes.count(), 0);
1323
1324 drop(sender);
1325
1326 assert_eq!(wakes.count(), 1);
1327 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Ready(None));
1328 }
1329
1330 #[test]
1331 fn pending_recv_wakes_on_handled_overflow_enqueue() {
1332 let (sender, mut receiver) = new_unreliable(NZUsize!(1));
1333 let wakes = Arc::new(WakeCounter::default());
1334 let waker = waker_ref(&wakes);
1335 let mut cx = Context::from_waker(&waker);
1336
1337 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Pending);
1338 assert_eq!(wakes.count(), 0);
1339
1340 assert_eq!(sender.state.ready.push(Message::Vote(1)), Ok(()));
1342 assert_eq!(
1343 sender.enqueue(Message::Buffered(2)),
1344 Unreliable::new(Feedback::Backoff)
1345 );
1346
1347 assert_eq!(wakes.count(), 1);
1348 assert_eq!(receiver.try_recv(), Ok(Message::Vote(1)));
1349 assert_eq!(receiver.try_recv(), Ok(Message::Buffered(2)));
1350 }
1351
1352 #[test]
1353 fn receiver_drop_blocks_ready_fast_path_feedback() {
1354 let (sender, receiver) = new_unreliable(NZUsize!(1));
1355 let wakes = Arc::new(WakeCounter::default());
1356 let waker = waker_ref(&wakes);
1357 let mut cx = Context::from_waker(&waker);
1358
1359 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Pending);
1360 drop(receiver);
1361
1362 assert_eq!(
1363 sender.enqueue(Message::Vote(1)),
1364 Unreliable::new(Feedback::Closed)
1365 );
1366 assert_eq!(wakes.count(), 0);
1367 }
1368
1369 #[test_async]
1370 async fn empty_inbox_closes_when_senders_drop() {
1371 let (sender, mut receiver) = new_unreliable::<Message>(NZUsize!(1));
1372 drop(sender);
1373
1374 assert_eq!(receiver.try_recv(), Err(TryRecvError::Disconnected));
1375 assert_eq!(receiver.recv().await, None);
1376 }
1377
1378 #[test]
1379 fn enqueue_after_receiver_drop_returns_closed() {
1380 let (sender, receiver) = new_unreliable(NZUsize!(1));
1381 drop(receiver);
1382
1383 assert_eq!(
1384 sender.enqueue(Message::Vote(1)),
1385 Unreliable::new(Feedback::Closed)
1386 );
1387 }
1388
1389 #[test_async]
1390 async fn receiver_drop_cancels_buffered_responders() {
1391 let (sender, receiver) = new(NZUsize!(1));
1392 let (ready_tx, ready_rx) = oneshot::channel();
1393 let (overflow_tx, overflow_rx) = oneshot::channel();
1394
1395 assert_eq!(sender.enqueue(Ack { _sender: ready_tx }), Feedback::Ok);
1396 assert_eq!(
1397 sender.enqueue(Ack {
1398 _sender: overflow_tx
1399 }),
1400 Feedback::Backoff
1401 );
1402 drop(receiver);
1403
1404 assert!(ready_rx.await.is_err());
1405 assert!(overflow_rx.await.is_err());
1406 }
1407
1408 #[derive(Debug, PartialEq, Eq)]
1409 enum ClearingMessage {
1410 FillReady,
1411 ClearOverflow,
1412 }
1413
1414 impl Policy for ClearingMessage {
1415 type Overflow = VecDeque<Self>;
1416
1417 fn handle(overflow: &mut VecDeque<Self>, message: Self) {
1418 overflow.push_back(message);
1419 overflow.clear();
1420 }
1421 }
1422
1423 #[test]
1424 fn policy_can_clear_overflow_and_request_backoff() {
1425 let (sender, mut receiver) = new(NZUsize!(1));
1426 assert_eq!(sender.enqueue(ClearingMessage::FillReady), Feedback::Ok);
1427 assert_eq!(
1428 sender.enqueue(ClearingMessage::ClearOverflow),
1429 Feedback::Backoff
1430 );
1431
1432 assert!(matches!(
1433 receiver.try_recv(),
1434 Ok(ClearingMessage::FillReady)
1435 ));
1436 assert_eq!(receiver.try_recv(), Err(TryRecvError::Empty));
1437 }
1438
1439 #[derive(Debug, PartialEq, Eq)]
1440 enum SpillMessage {
1441 FillReady,
1442 Spill,
1443 }
1444
1445 impl Policy for SpillMessage {
1446 type Overflow = VecDeque<Self>;
1447
1448 fn handle(overflow: &mut VecDeque<Self>, message: Self) {
1449 overflow.push_back(message);
1450 }
1451 }
1452
1453 #[test]
1454 fn pending_recv_wakes_when_policy_spills() {
1455 let (sender, mut receiver) = new(NZUsize!(1));
1456 let wakes = Arc::new(WakeCounter::default());
1457 let waker = waker_ref(&wakes);
1458 let mut cx = Context::from_waker(&waker);
1459
1460 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Pending);
1461 assert_eq!(wakes.count(), 0);
1462
1463 assert_eq!(sender.state.ready.push(SpillMessage::FillReady), Ok(()));
1464 assert_eq!(sender.enqueue(SpillMessage::Spill), Feedback::Backoff);
1465
1466 assert_eq!(wakes.count(), 1);
1467 assert_eq!(receiver.try_recv(), Ok(SpillMessage::FillReady));
1468 assert_eq!(receiver.try_recv(), Ok(SpillMessage::Spill));
1469 }
1470}
1471
1472#[cfg(all(test, feature = "loom"))]
1473mod loom_tests {
1474 use super::{mocks, *};
1475 use commonware_utils::NZUsize;
1476 use futures::pin_mut;
1477 use loom::{
1478 sync::{
1479 Arc,
1480 atomic::{AtomicUsize, Ordering},
1481 },
1482 thread,
1483 };
1484 use std::{
1485 future::Future,
1486 task::{RawWaker, RawWakerVTable, Waker},
1487 };
1488
1489 fn new<T: Policy>(capacity: NonZeroUsize) -> (Sender<T>, Receiver<T>) {
1490 super::new(mocks::Metrics, capacity)
1491 }
1492
1493 fn new_unreliable<T: UnreliablePolicy>(
1494 capacity: NonZeroUsize,
1495 ) -> (UnreliableSender<T>, UnreliableReceiver<T>) {
1496 super::new_unreliable(mocks::Metrics, capacity)
1497 }
1498
1499 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
1500 enum Message {
1501 Drop(u8),
1502 Spill(u8),
1503 }
1504
1505 #[derive(Clone, Debug)]
1506 enum OrderedMessage {
1507 Item(u8),
1508 Coordinated(u8, Arc<AtomicUsize>),
1509 }
1510
1511 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
1512 enum ReplacingMessage {
1513 FillReady,
1514 Replace(u8),
1515 }
1516
1517 struct TrackedMessage {
1518 drops: Arc<AtomicUsize>,
1519 }
1520
1521 struct CyclicMessage {
1522 _sender: Sender<Self>,
1523 drops: Arc<AtomicUsize>,
1524 }
1525
1526 impl TrackedMessage {
1527 const fn new(drops: Arc<AtomicUsize>) -> Self {
1528 Self { drops }
1529 }
1530 }
1531
1532 impl Drop for TrackedMessage {
1533 fn drop(&mut self) {
1534 self.drops.fetch_add(1, Ordering::AcqRel);
1535 }
1536 }
1537
1538 impl Drop for CyclicMessage {
1539 fn drop(&mut self) {
1540 self.drops.fetch_add(1, Ordering::AcqRel);
1541 }
1542 }
1543
1544 impl UnreliablePolicy for Message {
1545 type Overflow = VecDeque<Self>;
1546
1547 fn handle(overflow: &mut VecDeque<Self>, message: Self) -> bool {
1548 match message {
1549 Self::Drop(_) => false,
1550 Self::Spill(_) => {
1551 overflow.push_back(message);
1552 true
1553 }
1554 }
1555 }
1556 }
1557
1558 impl Policy for OrderedMessage {
1559 type Overflow = VecDeque<Self>;
1560
1561 fn handle(overflow: &mut VecDeque<Self>, message: Self) {
1562 let gate = match &message {
1563 Self::Item(_) => None,
1564 Self::Coordinated(_, gate) => Some(gate.clone()),
1565 };
1566 overflow.push_back(message);
1567 if let Some(gate) = gate {
1568 gate.store(1, Ordering::Release);
1569 while gate.load(Ordering::Acquire) == 1 {
1570 thread::yield_now();
1571 }
1572 }
1573 }
1574 }
1575
1576 impl UnreliablePolicy for ReplacingMessage {
1577 type Overflow = VecDeque<Self>;
1578
1579 fn handle(overflow: &mut VecDeque<Self>, message: Self) -> bool {
1580 match message {
1581 Self::FillReady => false,
1582 Self::Replace(_) => {
1583 if let Some(pending) = overflow
1584 .iter_mut()
1585 .rev()
1586 .find(|pending| matches!(pending, Self::Replace(_)))
1587 {
1588 *pending = message;
1589 } else {
1590 overflow.push_back(message);
1591 }
1592 true
1593 }
1594 }
1595 }
1596 }
1597
1598 impl Policy for TrackedMessage {
1599 type Overflow = VecDeque<Self>;
1600
1601 fn handle(overflow: &mut VecDeque<Self>, message: Self) {
1602 overflow.push_back(message);
1603 }
1604 }
1605
1606 impl Policy for CyclicMessage {
1607 type Overflow = VecDeque<Self>;
1608
1609 fn handle(overflow: &mut VecDeque<Self>, message: Self) {
1610 overflow.push_back(message);
1611 }
1612 }
1613
1614 fn record(seen: &AtomicUsize, message: Message) {
1615 let value = match message {
1616 Message::Drop(value) | Message::Spill(value) => value,
1617 };
1618 seen.fetch_or(1usize << usize::from(value), Ordering::AcqRel);
1619 }
1620
1621 fn value(message: OrderedMessage) -> u8 {
1622 match message {
1623 OrderedMessage::Item(value) | OrderedMessage::Coordinated(value, _) => value,
1624 }
1625 }
1626
1627 const fn replacement_value(message: ReplacingMessage) -> Option<u8> {
1628 match message {
1629 ReplacingMessage::FillReady => None,
1630 ReplacingMessage::Replace(value) => Some(value),
1631 }
1632 }
1633
1634 unsafe fn clone_counter(data: *const ()) -> RawWaker {
1635 let wakes = unsafe { Arc::<AtomicUsize>::from_raw(data.cast()) };
1638 let cloned = wakes.clone();
1639 let _ = Arc::into_raw(wakes);
1640 RawWaker::new(Arc::into_raw(cloned).cast(), &COUNTER_WAKER_VTABLE)
1641 }
1642
1643 unsafe fn wake_counter(data: *const ()) {
1644 let wakes = unsafe { Arc::<AtomicUsize>::from_raw(data.cast()) };
1647 wakes.fetch_add(1, Ordering::AcqRel);
1648 }
1649
1650 unsafe fn wake_counter_by_ref(data: *const ()) {
1651 let wakes = unsafe { Arc::<AtomicUsize>::from_raw(data.cast()) };
1654 wakes.fetch_add(1, Ordering::AcqRel);
1655 let _ = Arc::into_raw(wakes);
1656 }
1657
1658 unsafe fn drop_counter(data: *const ()) {
1659 unsafe {
1662 drop(Arc::<AtomicUsize>::from_raw(data.cast()));
1663 }
1664 }
1665
1666 static COUNTER_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
1667 clone_counter,
1668 wake_counter,
1669 wake_counter_by_ref,
1670 drop_counter,
1671 );
1672
1673 fn counting_waker(wakes: Arc<AtomicUsize>) -> Waker {
1674 let raw = RawWaker::new(Arc::into_raw(wakes).cast(), &COUNTER_WAKER_VTABLE);
1675 unsafe { Waker::from_raw(raw) }
1678 }
1679
1680 #[test]
1681 fn sender_drop_racing_waker_registration_wakes_or_disconnects() {
1682 loom::model(|| {
1683 let (sender, receiver) = new_unreliable::<Message>(NZUsize!(1));
1684 let wakes = Arc::new(AtomicUsize::new(0));
1685 let waker = counting_waker(wakes.clone());
1686 let mut cx = Context::from_waker(&waker);
1687
1688 let close = thread::spawn(move || {
1689 drop(sender);
1690 });
1691
1692 let poll = receiver.state.poll_recv(&mut cx);
1693 close.join().unwrap();
1694
1695 match poll {
1696 Poll::Ready(None) => {}
1697 Poll::Pending => {
1698 assert!(wakes.load(Ordering::Acquire) > 0);
1699 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Ready(None));
1700 }
1701 Poll::Ready(Some(_)) => panic!("unexpected message"),
1702 }
1703 });
1704 }
1705
1706 #[test]
1707 fn sender_enqueue_then_drop_racing_poll_recv_drains_message() {
1708 loom::model(|| {
1709 let (sender, receiver) = new_unreliable::<Message>(NZUsize!(1));
1710 let wakes = Arc::new(AtomicUsize::new(0));
1711 let waker = counting_waker(wakes.clone());
1712 let mut cx = Context::from_waker(&waker);
1713
1714 let enqueue = thread::spawn(move || {
1715 assert_eq!(
1716 sender.enqueue(Message::Spill(0)),
1717 Unreliable::new(Feedback::Ok)
1718 );
1719 });
1720
1721 let poll = receiver.state.poll_recv(&mut cx);
1722 enqueue.join().unwrap();
1723
1724 match poll {
1725 Poll::Ready(Some(Message::Spill(0))) => {}
1726 Poll::Pending => {
1727 assert!(wakes.load(Ordering::Acquire) > 0);
1728 assert_eq!(
1729 receiver.state.poll_recv(&mut cx),
1730 Poll::Ready(Some(Message::Spill(0)))
1731 );
1732 }
1733 Poll::Ready(None) => panic!("disconnected before draining message"),
1734 Poll::Ready(Some(message)) => panic!("unexpected message: {message:?}"),
1735 }
1736
1737 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Ready(None));
1738 });
1739 }
1740
1741 #[test]
1742 fn sender_enqueue_then_drop_racing_try_recv_drains_message() {
1743 loom::model(|| {
1744 let (sender, mut receiver) = new_unreliable::<Message>(NZUsize!(1));
1745
1746 let enqueue = thread::spawn(move || {
1747 assert_eq!(
1748 sender.enqueue(Message::Spill(0)),
1749 Unreliable::new(Feedback::Ok)
1750 );
1751 });
1752
1753 let result = receiver.try_recv();
1754 enqueue.join().unwrap();
1755
1756 match result {
1757 Ok(Message::Spill(0)) => {}
1758 Err(TryRecvError::Empty) => {
1759 assert_eq!(receiver.try_recv(), Ok(Message::Spill(0)));
1760 }
1761 Err(TryRecvError::Disconnected) => {
1762 panic!("disconnected before draining message");
1763 }
1764 Ok(message) => panic!("unexpected message: {message:?}"),
1765 }
1766
1767 assert_eq!(receiver.try_recv(), Err(TryRecvError::Disconnected));
1768 });
1769 }
1770
1771 #[test]
1772 fn handled_enqueue_wakes_registered_receiver() {
1773 loom::model(|| {
1774 let (sender, mut receiver) = new_unreliable::<Message>(NZUsize!(1));
1775 let wakes = Arc::new(AtomicUsize::new(0));
1776 let waker = counting_waker(wakes.clone());
1777 let mut cx = Context::from_waker(&waker);
1778
1779 let next = receiver.recv();
1780 pin_mut!(next);
1781 assert!(matches!(next.as_mut().poll(&mut cx), Poll::Pending));
1782 assert_eq!(
1783 sender.enqueue(Message::Spill(0)),
1784 Unreliable::new(Feedback::Ok)
1785 );
1786
1787 assert_eq!(wakes.load(Ordering::Acquire), 1);
1788 assert_eq!(
1789 next.as_mut().poll(&mut cx),
1790 Poll::Ready(Some(Message::Spill(0)))
1791 );
1792 });
1793 }
1794
1795 #[test]
1796 fn receiver_drop_racing_ready_fast_path_feedback_wakes_if_ready() {
1797 loom::model(|| {
1798 let (sender, receiver) = new_unreliable::<Message>(NZUsize!(1));
1799 let wakes = Arc::new(AtomicUsize::new(0));
1800 let waker = counting_waker(wakes.clone());
1801 let mut cx = Context::from_waker(&waker);
1802
1803 assert_eq!(receiver.state.poll_recv(&mut cx), Poll::Pending);
1804
1805 let close = thread::spawn(move || {
1806 drop(receiver);
1807 });
1808 let feedback = sender.enqueue(Message::Spill(0));
1809 close.join().unwrap();
1810
1811 if feedback.accepted() {
1812 assert!(wakes.load(Ordering::Acquire) > 0);
1813 } else {
1814 assert_eq!(feedback, Unreliable::new(Feedback::Closed));
1815 }
1816 assert_eq!(
1817 sender.enqueue(Message::Spill(1)),
1818 Unreliable::new(Feedback::Closed)
1819 );
1820 });
1821 }
1822
1823 #[test]
1824 fn receiver_drop_racing_ready_enqueue_drops_message() {
1825 loom::model(|| {
1826 let (sender, receiver) = new::<TrackedMessage>(NZUsize!(1));
1827 let drops = Arc::new(AtomicUsize::new(0));
1828
1829 let close = thread::spawn(move || {
1830 drop(receiver);
1831 });
1832 let _ = sender.enqueue(TrackedMessage::new(drops.clone()));
1833 close.join().unwrap();
1834
1835 assert_eq!(drops.load(Ordering::Acquire), 1);
1836 });
1837 }
1838
1839 #[test]
1840 fn receiver_drop_racing_overflow_enqueue_drops_messages() {
1841 loom::model(|| {
1842 let (sender, receiver) = new::<TrackedMessage>(NZUsize!(1));
1843 let ready_drops = Arc::new(AtomicUsize::new(0));
1844 let overflow_drops = Arc::new(AtomicUsize::new(0));
1845
1846 assert_eq!(
1847 sender.enqueue(TrackedMessage::new(ready_drops.clone())),
1848 Feedback::Ok
1849 );
1850 let close = thread::spawn(move || {
1851 drop(receiver);
1852 });
1853 let _ = sender.enqueue(TrackedMessage::new(overflow_drops.clone()));
1854 close.join().unwrap();
1855
1856 assert_eq!(ready_drops.load(Ordering::Acquire), 1);
1857 assert_eq!(overflow_drops.load(Ordering::Acquire), 1);
1858 });
1859 }
1860
1861 #[test]
1862 fn receiver_drop_drains_ready_message_published_under_overflow_lock() {
1863 loom::model(|| {
1864 let (sender, receiver) = new::<TrackedMessage>(NZUsize!(1));
1865 let drops = Arc::new(AtomicUsize::new(0));
1866 let mutation = Mutation::begin(&sender.state.overflow.activity);
1867 let queue = lock(&sender.state.overflow.queue);
1868
1869 let close = thread::spawn(move || {
1870 drop(receiver);
1871 });
1872
1873 assert!(
1874 sender
1875 .state
1876 .ready
1877 .push(TrackedMessage::new(drops.clone()))
1878 .is_ok()
1879 );
1880 mutation.publish(queue.is_empty());
1881 drop(queue);
1882 drop(mutation);
1883 close.join().unwrap();
1884
1885 assert_eq!(drops.load(Ordering::Acquire), 1);
1886 });
1887 }
1888
1889 #[test]
1890 fn receiver_drop_drains_overflow_message_published_under_overflow_lock() {
1891 loom::model(|| {
1892 let (sender, receiver) = new::<TrackedMessage>(NZUsize!(1));
1893 let ready_drops = Arc::new(AtomicUsize::new(0));
1894 let overflow_drops = Arc::new(AtomicUsize::new(0));
1895
1896 assert_eq!(
1897 sender.enqueue(TrackedMessage::new(ready_drops.clone())),
1898 Feedback::Ok
1899 );
1900
1901 let mutation = Mutation::begin(&sender.state.overflow.activity);
1902 let mut queue = lock(&sender.state.overflow.queue);
1903 let close = thread::spawn(move || {
1904 drop(receiver);
1905 });
1906
1907 queue.push_back(TrackedMessage::new(overflow_drops.clone()));
1908 mutation.publish(queue.is_empty());
1909 drop(queue);
1910 drop(mutation);
1911 close.join().unwrap();
1912
1913 assert_eq!(ready_drops.load(Ordering::Acquire), 1);
1914 assert_eq!(overflow_drops.load(Ordering::Acquire), 1);
1915 });
1916 }
1917
1918 #[test]
1919 fn receiver_drop_breaks_message_sender_cycle() {
1920 loom::model(|| {
1921 let (sender, receiver) = new::<CyclicMessage>(NZUsize!(1));
1922 let drops = Arc::new(AtomicUsize::new(0));
1923
1924 assert_eq!(
1925 sender.enqueue(CyclicMessage {
1926 _sender: sender.clone(),
1927 drops: drops.clone(),
1928 }),
1929 Feedback::Ok
1930 );
1931 assert_eq!(
1932 sender.enqueue(CyclicMessage {
1933 _sender: sender.clone(),
1934 drops: drops.clone(),
1935 }),
1936 Feedback::Backoff
1937 );
1938
1939 drop(receiver);
1940
1941 assert_eq!(drops.load(Ordering::Acquire), 2);
1942 assert_eq!(
1943 sender.enqueue(CyclicMessage {
1944 _sender: sender.clone(),
1945 drops,
1946 }),
1947 Feedback::Closed
1948 );
1949 });
1950 }
1951
1952 #[test]
1953 fn concurrent_close_and_ready_enqueue_remains_closed() {
1954 loom::model(|| {
1955 let (sender, receiver) = new_unreliable::<Message>(NZUsize!(1));
1956
1957 let enqueue_sender = sender.clone();
1958 let enqueue = thread::spawn(move || {
1959 let _ = enqueue_sender.enqueue(Message::Spill(1));
1960 });
1961
1962 let close = thread::spawn(move || {
1963 drop(receiver);
1964 });
1965
1966 enqueue.join().unwrap();
1967 close.join().unwrap();
1968 assert_eq!(
1969 sender.enqueue(Message::Spill(2)),
1970 Unreliable::new(Feedback::Closed)
1971 );
1972 });
1973 }
1974
1975 #[test]
1976 fn concurrent_close_and_overflow_enqueue_remains_closed() {
1977 loom::model(|| {
1978 let (sender, receiver) = new_unreliable::<Message>(NZUsize!(1));
1979 assert_eq!(
1980 sender.enqueue(Message::Drop(0)),
1981 Unreliable::new(Feedback::Ok)
1982 );
1983
1984 let enqueue_sender = sender.clone();
1985 let enqueue = thread::spawn(move || {
1986 let _ = enqueue_sender.enqueue(Message::Spill(1));
1987 });
1988
1989 let close = thread::spawn(move || {
1990 drop(receiver);
1991 });
1992
1993 enqueue.join().unwrap();
1994 close.join().unwrap();
1995 assert_eq!(
1996 sender.enqueue(Message::Spill(2)),
1997 Unreliable::new(Feedback::Closed)
1998 );
1999 });
2000 }
2001
2002 #[test]
2003 fn concurrent_spill_and_refill_preserves_messages() {
2004 loom::model(|| {
2005 let (sender, mut receiver) = new_unreliable::<Message>(NZUsize!(1));
2006 let idle_sender = sender.clone();
2007 assert_eq!(
2008 sender.enqueue(Message::Spill(0)),
2009 Unreliable::new(Feedback::Ok)
2010 );
2011
2012 let seen = Arc::new(AtomicUsize::new(0));
2013 let enqueue = thread::spawn(move || {
2014 let feedback = sender.enqueue(Message::Spill(1));
2015 assert!(feedback.accepted());
2016 });
2017
2018 let seen_by_receiver = seen.clone();
2019 let recv = thread::spawn(move || {
2020 if let Ok(message) = receiver.try_recv() {
2021 record(&seen_by_receiver, message);
2022 }
2023 receiver
2024 });
2025
2026 enqueue.join().unwrap();
2027 let mut receiver = recv.join().unwrap();
2028
2029 while let Ok(message) = receiver.try_recv() {
2030 record(&seen, message);
2031 }
2032 assert_eq!(receiver.try_recv(), Err(TryRecvError::Empty));
2033 drop(idle_sender);
2034 assert_eq!(seen.load(Ordering::Acquire), 0b11);
2035 });
2036 }
2037
2038 #[test]
2039 fn concurrent_spill_senders_preserve_messages() {
2040 loom::model(|| {
2041 let (sender, mut receiver) = new_unreliable::<Message>(NZUsize!(1));
2042 let idle_sender = sender.clone();
2043 assert_eq!(
2044 sender.enqueue(Message::Spill(0)),
2045 Unreliable::new(Feedback::Ok)
2046 );
2047
2048 let sender_1 = sender.clone();
2049 let enqueue_1 = thread::spawn(move || sender_1.enqueue(Message::Spill(1)));
2050 let enqueue_2 = thread::spawn(move || sender.enqueue(Message::Spill(2)));
2051
2052 let seen = Arc::new(AtomicUsize::new(0));
2053
2054 assert!(enqueue_1.join().unwrap().accepted());
2055 assert!(enqueue_2.join().unwrap().accepted());
2056
2057 while let Ok(message) = receiver.try_recv() {
2058 record(&seen, message);
2059 }
2060 assert_eq!(receiver.try_recv(), Err(TryRecvError::Empty));
2061 drop(idle_sender);
2062 assert_eq!(seen.load(Ordering::Acquire), 0b111);
2063 });
2064 }
2065
2066 #[test]
2067 fn concurrent_replace_keeps_one_overflow_message() {
2068 loom::model(|| {
2069 let (sender, mut receiver) = new_unreliable::<ReplacingMessage>(NZUsize!(1));
2070 let idle_sender = sender.clone();
2071 assert_eq!(
2072 sender.enqueue(ReplacingMessage::FillReady),
2073 Unreliable::new(Feedback::Ok)
2074 );
2075 assert_eq!(
2076 sender.enqueue(ReplacingMessage::Replace(1)),
2077 Unreliable::new(Feedback::Backoff)
2078 );
2079
2080 let sender_1 = sender.clone();
2081 let replace_1 = thread::spawn(move || sender_1.enqueue(ReplacingMessage::Replace(2)));
2082 let replace_2 = thread::spawn(move || sender.enqueue(ReplacingMessage::Replace(3)));
2083
2084 assert_eq!(
2085 replace_1.join().unwrap(),
2086 Unreliable::new(Feedback::Backoff)
2087 );
2088 assert_eq!(
2089 replace_2.join().unwrap(),
2090 Unreliable::new(Feedback::Backoff)
2091 );
2092 assert_eq!(receiver.try_recv(), Ok(ReplacingMessage::FillReady));
2093
2094 let retained = replacement_value(receiver.try_recv().unwrap()).unwrap();
2095 assert!(retained == 2 || retained == 3);
2096 assert_eq!(receiver.try_recv(), Err(TryRecvError::Empty));
2097 drop(idle_sender);
2098 });
2099 }
2100
2101 #[test]
2102 fn stale_overflow_hint_retries_ready_before_policy() {
2103 loom::model(|| {
2104 let (sender, mut receiver) = new_unreliable::<Message>(NZUsize!(2));
2105 assert_eq!(
2106 sender.enqueue(Message::Drop(0)),
2107 Unreliable::new(Feedback::Ok)
2108 );
2109 assert_eq!(
2110 sender.enqueue(Message::Drop(1)),
2111 Unreliable::new(Feedback::Ok)
2112 );
2113 assert_eq!(
2114 sender.enqueue(Message::Spill(2)),
2115 Unreliable::new(Feedback::Backoff)
2116 );
2117
2118 assert_eq!(receiver.try_recv(), Ok(Message::Drop(0)));
2119 assert_eq!(receiver.try_recv(), Ok(Message::Drop(1)));
2120
2121 assert_eq!(
2122 sender.enqueue(Message::Drop(3)),
2123 Unreliable::new(Feedback::Ok)
2124 );
2125 assert_eq!(receiver.try_recv(), Ok(Message::Spill(2)));
2126 assert_eq!(receiver.try_recv(), Ok(Message::Drop(3)));
2127 });
2128 }
2129
2130 #[test]
2131 fn concurrent_overflow_cannot_be_bypassed_by_ready_fast_path() {
2132 loom::model(|| {
2133 let (sender, mut receiver) = new::<OrderedMessage>(NZUsize!(2));
2134 assert_eq!(sender.enqueue(OrderedMessage::Item(0)), Feedback::Ok);
2135 assert_eq!(sender.enqueue(OrderedMessage::Item(1)), Feedback::Ok);
2136
2137 let gate = Arc::new(AtomicUsize::new(0));
2138 let overflow_sender = sender.clone();
2139 let overflow_gate = gate.clone();
2140 let overflow = thread::spawn(move || {
2141 assert_eq!(
2142 overflow_sender.enqueue(OrderedMessage::Coordinated(2, overflow_gate)),
2143 Feedback::Backoff
2144 );
2145 });
2146
2147 while gate.load(Ordering::Acquire) == 0 {
2148 thread::yield_now();
2149 }
2150
2151 let mut observed = vec![value(receiver.try_recv().unwrap())];
2154 gate.store(2, Ordering::Release);
2155 let feedback = sender.enqueue(OrderedMessage::Item(3));
2156 assert!(feedback.accepted());
2157
2158 overflow.join().unwrap();
2159 while let Ok(message) = receiver.try_recv() {
2160 observed.push(value(message));
2161 }
2162
2163 assert_eq!(observed, vec![0, 1, 2, 3]);
2164 });
2165 }
2166
2167 #[test]
2168 fn concurrent_overflow_mutation_does_not_hide_published_overflow() {
2169 loom::model(|| {
2170 let (sender, mut receiver) = new::<OrderedMessage>(NZUsize!(1));
2171 assert_eq!(sender.enqueue(OrderedMessage::Item(0)), Feedback::Ok);
2172 assert_eq!(sender.enqueue(OrderedMessage::Item(1)), Feedback::Backoff);
2173
2174 let gate = Arc::new(AtomicUsize::new(0));
2175 let overflow_gate = gate.clone();
2176 let overflow = thread::spawn(move || {
2177 sender.enqueue(OrderedMessage::Coordinated(2, overflow_gate))
2178 });
2179
2180 while gate.load(Ordering::Acquire) == 0 {
2181 thread::yield_now();
2182 }
2183
2184 let release_gate = gate;
2185 let release = thread::spawn(move || {
2186 release_gate.store(2, Ordering::Release);
2187 });
2188
2189 let receive = thread::spawn(move || {
2190 assert_eq!(receiver.try_recv().map(value), Ok(0));
2191 assert_eq!(receiver.try_recv().map(value), Ok(1));
2192 receiver
2193 });
2194
2195 release.join().unwrap();
2196 let mut receiver = receive.join().unwrap();
2197 assert_eq!(overflow.join().unwrap(), Feedback::Backoff);
2198 assert_eq!(receiver.try_recv().map(value), Ok(2));
2199 });
2200 }
2201
2202 #[test]
2203 fn published_overflow_wakes_pending_receiver() {
2204 loom::model(|| {
2205 let (sender, mut receiver) = new::<OrderedMessage>(NZUsize!(1));
2206 let wakes = Arc::new(AtomicUsize::new(0));
2207 let waker = counting_waker(wakes.clone());
2208 let mut cx = Context::from_waker(&waker);
2209
2210 let gate = Arc::new(AtomicUsize::new(0));
2211 let overflow = {
2212 let next = receiver.recv();
2213 pin_mut!(next);
2214 assert!(matches!(next.as_mut().poll(&mut cx), Poll::Pending));
2215
2216 assert_eq!(sender.enqueue(OrderedMessage::Item(0)), Feedback::Ok);
2217 while wakes.load(Ordering::Acquire) == 0 {
2218 thread::yield_now();
2219 }
2220
2221 let overflow_gate = gate.clone();
2222 let overflow = thread::spawn(move || {
2223 sender.enqueue(OrderedMessage::Coordinated(1, overflow_gate))
2224 });
2225
2226 while gate.load(Ordering::Acquire) == 0 {
2227 thread::yield_now();
2228 }
2229
2230 assert_eq!(
2231 next.as_mut()
2232 .poll(&mut cx)
2233 .map(|message| message.map(value)),
2234 Poll::Ready(Some(0))
2235 );
2236 overflow
2237 };
2238
2239 {
2240 let next = receiver.recv();
2241 pin_mut!(next);
2242 assert!(matches!(next.as_mut().poll(&mut cx), Poll::Pending));
2243 assert_eq!(wakes.load(Ordering::Acquire), 1);
2244
2245 gate.store(2, Ordering::Release);
2246 while wakes.load(Ordering::Acquire) < 2 {
2247 thread::yield_now();
2248 }
2249
2250 assert_eq!(
2251 next.as_mut()
2252 .poll(&mut cx)
2253 .map(|message| message.map(value)),
2254 Poll::Ready(Some(1))
2255 );
2256 }
2257 assert_eq!(overflow.join().unwrap(), Feedback::Backoff);
2258 });
2259 }
2260
2261 #[test]
2262 fn concurrent_refill_and_enqueue_preserves_overflow_order() {
2263 loom::model(|| {
2264 let (sender, mut receiver) = new::<OrderedMessage>(NZUsize!(1));
2265 assert_eq!(sender.enqueue(OrderedMessage::Item(0)), Feedback::Ok);
2266 assert_eq!(sender.enqueue(OrderedMessage::Item(1)), Feedback::Backoff);
2267
2268 let enqueue = thread::spawn(move || sender.enqueue(OrderedMessage::Item(2)));
2269 let receive = thread::spawn(move || {
2270 assert_eq!(receiver.try_recv().map(value), Ok(0));
2271 receiver
2272 });
2273
2274 let mut receiver = receive.join().unwrap();
2275 assert_eq!(enqueue.join().unwrap(), Feedback::Backoff);
2276 assert_eq!(receiver.try_recv().map(value), Ok(1));
2277 assert_eq!(receiver.try_recv().map(value), Ok(2));
2278 });
2279 }
2280}