use std::collections::HashMap;
use std::sync::{Arc, PoisonError, RwLock};
use crate::state::ChunkCollector;
pub struct ChunkCollectorStore {
pub inner: Arc<RwLock<HashMap<usize, Vec<Option<ChunkCollector>>>>>,
}
impl ChunkCollectorStore {
pub fn new() -> Self {
Self { inner: Arc::new(RwLock::new(HashMap::new())) }
}
pub fn reset(&self) {
self.inner.write().unwrap_or_else(PoisonError::into_inner).clear();
}
#[cfg(test)]
pub fn is_empty(&self) -> bool {
self.inner.read().map(|g| g.is_empty()).unwrap_or(true)
}
}
impl Default for ChunkCollectorStore {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_is_empty() {
let store = ChunkCollectorStore::new();
assert!(store.is_empty());
}
#[test]
fn default_matches_new() {
let store = ChunkCollectorStore::default();
assert!(store.is_empty());
}
#[test]
fn reset_clears_map() {
let store = ChunkCollectorStore::new();
store.inner.write().unwrap().insert(7, vec![None, None]);
assert!(!store.is_empty());
store.reset();
assert!(store.is_empty());
}
#[test]
fn reset_recovers_from_poisoned_inner() {
use std::panic::{catch_unwind, AssertUnwindSafe};
let store = Arc::new(ChunkCollectorStore::new());
let store_for_panic = store.clone();
let _ = catch_unwind(AssertUnwindSafe(|| {
let _guard = store_for_panic.inner.write().unwrap();
panic!("intentional poison");
}));
assert!(store.inner.is_poisoned());
store.reset();
assert!(store.is_empty());
}
}