use std::cell::{Cell, RefCell}; #[derive(Debug)] pub struct ConcurrentQueue { queue: RefCell>, closed: Cell, } pub enum PushError { #[allow(dead_code)] Full(T), Closed(T), } pub enum PopError { Empty, Closed, } impl ConcurrentQueue { pub fn unbounded() -> Self { Self { queue: RefCell::new(Vec::new()), closed: Cell::new(false) } } pub fn push(&self, value: T) -> Result<(), PushError> { if self.closed.get() { return Err(PushError::Closed(value)); } self.queue.borrow_mut().push(value); Ok(()) } pub fn pop(&self) -> Result { self.queue.borrow_mut().pop().ok_or_else(|| { if self.closed.get() { PopError::Closed } else { PopError::Empty } }) } pub fn close(&self) -> bool { !self.closed.replace(true) } } // SAFETY: Wasm without the `atomics` target feature is single-threaded. unsafe impl Send for ConcurrentQueue {} // SAFETY: Wasm without the `atomics` target feature is single-threaded. unsafe impl Sync for ConcurrentQueue {}