forked from libre-chip/fayalite
switch interning to use HashTable rather than HashMap
This commit is contained in:
parent
36f1b9bbb6
commit
07725ab489
1 changed files with 23 additions and 16 deletions
|
@ -3,7 +3,7 @@
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
use crate::intern::type_map::TypeIdMap;
|
use crate::intern::type_map::TypeIdMap;
|
||||||
use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec};
|
use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec};
|
||||||
use hashbrown::{hash_map::RawEntryMut, HashMap, HashTable};
|
use hashbrown::{HashTable, hash_map::DefaultHashBuilder as DefaultBuildHasher};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
|
@ -17,7 +17,7 @@ use std::{
|
||||||
sync::{Mutex, RwLock},
|
sync::{Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod type_map;
|
mod type_map;
|
||||||
|
|
||||||
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
|
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
|
||||||
fn get(&self) -> Interned<T>;
|
fn get(&self) -> Interned<T>;
|
||||||
|
@ -316,8 +316,13 @@ pub trait Intern: Any + Send + Sync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InternerState<T: ?Sized + 'static + Send + Sync> {
|
||||||
|
table: HashTable<&'static T>,
|
||||||
|
hasher: DefaultBuildHasher,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Interner<T: ?Sized + 'static + Send + Sync> {
|
pub struct Interner<T: ?Sized + 'static + Send + Sync> {
|
||||||
map: Mutex<HashMap<&'static T, ()>>,
|
state: Mutex<InternerState<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
||||||
|
@ -330,7 +335,10 @@ impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
||||||
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: Default::default(),
|
state: Mutex::new(InternerState {
|
||||||
|
table: HashTable::new(),
|
||||||
|
hasher: Default::default(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,17 +349,16 @@ impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
|
||||||
alloc: F,
|
alloc: F,
|
||||||
value: Cow<'_, T>,
|
value: Cow<'_, T>,
|
||||||
) -> Interned<T> {
|
) -> Interned<T> {
|
||||||
let mut map = self.map.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
let hasher = map.hasher().clone();
|
let InternerState { table, hasher } = &mut *state;
|
||||||
let hash = hasher.hash_one(&*value);
|
let inner = *table
|
||||||
let inner = match map.raw_entry_mut().from_hash(hash, |k| **k == *value) {
|
.entry(
|
||||||
RawEntryMut::Occupied(entry) => *entry.key(),
|
hasher.hash_one(&*value),
|
||||||
RawEntryMut::Vacant(entry) => {
|
|k| **k == *value,
|
||||||
*entry
|
|k| hasher.hash_one(&**k),
|
||||||
.insert_with_hasher(hash, alloc(value), (), |k| hasher.hash_one(&**k))
|
)
|
||||||
.0
|
.or_insert_with(|| alloc(value))
|
||||||
}
|
.get();
|
||||||
};
|
|
||||||
Interned { inner }
|
Interned { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -742,7 +749,7 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy {
|
||||||
fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
|
fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
|
||||||
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
|
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
|
||||||
let map: &RwLock<(
|
let map: &RwLock<(
|
||||||
hashbrown::hash_map::DefaultHashBuilder,
|
DefaultBuildHasher,
|
||||||
HashTable<(Self, Self::InputOwned, Self::Output)>,
|
HashTable<(Self, Self::InputOwned, Self::Output)>,
|
||||||
)> = TYPE_ID_MAP.get_or_insert_default();
|
)> = TYPE_ID_MAP.get_or_insert_default();
|
||||||
fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
|
fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue