use std::collections::VecDeque;
use sim_kernel::{Error, Result};
use sim_lib_stream_core::StreamStats;
use crate::{LiveAudioEvent, LiveControlEvent, LiveQueuePush};
pub type ControlToAudioQueue = BoundedLiveQueue<LiveControlEvent>;
pub type AudioToControlQueue = BoundedLiveQueue<LiveAudioEvent>;
#[derive(Clone, Debug)]
pub struct BoundedLiveQueue<T> {
entries: VecDeque<T>,
bound: usize,
pending_dropped_newest: u64,
stats: StreamStats,
}
impl<T> BoundedLiveQueue<T> {
pub fn with_capacity(bound: usize) -> Result<Self> {
if bound == 0 {
return Err(Error::Eval(
"live queue capacity must be greater than zero".to_owned(),
));
}
Ok(Self {
entries: VecDeque::with_capacity(bound),
bound,
pending_dropped_newest: 0,
stats: StreamStats::default(),
})
}
pub fn push(&mut self, item: T) -> LiveQueuePush {
self.stats.pushed = self.stats.pushed.saturating_add(1);
if self.entries.len() >= self.bound {
self.pending_dropped_newest = self.pending_dropped_newest.saturating_add(1);
self.stats.dropped_newest = self.stats.dropped_newest.saturating_add(1);
LiveQueuePush::DroppedNewest
} else {
self.entries.push_back(item);
self.stats.accepted = self.stats.accepted.saturating_add(1);
LiveQueuePush::Accepted
}
}
pub fn pop(&mut self) -> Option<T> {
let item = self.entries.pop_front();
if item.is_some() {
self.stats.yielded = self.stats.yielded.saturating_add(1);
}
item
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn capacity(&self) -> usize {
self.bound
}
pub fn allocated_capacity(&self) -> usize {
self.entries.capacity()
}
pub fn dropped(&self) -> u64 {
self.pending_dropped_newest
}
pub fn take_dropped(&mut self) -> u64 {
let dropped = self.pending_dropped_newest;
self.pending_dropped_newest = 0;
dropped
}
pub fn stats(&self) -> StreamStats {
self.stats.clone()
}
}