// Copyright 2025 System76 // SPDX-License-Identifier: MPL-2.0 use std::{ collections::VecDeque, sync::{ Arc, Mutex, atomic::{AtomicBool, Ordering}, }, }; /// Create a channel backed by `tokio::sync::Notify` and a sync mutex with a vec deque. pub fn channel() -> (Sender, Receiver) { let channel = Arc::new(Channel { queue: Mutex::new(VecDeque::default()), notify: tokio::sync::Notify::const_new(), closed: AtomicBool::new(false), }); (Sender(channel.clone()), Receiver(channel)) } /// A channel backed by `tokio::sync::Notify` and a sync mutex with a vec deque. struct Channel { pub(self) queue: Mutex>, /// Set when a new message has been stored. pub(self) notify: tokio::sync::Notify, /// Set when the receiver is dropped. pub(self) closed: AtomicBool, } pub struct Sender(Arc>); impl Sender { pub fn send(&self, message: Message) { self.0.queue.lock().unwrap().push_back(message); self.0.notify.notify_one(); } } impl Drop for Sender { fn drop(&mut self) { self.0.closed.store(true, Ordering::SeqCst); self.0.notify.notify_one(); } } pub struct Receiver(Arc>); impl Receiver { /// Returns a value until the sender is dropped. pub async fn recv(&self) -> Option { loop { { let mut queue = self.0.queue.lock().unwrap(); if let Some(value) = queue.pop_front() { if queue.capacity() - queue.len() > 32 { let capacity = queue.len().next_power_of_two(); queue.shrink_to(capacity); } drop(queue); return Some(value); } } if self.0.closed.load(Ordering::SeqCst) { return None; } self.0.notify.notified().await; } } pub fn try_recv(&self) -> Option { self.0.queue.lock().unwrap().pop_front() } }