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)]
 | 
			
		||||
use crate::intern::type_map::TypeIdMap;
 | 
			
		||||
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 std::{
 | 
			
		||||
    any::{Any, TypeId},
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ use std::{
 | 
			
		|||
    sync::{Mutex, RwLock},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub mod type_map;
 | 
			
		||||
mod type_map;
 | 
			
		||||
 | 
			
		||||
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
 | 
			
		||||
    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> {
 | 
			
		||||
    map: Mutex<HashMap<&'static T, ()>>,
 | 
			
		||||
    state: Mutex<InternerState<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> {
 | 
			
		||||
    fn default() -> 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,
 | 
			
		||||
        value: Cow<'_, T>,
 | 
			
		||||
    ) -> Interned<T> {
 | 
			
		||||
        let mut map = self.map.lock().unwrap();
 | 
			
		||||
        let hasher = map.hasher().clone();
 | 
			
		||||
        let hash = hasher.hash_one(&*value);
 | 
			
		||||
        let inner = match map.raw_entry_mut().from_hash(hash, |k| **k == *value) {
 | 
			
		||||
            RawEntryMut::Occupied(entry) => *entry.key(),
 | 
			
		||||
            RawEntryMut::Vacant(entry) => {
 | 
			
		||||
                *entry
 | 
			
		||||
                    .insert_with_hasher(hash, alloc(value), (), |k| hasher.hash_one(&**k))
 | 
			
		||||
                    .0
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        let mut state = self.state.lock().unwrap();
 | 
			
		||||
        let InternerState { table, hasher } = &mut *state;
 | 
			
		||||
        let inner = *table
 | 
			
		||||
            .entry(
 | 
			
		||||
                hasher.hash_one(&*value),
 | 
			
		||||
                |k| **k == *value,
 | 
			
		||||
                |k| hasher.hash_one(&**k),
 | 
			
		||||
            )
 | 
			
		||||
            .or_insert_with(|| alloc(value))
 | 
			
		||||
            .get();
 | 
			
		||||
        Interned { inner }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -742,7 +749,7 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy {
 | 
			
		|||
    fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
 | 
			
		||||
        static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
 | 
			
		||||
        let map: &RwLock<(
 | 
			
		||||
            hashbrown::hash_map::DefaultHashBuilder,
 | 
			
		||||
            DefaultBuildHasher,
 | 
			
		||||
            HashTable<(Self, Self::InputOwned, Self::Output)>,
 | 
			
		||||
        )> = TYPE_ID_MAP.get_or_insert_default();
 | 
			
		||||
        fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue