Merge pull request #160 from mscofield0/master

Add "alter" variation but for immutable borrows
This commit is contained in:
Joel 2021-12-12 17:56:04 +01:00 committed by GitHub
commit fde71253ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 0 deletions

View File

@ -578,6 +578,33 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
self._alter_all(f);
}
/// Scoped access into an item of the map according to a function.
///
/// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
///
/// # Examples
///
/// ```
/// use dashmap::DashMap;
///
/// let warehouse = DashMap::new();
/// warehouse.insert(4267, ("Banana", 100));
/// warehouse.insert(2359, ("Pear", 120));
/// let fruit = warehouse.view(&4267, |_k, v| *v);
/// assert_eq!(fruit, Some(("Banana", 100)));
/// ```
///
/// # Panics
///
/// If the given closure panics, then `view` will abort the process
pub fn view<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self._view(key, f)
}
/// Checks if the map contains a specific key.
///
/// **Locking behaviour:** May deadlock if called when holding a mutable reference into the map.
@ -773,6 +800,17 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
});
}
fn _view<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.get(key).map(|r| {
let (k, v) = r.pair();
f(k, v)
})
}
fn _entry(&'a self, key: K) -> Entry<'a, K, V, S> {
let hash = self.hash_usize(&key);
@ -990,4 +1028,42 @@ mod tests {
assert_eq!(i, *dm_hm_default.get(&i).unwrap().value());
}
}
#[test]
fn test_map_view() {
let dm = DashMap::new();
let vegetables: [String; 4] = [
"Salad".to_string(),
"Beans".to_string(),
"Potato".to_string(),
"Tomato".to_string(),
];
// Give it some values
dm.insert(0, "Banana".to_string());
dm.insert(4, "Pear".to_string());
dm.insert(9, "Potato".to_string());
dm.insert(12, "Chicken".to_string());
let potato_vegetableness = dm.view(&9, |_, v| {
let is_vegetable = vegetables.contains(v);
is_vegetable
});
assert_eq!(potato_vegetableness, Some(true));
let chicken_vegetableness = dm.view(&12, |_, v| {
let is_vegetable = vegetables.contains(v);
is_vegetable
});
assert_eq!(chicken_vegetableness, Some(false));
let not_in_map = dm.view(&30, |_k, _v| false);
assert_eq!(not_in_map, None);
}
}

View File

@ -72,6 +72,11 @@ pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> {
fn _alter_all(&self, f: impl FnMut(&K, V) -> V);
fn _view<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized;
fn _entry(&'a self, key: K) -> Entry<'a, K, V, S>;
fn _hasher(&self) -> S;