Split Intern::drop
into hot and cold path
This commit is contained in:
parent
afd83e0686
commit
76452956e4
1 changed files with 23 additions and 16 deletions
|
@ -53,19 +53,27 @@ impl<T: Internable> Interned<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Internable + ?Sized> Drop for Interned<T> {
|
impl<T: Internable + ?Sized> Drop for Interned<T> {
|
||||||
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// When the last `Ref` is dropped, remove the object from the global map.
|
// When the last `Ref` is dropped, remove the object from the global map.
|
||||||
if Arc::strong_count(&self.arc) == 2 {
|
if Arc::strong_count(&self.arc) == 2 {
|
||||||
// Only `self` and the global map point to the object.
|
// Only `self` and the global map point to the object.
|
||||||
|
|
||||||
|
self.drop_slow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Internable + ?Sized> Interned<T> {
|
||||||
|
#[cold]
|
||||||
|
fn drop_slow(&mut self) {
|
||||||
let storage = T::storage().get();
|
let storage = T::storage().get();
|
||||||
let shard_idx = storage.determine_map(&self.arc);
|
let shard_idx = storage.determine_map(&self.arc);
|
||||||
let shard = &storage.shards()[shard_idx];
|
let shard = &storage.shards()[shard_idx];
|
||||||
let mut shard = shard.write();
|
let mut shard = shard.write();
|
||||||
|
|
||||||
// FIXME: avoid double lookup
|
// FIXME: avoid double lookup
|
||||||
let (arc, _) =
|
let (arc, _) = shard.get_key_value(&self.arc).expect("interned value removed prematurely");
|
||||||
shard.get_key_value(&self.arc).expect("interned value removed prematurely");
|
|
||||||
|
|
||||||
if Arc::strong_count(arc) != 2 {
|
if Arc::strong_count(arc) != 2 {
|
||||||
// Another thread has interned another copy
|
// Another thread has interned another copy
|
||||||
|
@ -80,7 +88,6 @@ impl<T: Internable + ?Sized> Drop for Interned<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Compares interned `Ref`s using pointer equality.
|
/// Compares interned `Ref`s using pointer equality.
|
||||||
impl<T: Internable + ?Sized> PartialEq for Interned<T> {
|
impl<T: Internable + ?Sized> PartialEq for Interned<T> {
|
||||||
|
|
Loading…
Reference in a new issue