Created
September 28, 2021 14:40
-
-
Save AnthonyMikh/346c292d092964a5d8bdf942aa4b6068 to your computer and use it in GitHub Desktop.
Набросок разделяемой между потоками хэшмапы, поддерживающей поиск по предвычисленному хэшу
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use hashbrown::HashMap; | |
use std::{ | |
borrow::Borrow, | |
hash::{BuildHasher, Hash, Hasher}, | |
sync::{Mutex, MutexGuard, PoisonError}, | |
}; | |
pub struct LockedHashMap<K, V, S> { | |
inner: Mutex<HashMap<K, V, S>>, | |
} | |
impl<K, V> LockedHashMap<K, V, hashbrown::hash_map::DefaultHashBuilder> { | |
#[allow(clippy::new_without_default)] | |
pub fn new() -> Self { | |
Self { | |
inner: <_>::default(), | |
} | |
} | |
} | |
impl<K, V, S> LockedHashMap<K, V, S> { | |
pub fn with_hasher(build_hasher: S) -> Self { | |
Self { | |
inner: Mutex::new(HashMap::with_hasher(build_hasher)), | |
} | |
} | |
fn lock_poisonless(&self) -> MutexGuard<'_, HashMap<K, V, S>> { | |
self.inner.lock().unwrap_or_else(PoisonError::into_inner) | |
} | |
pub fn find_with_hash<Q>(&self, hash: u64, key: &Q) -> Option<V> | |
where | |
Q: ?Sized + Eq, | |
K: Borrow<Q> + Hash + Eq, | |
V: Clone, | |
{ | |
self.lock_poisonless() | |
.raw_entry() | |
.from_key_hashed_nocheck(hash, key) | |
.map(|(_k, v)| v.clone()) | |
} | |
pub fn insert(&self, key: K, value: V) -> Option<V> | |
where | |
K: Hash + Eq, | |
S: BuildHasher, | |
{ | |
self.lock_poisonless().insert(key, value) | |
} | |
pub fn insert_with_hash(&self, hash: u64, key: K, value: V) -> Option<V> | |
where | |
K: Hash + Eq, | |
S: BuildHasher, | |
{ | |
use hashbrown::hash_map::RawEntryMut::*; | |
match self | |
.lock_poisonless() | |
.raw_entry_mut() | |
.from_key_hashed_nocheck(hash, &key) | |
{ | |
Vacant(e) => { | |
e.insert(key, value); | |
None | |
} | |
Occupied(mut e) => Some(std::mem::replace(e.get_mut(), value)), | |
} | |
} | |
pub fn hasher(&self) -> S | |
where | |
S: Clone, | |
{ | |
self.lock_poisonless().hasher().clone() | |
} | |
} | |
fn hash_single<T: Hash, S: BuildHasher>(build_hasher: &S, val: &T) -> u64 { | |
let mut hasher = build_hasher.build_hasher(); | |
val.hash(&mut hasher); | |
hasher.finish() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment