Skip to main content

digdigdig3_station/series/
map.rs

1use std::collections::HashMap;
2use std::sync::Arc;
3
4use tokio::sync::RwLock;
5
6use super::{DataPoint, Series, SeriesKey};
7
8/// `Arc<RwLock<HashMap<Key, Arc<RwLock<Series<T>>>>>>` — MLC dual-read pattern.
9///
10/// Outer RwLock guards the map structure (only locked briefly during
11/// get_or_create). Inner RwLock per-series allows independent reads/writes
12/// across keys without serializing on the map mutex.
13pub struct SharedSeriesMap<T: DataPoint> {
14    inner: Arc<RwLock<HashMap<SeriesKey, Arc<RwLock<Series<T>>>>>>,
15    default_capacity: usize,
16}
17
18impl<T: DataPoint> Clone for SharedSeriesMap<T> {
19    fn clone(&self) -> Self {
20        Self {
21            inner: self.inner.clone(),
22            default_capacity: self.default_capacity,
23        }
24    }
25}
26
27impl<T: DataPoint> SharedSeriesMap<T> {
28    pub fn new(default_capacity: usize) -> Self {
29        Self {
30            inner: Arc::new(RwLock::new(HashMap::new())),
31            default_capacity: default_capacity.max(1),
32        }
33    }
34
35    /// Return existing series or create + insert an empty one.
36    pub async fn get_or_create(&self, key: SeriesKey) -> Arc<RwLock<Series<T>>> {
37        if let Some(s) = self.get(&key).await {
38            return s;
39        }
40        let mut guard = self.inner.write().await;
41        guard
42            .entry(key)
43            .or_insert_with(|| Arc::new(RwLock::new(Series::new(self.default_capacity))))
44            .clone()
45    }
46
47    pub async fn get(&self, key: &SeriesKey) -> Option<Arc<RwLock<Series<T>>>> {
48        self.inner.read().await.get(key).cloned()
49    }
50
51    pub async fn remove(&self, key: &SeriesKey) -> Option<Arc<RwLock<Series<T>>>> {
52        self.inner.write().await.remove(key)
53    }
54
55    pub async fn len(&self) -> usize {
56        self.inner.read().await.len()
57    }
58
59    pub async fn keys(&self) -> Vec<SeriesKey> {
60        self.inner.read().await.keys().cloned().collect()
61    }
62}