use std::sync::{Arc, RwLock, RwLockReadGuard};
use super::IElementProcessor;
#[derive(Default)]
pub struct ElementProcessorSet {
entries: Vec<Option<Arc<dyn IElementProcessor>>>,
}
impl ElementProcessorSet {
#[must_use]
pub const fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn insert(&mut self, processor: Option<Arc<dyn IElementProcessor>>) -> bool {
let duplicate = self
.entries
.iter()
.any(|existing| match (&processor, existing) {
(None, None) => true,
(Some(left), Some(right)) => Arc::ptr_eq(left, right),
_ => false,
});
if duplicate {
return false;
}
self.entries.push(processor);
true
}
#[must_use]
pub fn len(&self) -> usize {
self.entries.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn iter(&self) -> impl ExactSizeIterator<Item = Option<&Arc<dyn IElementProcessor>>> {
self.entries.iter().map(Option::as_ref)
}
}
pub struct UnmodifiableElementProcessorSet {
source: Arc<RwLock<ElementProcessorSet>>,
}
impl UnmodifiableElementProcessorSet {
pub(crate) fn new(source: Arc<RwLock<ElementProcessorSet>>) -> Self {
Self { source }
}
#[must_use]
pub fn len(&self) -> usize {
read_recovering_poison(&self.source).len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
read_recovering_poison(&self.source).is_empty()
}
#[must_use]
pub fn snapshot(&self) -> Vec<Option<Arc<dyn IElementProcessor>>> {
read_recovering_poison(&self.source)
.iter()
.map(|value| value.cloned())
.collect()
}
}
pub(crate) fn read_set(
source: &RwLock<ElementProcessorSet>,
) -> RwLockReadGuard<'_, ElementProcessorSet> {
read_recovering_poison(source)
}
fn read_recovering_poison<T>(lock: &RwLock<T>) -> RwLockReadGuard<'_, T> {
lock.read()
.unwrap_or_else(std::sync::PoisonError::into_inner)
}