forked from libre-chip/fayalite
move Interner into new mod interner
This commit is contained in:
parent
26b0dc3fd8
commit
39810043ea
2 changed files with 91 additions and 76 deletions
|
|
@ -16,9 +16,10 @@ use std::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{Mutex, RwLock},
|
sync::RwLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod interner;
|
||||||
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 {
|
||||||
|
|
@ -593,78 +594,6 @@ impl<T: ?Sized + 'static + Send + Sync + ToOwned> From<Interned<T>> for Cow<'_,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InternerState<T: ?Sized + 'static + Send + Sync> {
|
|
||||||
table: HashTable<&'static T>,
|
|
||||||
hasher: DefaultBuildHasher,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct Interner<T: ?Sized + 'static + Send + Sync> {
|
|
||||||
state: Mutex<InternerState<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
|
||||||
fn get() -> &'static Interner<T> {
|
|
||||||
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
|
|
||||||
thread_local! {
|
|
||||||
static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() };
|
|
||||||
}
|
|
||||||
TYPE_ID_MAP_CACHE.with(|cache| {
|
|
||||||
cache.get_or_insert_with(|| {
|
|
||||||
TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default()))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
state: Mutex::new(InternerState {
|
|
||||||
table: HashTable::new(),
|
|
||||||
hasher: Default::default(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
|
|
||||||
fn intern<F: FnOnce(Cow<'_, T>) -> &'static T>(
|
|
||||||
&self,
|
|
||||||
alloc: F,
|
|
||||||
value: Cow<'_, T>,
|
|
||||||
) -> Interned<T> {
|
|
||||||
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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<T> {
|
|
||||||
fn intern_sized(&self, value: Cow<'_, T>) -> Interned<T> {
|
|
||||||
self.intern(|value| Box::leak(Box::new(value.into_owned())), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<[T]> {
|
|
||||||
fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> {
|
|
||||||
self.intern(|value| value.into_owned().leak(), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Interner<BitSlice> {
|
|
||||||
fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned<BitSlice> {
|
|
||||||
self.intern(|value| value.into_owned().leak(), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||||
inner: &'static T,
|
inner: &'static T,
|
||||||
}
|
}
|
||||||
|
|
@ -984,7 +913,7 @@ impl<T: Clone + Send + Sync + 'static + Hash + Eq> Intern for T {
|
||||||
where
|
where
|
||||||
Self: ToOwned,
|
Self: ToOwned,
|
||||||
{
|
{
|
||||||
Interner::get().intern_sized(this)
|
interner::Interner::get().intern_sized(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1004,7 +933,7 @@ impl<T: Clone + Send + Sync + 'static + Hash + Eq> Intern for [T] {
|
||||||
where
|
where
|
||||||
Self: ToOwned,
|
Self: ToOwned,
|
||||||
{
|
{
|
||||||
Interner::get().intern_slice(this)
|
interner::Interner::get().intern_slice(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1024,7 +953,7 @@ impl Intern for BitSlice {
|
||||||
where
|
where
|
||||||
Self: ToOwned,
|
Self: ToOwned,
|
||||||
{
|
{
|
||||||
Interner::get().intern_bit_slice(this)
|
interner::Interner::get().intern_bit_slice(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
86
crates/fayalite/src/intern/interner.rs
Normal file
86
crates/fayalite/src/intern/interner.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
intern::{Interned, type_map::TypeIdMap},
|
||||||
|
util::DefaultBuildHasher,
|
||||||
|
};
|
||||||
|
use bitvec::slice::BitSlice;
|
||||||
|
use hashbrown::HashTable;
|
||||||
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
hash::{BuildHasher, Hash},
|
||||||
|
sync::Mutex,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InternerState<T: ?Sized + 'static + Send + Sync> {
|
||||||
|
table: HashTable<&'static T>,
|
||||||
|
hasher: DefaultBuildHasher,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct Interner<T: ?Sized + 'static + Send + Sync> {
|
||||||
|
state: Mutex<InternerState<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
||||||
|
pub(crate) fn get() -> &'static Interner<T> {
|
||||||
|
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
|
||||||
|
thread_local! {
|
||||||
|
static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() };
|
||||||
|
}
|
||||||
|
TYPE_ID_MAP_CACHE.with(|cache| {
|
||||||
|
cache.get_or_insert_with(|| {
|
||||||
|
TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
state: Mutex::new(InternerState {
|
||||||
|
table: HashTable::new(),
|
||||||
|
hasher: Default::default(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
|
||||||
|
fn intern<F: FnOnce(Cow<'_, T>) -> &'static T>(
|
||||||
|
&self,
|
||||||
|
alloc: F,
|
||||||
|
value: Cow<'_, T>,
|
||||||
|
) -> Interned<T> {
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<T> {
|
||||||
|
pub(crate) fn intern_sized(&self, value: Cow<'_, T>) -> Interned<T> {
|
||||||
|
self.intern(|value| Box::leak(Box::new(value.into_owned())), value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<[T]> {
|
||||||
|
pub(crate) fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> {
|
||||||
|
self.intern(|value| value.into_owned().leak(), value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interner<BitSlice> {
|
||||||
|
pub(crate) fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned<BitSlice> {
|
||||||
|
self.intern(|value| value.into_owned().leak(), value)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue