use alloc::collections::VecDeque;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::sync::atomic::{AtomicBool, Ordering};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::Mutex as EmbassyMutex;
use embassy_sync::signal::Signal;
pub(crate) type SharedMutex<T> = EmbassyMutex<CriticalSectionRawMutex, T>;
pub(crate) struct OneShot<T> {
signal: Arc<Signal<CriticalSectionRawMutex, T>>,
}
impl<T> OneShot<T> {
pub(crate) fn new() -> Self {
Self {
signal: Arc::new(Signal::new()),
}
}
pub(crate) fn send(&self, value: T) {
self.signal.signal(value);
}
pub(crate) async fn wait(&self) -> T {
self.signal.wait().await
}
}
impl<T> Clone for OneShot<T> {
fn clone(&self) -> Self {
Self {
signal: self.signal.clone(),
}
}
}
struct ChanInner<T> {
queue: SharedMutex<VecDeque<T>>,
signal: Signal<CriticalSectionRawMutex, ()>,
closed: AtomicBool,
}
pub(crate) struct Chan<T> {
inner: Arc<ChanInner<T>>,
}
impl<T> Chan<T> {
pub(crate) fn new() -> Self {
Self {
inner: Arc::new(ChanInner {
queue: SharedMutex::new(VecDeque::new()),
signal: Signal::new(),
closed: AtomicBool::new(false),
}),
}
}
pub(crate) async fn send(&self, value: T) {
{
let mut queue = self.inner.queue.lock().await;
queue.push_back(value);
}
self.inner.signal.signal(());
}
pub(crate) fn close(&self) {
self.inner.closed.store(true, Ordering::SeqCst);
self.inner.signal.signal(());
}
pub(crate) async fn recv(&self) -> Option<T> {
loop {
{
let mut queue = self.inner.queue.lock().await;
if let Some(value) = queue.pop_front() {
return Some(value);
}
if self.inner.closed.load(Ordering::SeqCst) {
return None;
}
}
self.inner.signal.wait().await;
}
}
#[cfg(feature = "test")]
pub(crate) fn is_same(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl<T> Clone for Chan<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
pub(crate) struct Notify {
signal: Arc<Signal<CriticalSectionRawMutex, ()>>,
}
impl Notify {
pub(crate) fn new() -> Self {
Self {
signal: Arc::new(Signal::new()),
}
}
pub(crate) fn notify(&self) {
self.signal.signal(());
}
pub(crate) async fn wait(&self) {
self.signal.wait().await
}
}
impl Clone for Notify {
fn clone(&self) -> Self {
Self {
signal: self.signal.clone(),
}
}
}
pub(crate) struct BroadcastRegistry {
subscribers: SharedMutex<Vec<Arc<Signal<CriticalSectionRawMutex, ()>>>>,
}
impl BroadcastRegistry {
pub(crate) fn new() -> Self {
Self {
subscribers: SharedMutex::new(Vec::new()),
}
}
pub(crate) async fn subscribe(&self) -> Arc<Signal<CriticalSectionRawMutex, ()>> {
let signal = Arc::new(Signal::new());
let mut subscribers = self.subscribers.lock().await;
subscribers.push(signal.clone());
signal
}
pub(crate) async fn notify_all(&self) {
let subscribers = self.subscribers.lock().await;
for signal in subscribers.iter() {
signal.signal(());
}
}
}