mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Change Map::get_or_insert_with to Map::entry
This commit is contained in:
parent
306e8ac5f9
commit
1c2de5641c
2 changed files with 66 additions and 46 deletions
|
@ -13,11 +13,10 @@ use smallvec::SmallVec;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash;
|
use std::hash;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::mem;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
||||||
|
|
||||||
use super::map::Map;
|
use super::map::{Entry, Map};
|
||||||
use super::unsafe_box::UnsafeBox;
|
use super::unsafe_box::UnsafeBox;
|
||||||
use super::{CascadeLevel, StyleSource};
|
use super::{CascadeLevel, StyleSource};
|
||||||
|
|
||||||
|
@ -402,33 +401,21 @@ impl StrongRuleNode {
|
||||||
return child.upgrade();
|
return child.upgrade();
|
||||||
}
|
}
|
||||||
let mut children = RwLockUpgradableReadGuard::upgrade(children);
|
let mut children = RwLockUpgradableReadGuard::upgrade(children);
|
||||||
let mut is_new = false;
|
match children.entry(key, |node| node.p.key()) {
|
||||||
let weak = {
|
Entry::Occupied(child) => {
|
||||||
let is_new = &mut is_new;
|
child.upgrade()
|
||||||
children.get_or_insert_with(
|
},
|
||||||
key,
|
Entry::Vacant(entry) => {
|
||||||
|node| node.p.key(),
|
let node = StrongRuleNode::new(Box::new(RuleNode::new(
|
||||||
move || {
|
unsafe { root.downgrade() },
|
||||||
*is_new = true;
|
self.clone(),
|
||||||
let root = unsafe { root.downgrade() };
|
source,
|
||||||
let strong = StrongRuleNode::new(Box::new(RuleNode::new(
|
level,
|
||||||
root,
|
)));
|
||||||
self.clone(),
|
entry.insert(unsafe { node.downgrade() });
|
||||||
source,
|
node
|
||||||
level,
|
},
|
||||||
)));
|
|
||||||
let weak = unsafe { strong.downgrade() };
|
|
||||||
mem::forget(strong);
|
|
||||||
weak
|
|
||||||
},
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if !is_new {
|
|
||||||
return weak.upgrade();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { StrongRuleNode::from_unsafe_box(UnsafeBox::clone(&weak.p)) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the style source corresponding to this rule node. May return `None`
|
/// Get the style source corresponding to this rule node. May return `None`
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
|
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
|
||||||
|
use std::collections::hash_map;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -28,6 +29,20 @@ enum MapIterInner<'a, K, V> {
|
||||||
Map(std::collections::hash_map::Values<'a, K, V>),
|
Map(std::collections::hash_map::Values<'a, K, V>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) enum Entry<'a, K, V> {
|
||||||
|
Occupied(&'a mut V),
|
||||||
|
Vacant(VacantEntry<'a, K, V>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct VacantEntry<'a, K, V> {
|
||||||
|
inner: VacantEntryInner<'a, K, V>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VacantEntryInner<'a, K, V> {
|
||||||
|
One(&'a mut MapInner<K, V>),
|
||||||
|
Map(hash_map::VacantEntry<'a, K, V>),
|
||||||
|
}
|
||||||
|
|
||||||
impl<K, V> Default for Map<K, V> {
|
impl<K, V> Default for Map<K, V> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Map {
|
Map {
|
||||||
|
@ -91,20 +106,15 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_or_insert_with(
|
pub(super) fn entry(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: K,
|
key: K,
|
||||||
key_from_value: impl FnOnce(&V) -> K,
|
key_from_value: impl FnOnce(&V) -> K,
|
||||||
new_value: impl FnOnce() -> V,
|
) -> Entry<'_, K, V> {
|
||||||
) -> &mut V {
|
|
||||||
match self.inner {
|
match self.inner {
|
||||||
MapInner::Empty => {
|
ref mut inner @ MapInner::Empty => Entry::Vacant(VacantEntry {
|
||||||
self.inner = MapInner::One(new_value());
|
inner: VacantEntryInner::One(inner),
|
||||||
match &mut self.inner {
|
}),
|
||||||
MapInner::One(one) => one,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MapInner::One(_) => {
|
MapInner::One(_) => {
|
||||||
let one = match mem::replace(&mut self.inner, MapInner::Empty) {
|
let one = match mem::replace(&mut self.inner, MapInner::Empty) {
|
||||||
MapInner::One(one) => one,
|
MapInner::One(one) => one,
|
||||||
|
@ -115,10 +125,11 @@ where
|
||||||
// Same for the equality test.
|
// Same for the equality test.
|
||||||
if key == one_key {
|
if key == one_key {
|
||||||
self.inner = MapInner::One(one);
|
self.inner = MapInner::One(one);
|
||||||
match &mut self.inner {
|
let one = match &mut self.inner {
|
||||||
MapInner::One(one) => return one,
|
MapInner::One(one) => one,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
};
|
||||||
|
return Entry::Occupied(one);
|
||||||
}
|
}
|
||||||
self.inner = MapInner::Map(Box::new(FxHashMap::with_capacity_and_hasher(
|
self.inner = MapInner::Map(Box::new(FxHashMap::with_capacity_and_hasher(
|
||||||
2,
|
2,
|
||||||
|
@ -129,12 +140,19 @@ where
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
map.insert(one_key, one);
|
map.insert(one_key, one);
|
||||||
// But it doesn't matter if f panics, by this point
|
match map.entry(key) {
|
||||||
// the map is as before but represented as a map instead
|
hash_map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry {
|
||||||
// of a single value.
|
inner: VacantEntryInner::Map(entry),
|
||||||
map.entry(key).or_insert_with(new_value)
|
}),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MapInner::Map(ref mut map) => match map.entry(key) {
|
||||||
|
hash_map::Entry::Occupied(entry) => Entry::Occupied(entry.into_mut()),
|
||||||
|
hash_map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry {
|
||||||
|
inner: VacantEntryInner::Map(entry),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
MapInner::Map(ref mut map) => map.entry(key).or_insert_with(new_value),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +170,21 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, K, V> VacantEntry<'a, K, V> {
|
||||||
|
pub(super) fn insert(self, value: V) -> &'a mut V {
|
||||||
|
match self.inner {
|
||||||
|
VacantEntryInner::One(map) => {
|
||||||
|
*map = MapInner::One(value);
|
||||||
|
match map {
|
||||||
|
MapInner::One(one) => one,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
VacantEntryInner::Map(entry) => entry.insert(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<K, V> MallocShallowSizeOf for Map<K, V>
|
impl<K, V> MallocShallowSizeOf for Map<K, V>
|
||||||
where
|
where
|
||||||
K: Eq + Hash,
|
K: Eq + Hash,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue