vortex_array/
arc_swap_map.rs1use std::borrow::Borrow;
7use std::fmt::Debug;
8use std::fmt::Formatter;
9use std::hash::Hash;
10use std::sync::Arc;
11
12use arc_swap::ArcSwap;
13use vortex_utils::aliases::hash_map::HashMap;
14
15pub struct ArcSwapMap<K, V> {
32 inner: Arc<ArcSwap<HashMap<K, V>>>,
33}
34
35impl<K, V> Default for ArcSwapMap<K, V> {
36 fn default() -> Self {
37 Self {
38 inner: Arc::new(ArcSwap::from_pointee(HashMap::default())),
39 }
40 }
41}
42
43impl<K, V> Clone for ArcSwapMap<K, V> {
44 fn clone(&self) -> Self {
45 Self {
46 inner: Arc::clone(&self.inner),
47 }
48 }
49}
50
51impl<K: Debug, V: Debug> Debug for ArcSwapMap<K, V> {
52 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53 self.read(|map| f.debug_tuple("ArcSwapMap").field(map).finish())
54 }
55}
56
57impl<K, V> ArcSwapMap<K, V> {
58 pub fn snapshot(&self) -> Arc<HashMap<K, V>> {
60 self.inner.load_full()
61 }
62
63 pub fn read<R>(&self, f: impl FnOnce(&HashMap<K, V>) -> R) -> R {
68 f(&self.inner.load())
69 }
70
71 fn modify(&self, f: impl Fn(&mut HashMap<K, V>))
76 where
77 K: Clone,
78 V: Clone,
79 {
80 self.inner.rcu(|existing| {
81 let mut map = existing.as_ref().clone();
82 f(&mut map);
83 map
84 });
85 }
86}
87
88impl<K: Eq + Hash, V: Clone> ArcSwapMap<K, V> {
89 pub fn get<Q>(&self, key: &Q) -> Option<V>
91 where
92 K: Borrow<Q>,
93 Q: Eq + Hash + ?Sized,
94 {
95 self.inner.load().get(key).cloned()
96 }
97
98 pub fn insert(&self, key: K, value: V)
100 where
101 K: Clone,
102 {
103 self.modify(|map| {
104 map.insert(key.clone(), value.clone());
105 });
106 }
107}
108
109impl<K: Eq + Hash + Clone, T: Clone> ArcSwapMap<K, Arc<[T]>> {
110 pub fn extend(&self, key: K, values: &[T]) {
115 self.modify(|map| {
116 let merged: Arc<[T]> = match map.get(&key) {
117 Some(existing) => existing.iter().chain(values).cloned().collect(),
118 None => values.into(),
119 };
120 map.insert(key.clone(), merged);
121 });
122 }
123
124 pub fn push(&self, key: K, value: T) {
127 self.extend(key, &[value]);
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn get_and_insert() {
137 let map = ArcSwapMap::<u32, i32>::default();
138 assert_eq!(map.get(&1), None);
139 map.insert(1, 10);
140 map.insert(1, 20);
141 assert_eq!(map.get(&1), Some(20));
142 }
143
144 #[test]
145 fn extend_appends_per_key() {
146 let map = ArcSwapMap::<u32, Arc<[i32]>>::default();
147 map.extend(1, &[1, 2]);
148 map.extend(1, &[3]);
149 map.extend(2, &[4]);
150 assert_eq!(map.get(&1).as_deref(), Some([1, 2, 3].as_slice()));
151 assert_eq!(map.get(&2).as_deref(), Some([4].as_slice()));
152 }
153
154 #[test]
155 fn push_appends_single_values() {
156 let map = ArcSwapMap::<u32, Arc<[i32]>>::default();
157 map.push(1, 1);
158 map.push(1, 2);
159 assert_eq!(map.get(&1).as_deref(), Some([1, 2].as_slice()));
160 }
161
162 #[test]
163 fn read_observes_a_single_snapshot() {
164 let map = ArcSwapMap::<u32, i32>::default();
165 map.insert(1, 1);
166 map.insert(2, 2);
167 assert_eq!(map.read(|m| m.values().sum::<i32>()), 3);
168 }
169
170 #[test]
171 fn snapshot_keeps_published_view() {
172 let map = ArcSwapMap::<u32, i32>::default();
173 map.insert(1, 10);
174
175 let snapshot = map.snapshot();
176 map.insert(1, 20);
177 map.insert(2, 30);
178
179 assert_eq!(snapshot.get(&1), Some(&10));
180 assert_eq!(snapshot.get(&2), None);
181 assert_eq!(map.get(&1), Some(20));
182 assert_eq!(map.get(&2), Some(30));
183 }
184
185 #[test]
186 fn clone_shares_the_same_cell() {
187 let map = ArcSwapMap::<u32, i32>::default();
188 let clone = map.clone();
189 map.insert(1, 10);
191 assert_eq!(clone.get(&1), Some(10));
192 clone.insert(2, 20);
193 assert_eq!(map.get(&2), Some(20));
194 }
195}