Skip to content

Commit a176408

Browse files
committed
Merge branch 'sixteen' of https://github.com/stepancheg/internment into stepancheg-sixteen
2 parents c5df427 + 08000e6 commit a176408

File tree

1 file changed

+77
-5
lines changed

1 file changed

+77
-5
lines changed

src/lib.rs

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,8 @@ use std::sync::atomic::Ordering;
6161
mod container;
6262
use container::{TypeHolder, TypeHolderSend};
6363

64-
use std::any::Any;
65-
#[cfg(feature = "arc")]
6664
use std::any::TypeId;
65+
use std::any::{type_name, Any};
6766
use std::borrow::Borrow;
6867
use std::convert::AsRef;
6968
use std::fmt::{Debug, Display, Pointer};
@@ -195,9 +194,82 @@ where
195194
F: FnOnce(&mut T) -> R,
196195
T: Any + Send + Default,
197196
{
198-
static INTERN_CONTAINERS: Mutex<TypeHolderSend> =
199-
parking_lot::const_mutex(TypeHolderSend::new());
200-
f(INTERN_CONTAINERS.lock().get_type_mut())
197+
// Compute the hash of the type.
198+
fn hash_of_type<T: 'static>() -> u64 {
199+
// We use very simple hasher, because it is optimized away to a constant:
200+
// https://rust.godbolt.org/z/4T1fa4GGs
201+
// which is not true for using `DefaultHasher`:
202+
// https://rust.godbolt.org/z/qKar1WKfz
203+
struct HasherForTypeId {
204+
hash: u64,
205+
}
206+
207+
impl Hasher for HasherForTypeId {
208+
fn write(&mut self, bytes: &[u8]) {
209+
// Hash for type only calls `write_u64` once,
210+
// but handle this case explicitly to make sure
211+
// this code doesn't break if stdlib internals change.
212+
213+
for byte in bytes {
214+
self.hash = self.hash.wrapping_mul(31).wrapping_add(*byte as u64);
215+
}
216+
}
217+
218+
fn write_u64(&mut self, v: u64) {
219+
self.hash = v;
220+
}
221+
222+
fn finish(&self) -> u64 {
223+
self.hash
224+
}
225+
}
226+
227+
let mut hasher = HasherForTypeId { hash: 0 };
228+
TypeId::of::<T>().hash(&mut hasher);
229+
hasher.hash
230+
}
231+
232+
const INTERN_CONTAINER_COUNT: usize = 32;
233+
static INTERN_CONTAINERS: [Mutex<TypeHolderSend>; INTERN_CONTAINER_COUNT] = [
234+
// There's no way to create a static array without copy-paste.
235+
parking_lot::const_mutex(TypeHolderSend::new()),
236+
parking_lot::const_mutex(TypeHolderSend::new()),
237+
parking_lot::const_mutex(TypeHolderSend::new()),
238+
parking_lot::const_mutex(TypeHolderSend::new()),
239+
parking_lot::const_mutex(TypeHolderSend::new()),
240+
parking_lot::const_mutex(TypeHolderSend::new()),
241+
parking_lot::const_mutex(TypeHolderSend::new()),
242+
parking_lot::const_mutex(TypeHolderSend::new()),
243+
parking_lot::const_mutex(TypeHolderSend::new()),
244+
parking_lot::const_mutex(TypeHolderSend::new()),
245+
parking_lot::const_mutex(TypeHolderSend::new()),
246+
parking_lot::const_mutex(TypeHolderSend::new()),
247+
parking_lot::const_mutex(TypeHolderSend::new()),
248+
parking_lot::const_mutex(TypeHolderSend::new()),
249+
parking_lot::const_mutex(TypeHolderSend::new()),
250+
parking_lot::const_mutex(TypeHolderSend::new()),
251+
parking_lot::const_mutex(TypeHolderSend::new()),
252+
parking_lot::const_mutex(TypeHolderSend::new()),
253+
parking_lot::const_mutex(TypeHolderSend::new()),
254+
parking_lot::const_mutex(TypeHolderSend::new()),
255+
parking_lot::const_mutex(TypeHolderSend::new()),
256+
parking_lot::const_mutex(TypeHolderSend::new()),
257+
parking_lot::const_mutex(TypeHolderSend::new()),
258+
parking_lot::const_mutex(TypeHolderSend::new()),
259+
parking_lot::const_mutex(TypeHolderSend::new()),
260+
parking_lot::const_mutex(TypeHolderSend::new()),
261+
parking_lot::const_mutex(TypeHolderSend::new()),
262+
parking_lot::const_mutex(TypeHolderSend::new()),
263+
parking_lot::const_mutex(TypeHolderSend::new()),
264+
parking_lot::const_mutex(TypeHolderSend::new()),
265+
parking_lot::const_mutex(TypeHolderSend::new()),
266+
parking_lot::const_mutex(TypeHolderSend::new()),
267+
];
268+
f(
269+
INTERN_CONTAINERS[hash_of_type::<T>() as usize % INTERN_CONTAINER_COUNT]
270+
.lock()
271+
.get_type_mut(),
272+
)
201273
}
202274

203275
impl<T: Eq + Hash + Send + Sync + 'static> Intern<T> {

0 commit comments

Comments
 (0)