Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Created September 28, 2021 14:40
Show Gist options
  • Save AnthonyMikh/346c292d092964a5d8bdf942aa4b6068 to your computer and use it in GitHub Desktop.
Save AnthonyMikh/346c292d092964a5d8bdf942aa4b6068 to your computer and use it in GitHub Desktop.
Набросок разделяемой между потоками хэшмапы, поддерживающей поиск по предвычисленному хэшу
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