commonware_utils/channel/
ring.rs1use crate::sync::Mutex;
31use core::num::NonZeroUsize;
32use futures::{Sink, Stream, stream::FusedStream};
33use std::{
34 collections::VecDeque,
35 mem,
36 pin::Pin,
37 sync::Arc,
38 task::{Context, Poll, Waker},
39};
40use thiserror::Error;
41
42#[derive(Debug, Error)]
44#[error("channel closed")]
45pub struct ChannelClosed;
46
47#[derive(Debug, Error, PartialEq, Eq)]
49pub enum TryRecvError {
50 #[error("channel empty")]
52 Empty,
53 #[error("channel closed")]
55 Disconnected,
56}
57
58#[derive(Debug)]
63struct Shared<T> {
64 buffer: VecDeque<T>,
65 capacity: usize,
66 receiver_waker: Option<Waker>,
67 sender_count: usize,
68 receiver_dropped: bool,
69}
70
71#[derive(Debug)]
79pub struct Sender<T> {
80 shared: Arc<Mutex<Shared<T>>>,
81}
82
83impl<T> Sender<T> {
84 pub fn is_closed(&self) -> bool {
88 let shared = self.shared.lock();
89 shared.receiver_dropped
90 }
91
92 pub fn send_lossy(&self, item: T) -> bool {
96 let mut shared = self.shared.lock();
97
98 if shared.receiver_dropped {
100 return false;
101 }
102
103 let old_item = if shared.buffer.len() >= shared.capacity {
105 shared.buffer.pop_front()
106 } else {
107 None
108 };
109
110 shared.buffer.push_back(item);
113 let waker = shared.receiver_waker.take();
114 drop(shared);
115
116 drop(old_item);
118
119 if let Some(w) = waker {
121 w.wake();
122 }
123
124 true
125 }
126}
127
128impl<T> Clone for Sender<T> {
129 fn clone(&self) -> Self {
130 let mut shared = self.shared.lock();
131 shared.sender_count += 1;
132 drop(shared);
133
134 Self {
135 shared: self.shared.clone(),
136 }
137 }
138}
139
140impl<T> Drop for Sender<T> {
141 fn drop(&mut self) {
142 let mut shared = self.shared.lock();
143 shared.sender_count -= 1;
144 let waker = if shared.sender_count == 0 {
145 shared.receiver_waker.take()
146 } else {
147 None
148 };
149 drop(shared);
150
151 if let Some(w) = waker {
152 w.wake();
153 }
154 }
155}
156
157impl<T> Sink<T> for Sender<T> {
158 type Error = ChannelClosed;
159
160 fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
161 let shared = self.shared.lock();
162 if shared.receiver_dropped {
163 return Poll::Ready(Err(ChannelClosed));
164 }
165
166 Poll::Ready(Ok(()))
167 }
168
169 fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> {
170 self.send_lossy(item).then_some(()).ok_or(ChannelClosed)
171 }
172
173 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
174 Poll::Ready(Ok(()))
176 }
177
178 fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
179 Poll::Ready(Ok(()))
181 }
182}
183
184#[derive(Debug)]
192pub struct Receiver<T> {
193 shared: Arc<Mutex<Shared<T>>>,
194}
195
196impl<T> Receiver<T> {
197 pub async fn recv(&mut self) -> Option<T> {
199 futures::future::poll_fn(|cx| Pin::new(&mut *self).poll_next(cx)).await
200 }
201
202 pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
204 let mut shared = self.shared.lock();
205 if let Some(item) = shared.buffer.pop_front() {
206 return Ok(item);
207 }
208 if shared.sender_count == 0 {
209 return Err(TryRecvError::Disconnected);
210 }
211 Err(TryRecvError::Empty)
212 }
213}
214
215impl<T> Stream for Receiver<T> {
216 type Item = T;
217
218 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
219 let waker = cx.waker().clone();
221
222 let mut shared = self.shared.lock();
224 if let Some(item) = shared.buffer.pop_front() {
225 return Poll::Ready(Some(item));
226 }
227 if shared.sender_count == 0 {
228 return Poll::Ready(None);
229 }
230
231 let replaced = shared.receiver_waker.replace(waker);
234 drop(shared);
235 drop(replaced);
236 Poll::Pending
237 }
238}
239
240impl<T> FusedStream for Receiver<T> {
241 fn is_terminated(&self) -> bool {
242 let shared = self.shared.lock();
243 shared.sender_count == 0 && shared.buffer.is_empty()
244 }
245}
246
247impl<T> Drop for Receiver<T> {
248 fn drop(&mut self) {
249 let mut shared = self.shared.lock();
250 shared.receiver_dropped = true;
251
252 let buffer = mem::take(&mut shared.buffer);
255 let waker = shared.receiver_waker.take();
256 drop(shared);
257 drop(buffer);
258 drop(waker);
259 }
260}
261
262pub fn channel<T>(capacity: NonZeroUsize) -> (Sender<T>, Receiver<T>) {
267 let shared = Arc::new(Mutex::new(Shared {
268 buffer: VecDeque::with_capacity(capacity.get()),
269 capacity: capacity.get(),
270 receiver_waker: None,
271 sender_count: 1,
272 receiver_dropped: false,
273 }));
274
275 let sender = Sender {
276 shared: shared.clone(),
277 };
278 let receiver = Receiver { shared };
279
280 (sender, receiver)
281}
282
283#[cfg(test)]
284mod tests {
285 use super::*;
286 use crate::NZUsize;
287 use futures::{SinkExt, StreamExt, executor::block_on};
288 use std::{sync::Weak, task::Wake};
289
290 #[test]
291 fn test_basic_send_recv() {
292 block_on(async {
293 let (mut sender, mut receiver) = channel::<i32>(NZUsize!(10));
294
295 sender.send(1).await.unwrap();
296 sender.send(2).await.unwrap();
297 sender.send(3).await.unwrap();
298
299 assert_eq!(receiver.next().await, Some(1));
300 assert_eq!(receiver.next().await, Some(2));
301 assert_eq!(receiver.next().await, Some(3));
302 });
303 }
304
305 #[test]
306 fn test_overflow_drops_oldest() {
307 block_on(async {
308 let (mut sender, mut receiver) = channel::<i32>(NZUsize!(2));
309
310 sender.send(1).await.unwrap();
311 sender.send(2).await.unwrap();
312 sender.send(3).await.unwrap(); sender.send(4).await.unwrap(); assert_eq!(receiver.next().await, Some(3));
316 assert_eq!(receiver.next().await, Some(4));
317 });
318 }
319
320 #[test]
321 fn test_send_after_receiver_dropped() {
322 block_on(async {
323 let (mut sender, receiver) = channel::<i32>(NZUsize!(10));
324 drop(receiver);
325
326 let err = sender.send(1).await.unwrap_err();
327 assert!(matches!(err, ChannelClosed));
328 });
329 }
330
331 #[test]
332 fn test_recv_after_sender_dropped() {
333 block_on(async {
334 let (mut sender, mut receiver) = channel::<i32>(NZUsize!(10));
335
336 sender.send(1).await.unwrap();
337 sender.send(2).await.unwrap();
338 drop(sender);
339
340 assert_eq!(receiver.next().await, Some(1));
341 assert_eq!(receiver.next().await, Some(2));
342 assert_eq!(receiver.next().await, None);
343 });
344 }
345
346 #[test]
347 fn test_stream_collect() {
348 block_on(async {
349 let (mut sender, receiver) = channel::<i32>(NZUsize!(10));
350
351 sender.send(1).await.unwrap();
352 sender.send(2).await.unwrap();
353 sender.send(3).await.unwrap();
354 drop(sender);
355
356 let items: Vec<_> = receiver.collect().await;
357 assert_eq!(items, vec![1, 2, 3]);
358 });
359 }
360
361 #[test]
362 fn test_clone_sender() {
363 block_on(async {
364 let (mut sender1, mut receiver) = channel::<i32>(NZUsize!(10));
365 let mut sender2 = sender1.clone();
366
367 sender1.send(1).await.unwrap();
368 sender2.send(2).await.unwrap();
369
370 assert_eq!(receiver.next().await, Some(1));
371 assert_eq!(receiver.next().await, Some(2));
372 });
373 }
374
375 #[test]
376 fn test_sender_drop_with_clones() {
377 block_on(async {
378 let (sender1, mut receiver) = channel::<i32>(NZUsize!(10));
379 let mut sender2 = sender1.clone();
380
381 drop(sender1);
382
383 sender2.send(1).await.unwrap();
385 assert_eq!(receiver.next().await, Some(1));
386
387 drop(sender2);
388 assert_eq!(receiver.next().await, None);
390 });
391 }
392
393 #[test]
394 fn test_capacity_one() {
395 block_on(async {
396 let (mut sender, mut receiver) = channel::<i32>(NZUsize!(1));
397
398 sender.send(1).await.unwrap();
399 sender.send(2).await.unwrap(); assert_eq!(receiver.next().await, Some(2));
402
403 sender.send(1).await.unwrap();
404 sender.send(2).await.unwrap(); sender.send(3).await.unwrap(); assert_eq!(receiver.next().await, Some(3));
408 });
409 }
410
411 #[test]
412 fn test_send_all() {
413 block_on(async {
414 let (mut sender, receiver) = channel::<i32>(NZUsize!(10));
415
416 let items = futures::stream::iter(vec![1, 2, 3]);
417 sender.send_all(&mut items.map(Ok)).await.unwrap();
418 drop(sender);
419
420 let received: Vec<_> = receiver.collect().await;
421 assert_eq!(received, vec![1, 2, 3]);
422 });
423 }
424
425 #[test]
426 fn test_fused_stream() {
427 use futures::stream::FusedStream;
428
429 block_on(async {
430 let (mut sender, mut receiver) = channel::<i32>(NZUsize!(10));
431
432 assert!(!receiver.is_terminated());
433
434 sender.send(1).await.unwrap();
435 assert!(!receiver.is_terminated());
436
437 drop(sender);
438 assert!(!receiver.is_terminated()); assert_eq!(receiver.next().await, Some(1));
441 assert!(receiver.is_terminated()); assert_eq!(receiver.next().await, None);
445 assert!(receiver.is_terminated());
446 });
447 }
448
449 #[test]
450 fn test_is_closed() {
451 block_on(async {
452 let (sender, receiver) = channel::<i32>(NZUsize!(10));
453
454 assert!(!sender.is_closed());
455
456 drop(receiver);
457 assert!(sender.is_closed());
458 });
459 }
460
461 struct Probe(Option<Sender<Arc<Self>>>);
467
468 impl Probe {
469 fn new(sender: &Sender<Arc<Self>>) -> Arc<Self> {
470 Arc::new(Self(Some(sender.clone())))
471 }
472 }
473
474 #[expect(clippy::manual_noop_waker, reason = "a probe waker must own a sender")]
475 impl Wake for Probe {
476 fn wake(self: Arc<Self>) {}
477 }
478
479 impl Drop for Probe {
480 fn drop(&mut self) {
481 let sender = self.0.take().expect("a probe must still own its sender");
484 if sender.shared.try_lock().is_none() {
485 mem::forget(sender);
486 panic!("senders must be dropped outside the channel lock");
487 }
488 }
489 }
490
491 fn register(sender: &Sender<Arc<Probe>>, receiver: &mut Receiver<Arc<Probe>>) -> Weak<Probe> {
494 let probe = Probe::new(sender);
495 let weak = Arc::downgrade(&probe);
496 let waker = Waker::from(probe);
497 assert!(
498 receiver
499 .poll_next_unpin(&mut Context::from_waker(&waker))
500 .is_pending(),
501 "an empty open channel must be pending"
502 );
503 drop(waker);
504 assert!(
505 weak.upgrade().is_some(),
506 "a pending receiver must register its waker"
507 );
508 weak
509 }
510
511 #[test]
512 fn test_receiver_drop_releases_unread_items() {
513 let (sender, receiver) = channel(NZUsize!(1));
514 let item = Probe::new(&sender);
515 let weak = Arc::downgrade(&item);
516 assert!(sender.send_lossy(item));
517
518 drop(receiver);
519 assert!(
520 weak.upgrade().is_none(),
521 "receiver drop must release unread items"
522 );
523 }
524
525 #[test]
526 fn test_receiver_drop_releases_waker() {
527 let (sender, mut receiver) = channel(NZUsize!(1));
528 let shared = Arc::downgrade(&sender.shared);
529 let waker = register(&sender, &mut receiver);
530
531 drop(receiver);
532 assert!(
533 waker.upgrade().is_none(),
534 "receiver drop must release its waker"
535 );
536
537 drop(sender);
539 assert!(
540 shared.upgrade().is_none(),
541 "the channel must not outlive its handles"
542 );
543 }
544
545 #[test]
546 fn test_replaced_waker_dropped_outside_lock() {
547 let (sender, mut receiver) = channel(NZUsize!(1));
548 let first = register(&sender, &mut receiver);
549
550 let second = register(&sender, &mut receiver);
552 assert!(
553 first.upgrade().is_none(),
554 "a replaced waker must be released"
555 );
556
557 assert!(sender.send_lossy(Probe::new(&sender)));
559 assert!(
560 second.upgrade().is_none(),
561 "a send must consume the registered waker"
562 );
563 assert!(
564 receiver.try_recv().is_ok(),
565 "the channel must deliver after its waker is replaced"
566 );
567 }
568}