Skip to main content

commonware_actor/
mailbox.rs

1//! Bounded message queue with caller-managed overflow.
2//!
3//! # Architecture
4//!
5//! The mailbox is split into two queues: a bounded `ready` queue
6//! that producers push to and the receiver pops from, and an unbounded
7//! `overflow` queue that holds messages displaced when ready is full. A
8//! [`Policy`] or [`UnreliablePolicy`] decides how overflow is updated when
9//! overflow is contended.
10//!
11//! ```text
12//!                          senders
13//!                             |
14//!         +-------------------+--------------------+
15//!         | overflow inactive                      | overflow active
16//!         | and ready has room                     | or ready full
17//!         v                                        v
18//!     +----------+    refill front-to-back     +----------+
19//!     |  ready   |<----------------------------| overflow |
20//!     +----------+    after each ready pop     +----------+
21//!         |
22//!         | pop first
23//!         v
24//!      receiver
25//! ```
26//!
27//! The receiver always pops from the ready queue first. After each ready pop, it
28//! eagerly refills ready from published overflow so senders can return to the
29//! ready fast path without waiting for ready to drain completely. Overflow is
30//! refilled from front to back, but policies decide which overflow messages are
31//! retained and in what order.
32//!
33//! Overflow should be rare. When overflow is populated, the receiver refills
34//! ready immediately instead of waiting to batch refill work. This can take the
35//! overflow lock once per popped message, but it keeps ready capacity available
36//! for later sends as soon as possible.
37//!
38//! # Ordering
39//!
40//! Enqueue calls from the same sender will be delivered in order. Concurrent enqueue calls,
41//! however, are not globally ordered and may be observed in any interleaving.
42
43use 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
58/// Retained overflow messages for a mailbox policy.
59pub trait Overflow<T>: Default {
60    /// Return whether the retained message set is empty.
61    fn is_empty(&self) -> bool;
62
63    /// Drain retained messages into `push` in delivery order until `push`
64    /// rejects a message.
65    ///
66    /// If `push` returns `Some`, the undelivered message and any later messages
67    /// must remain retained for a future drain.
68    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
91/// Overflow behavior for actor messages when an inbox is full.
92pub trait Policy: Sized {
93    /// Overflow storage used by this policy.
94    type Overflow: Overflow<Self>;
95
96    /// Reliably handle `message` when it cannot enter the bounded ready queue immediately.
97    ///
98    /// This may retain the message, coalesce it with retained work, replace older retained work,
99    /// or deliberately do no work because the message is already satisfied, superseded, or no
100    /// longer needed (for example, a request whose response channel is already closed).
101    ///
102    /// # Warning
103    ///
104    /// Do not enqueue into the same mailbox from this method or from destructors triggered by
105    /// editing `overflow`. This method runs while the mailbox holds its overflow lock, so same
106    /// mailbox re-entry can deadlock.
107    ///
108    /// This method should not unwind after mutating `overflow`. A panic, including one from a
109    /// destructor triggered while editing `overflow`, can leave retained overflow data stranded in
110    /// the mailbox.
111    fn handle(overflow: &mut Self::Overflow, message: Self);
112}
113
114/// Overflow behavior for actor messages that can be rejected when an inbox is full.
115pub trait UnreliablePolicy: Sized {
116    /// Overflow storage used by this policy.
117    type Overflow: Overflow<Self>;
118
119    /// Unreliably handle `message` when it cannot enter the bounded ready queue immediately.
120    ///
121    /// Returns `true` when the policy considered the message's effects. This includes retaining
122    /// the message, coalescing it with retained work, replacing older retained work, or deliberately
123    /// doing no work because the message is already satisfied, superseded, or no longer needed.
124    ///
125    /// Returns `false` only when the policy rejects the message under backpressure without
126    /// retaining, coalescing, replacing, or otherwise handling it. This is the unreliable case: the
127    /// submitted work was not semantically handled, and callers that care should retry or treat the
128    /// submission as failed.
129    ///
130    /// # Warning
131    ///
132    /// Do not enqueue into the same mailbox from this method or from destructors triggered by
133    /// editing `overflow`. This method runs while the mailbox holds its overflow lock, so same
134    /// mailbox re-entry can deadlock.
135    ///
136    /// This method should not unwind after mutating `overflow`. A panic, including one from a
137    /// destructor triggered while editing `overflow`, can leave retained overflow data stranded in
138    /// the mailbox.
139    fn handle(overflow: &mut Self::Overflow, message: Self) -> bool;
140}
141
142// Marker types that select the mailbox overflow policy.
143mod mode {
144    /// Uses a policy that always handles overflow messages.
145    pub(super) struct Reliable;
146
147    /// Uses a policy that may reject overflow messages.
148    pub(super) struct Unreliable;
149}
150
151trait Mode<T>: Sized {
152    /// Overflow storage used by this mode.
153    type Overflow: Overflow<T>;
154    /// Feedback returned from enqueue attempts.
155    type Feedback;
156
157    /// Updates overflow for a full inbox and reports whether the message was handled.
158    fn handle(overflow: &mut Self::Overflow, message: T) -> bool;
159    /// Maps ready-path feedback into this mode's feedback type.
160    fn ready_feedback(feedback: Feedback) -> Self::Feedback;
161    /// Maps overflow handling into this mode's feedback type.
162    fn overflow_feedback(handled: bool) -> Self::Feedback;
163    /// Returns `true` when this feedback should count as backoff.
164    fn is_backoff(feedback: &Self::Feedback) -> bool;
165    /// Returns `true` when this feedback means the receiver is closed.
166    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
224/// Sender half of a mailbox.
225pub struct Sender<T: Policy> {
226    state: Arc<State<T, mode::Reliable>>,
227}
228
229/// Sender half of an unreliable mailbox.
230pub 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    /// Submit a message without waiting for inbox capacity.
276    #[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    /// Submit a message without waiting for inbox capacity, allowing policy rejection.
284    #[must_use = "caller must handle enqueue feedback"]
285    pub fn enqueue(&self, message: T) -> Unreliable<Feedback> {
286        self.state.enqueue(message)
287    }
288}
289
290/// Receiver half of a mailbox.
291///
292/// Dropping the receiver closes the mailbox and drains buffered messages.
293///
294/// Dropping the last sender disconnects the mailbox, but the receiver continues
295/// returning buffered messages until ready and overflow are empty.
296pub struct Receiver<T: Policy> {
297    state: Arc<State<T, mode::Reliable>>,
298}
299
300/// Receiver half of an unreliable mailbox.
301///
302/// Dropping the receiver closes the mailbox and drains buffered messages.
303///
304/// Dropping the last sender disconnects the mailbox, but the receiver continues
305/// returning buffered messages until ready and overflow are empty.
306pub struct UnreliableReceiver<T: UnreliablePolicy> {
307    state: Arc<State<T, mode::Unreliable>>,
308}
309
310impl<T: Policy> Receiver<T> {
311    /// Receive the next message.
312    ///
313    /// Returns `None` after all senders are dropped and all buffered messages
314    /// have been drained.
315    pub async fn recv(&mut self) -> Option<T> {
316        recv_from(&self.state).await
317    }
318
319    /// Try to receive the next message without waiting.
320    ///
321    /// Returns [`TryRecvError::Disconnected`] after all senders are dropped and
322    /// all buffered messages have been drained.
323    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
324        try_recv_from(&self.state)
325    }
326}
327
328impl<T: UnreliablePolicy> UnreliableReceiver<T> {
329    /// Receive the next message.
330    ///
331    /// Returns `None` after all senders are dropped and all buffered messages
332    /// have been drained.
333    pub async fn recv(&mut self) -> Option<T> {
334        recv_from(&self.state).await
335    }
336
337    /// Try to receive the next message without waiting.
338    ///
339    /// Returns [`TryRecvError::Disconnected`] after all senders are dropped and
340    /// all buffered messages have been drained.
341    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
358/// Create a new bounded mailbox.
359pub 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
369/// Create a new bounded unreliable mailbox.
370pub 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
383// `activity` packs the published overflow state and in-flight overflow
384// mutations into one atomic word. The overflow lock serializes actual
385// overflow changes (this word lets the ready fast path avoid that lock when
386// overflow is inactive).
387//
388// The low bit records whether the most recently published overflow state was
389// non-empty. The higher bits count active overflow mutations. Each mutation
390// adds `OVERFLOW_MUTATION` while it may mutate or publish overflow state, so
391// the count and the state bit coexist in the same word.
392//
393// Useful states:
394// - `activity == 0`: no published overflow and no active overflow mutation, so
395//   senders may try the direct ready fast path.
396// - `activity & OVERFLOW_HAS_MESSAGES != 0`: overflow has published messages,
397//   so the receiver may try to refill ready. The overflow lock serializes
398//   refill with any active mutation.
399// - `activity >= OVERFLOW_MUTATION`: at least one overflow mutation is active.
400//   The overflow lock still serializes queue access; this state only keeps
401//   lock-free fast-path/refill decisions from acting on a changing overflow
402//   snapshot.
403//
404// Activity accesses are relaxed because this word does not publish queue
405// contents. The overflow mutex serializes overflow access, and the ready queue
406// owns its own synchronization. Stale activity observations only decide whether
407// a caller tries a fast path, locks overflow, or waits for a later wake.
408const 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        // Avoid ready while overflow is retained or changing.
545        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        // Mark overflow active so racing senders stay off the ready fast path.
558        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        // The fast-path push may have observed stale ready fullness. Retry
566        // ready under the overflow lock before applying policy, but only when
567        // there is no retained overflow that must stay ahead of this message.
568        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        // Preserve overflow order, or handle a still-full ready queue.
581        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        // Skip the overflow lock unless non-empty overflow was published.
588        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        // Attempt to drain all messages from ready
600        let mutation = Mutation::begin(&self.activity);
601        while ready.pop().is_some() {}
602
603        // Attempt to drain all messages from overflow (storing messages to drop after
604        // releasing the lock)
605        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        // A sender may have passed the fast-path activity check before this
616        // mutation began, so we drain again
617        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        // Receiver closure makes new sends fail immediately.
663        if self.closed.load(Ordering::Acquire) {
664            return M::ready_feedback(Feedback::Closed);
665        }
666
667        // Common case: publish directly to ready without taking overflow lock.
668        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        // Slow path: serialize through overflow and apply the policy.
681        let feedback = self
682            .overflow
683            .enqueue_overflow(&self.ready, message, || self.closed.load(Ordering::Acquire));
684
685        // Record any backoff.
686        if M::is_backoff(&feedback) {
687            self.backoff.inc();
688        }
689
690        // Wake after any non-closed slow-path enqueue because a receiver may
691        // have skipped refill while this overflow mutation was active. By the
692        // time we wake, the mutation has published its overflow state. Spurious
693        // wakes are acceptable.
694        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        // Fast path avoids waker churn when a message is already ready.
702        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        // A sender can enqueue and wake after the first pop but before this
713        // waker is installed. Re-check before sleeping so the wake is not lost.
714        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            // A freed ready slot may let the oldest overflow message advance.
728            self.overflow.refill(&self.ready);
729            return Some(message);
730        }
731
732        // Empty ready may race with stale activity, so let `refill`
733        // decide whether overflow is worth locking.
734        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    // Live sender count drives receiver disconnect detection.
761    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    // Wake a receiver that is parked waiting for data or disconnect.
769    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        // Prime ready directly to isolate the overflow wake after registration.
1341        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        // SAFETY: `data` was created by `Arc::into_raw` for an `AtomicUsize`
1636        // in `counting_waker` or this function's clone path.
1637        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        // SAFETY: `data` owns one raw `Arc<AtomicUsize>` reference for this
1645        // consuming wake path.
1646        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        // SAFETY: `data` is a borrowed raw `Arc<AtomicUsize>` reference. The
1652        // reference is converted back into raw form before returning.
1653        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        // SAFETY: `data` owns one raw `Arc<AtomicUsize>` reference that should
1660        // be dropped by the waker.
1661        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        // SAFETY: The vtable above reconstructs the same `Arc<AtomicUsize>`
1676        // type and preserves the raw waker reference-counting contract.
1677        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            // Message 2 has already been spilled. Even without cross-sender
2152            // FIFO, later enqueue calls must not bypass retained overflow.
2153            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}