Skip to content

Commit f8bae8b

Browse files
authored
Rollup merge of #78056 - ssomers:btree_chop_up_1, r=dtolnay
BTreeMap: split off most code of remove and split_off Putting map.rs on a diet, in addition to #77851. r? @dtolnay
2 parents 9583029 + 003516f commit f8bae8b

File tree

4 files changed

+239
-222
lines changed

4 files changed

+239
-222
lines changed

library/alloc/src/collections/btree/map.rs

+1-222
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ use super::node::{self, marker, ForceResult::*, Handle, NodeRef};
1313
use super::search::{self, SearchResult::*};
1414
use super::unwrap_unchecked;
1515

16-
use UnderflowResult::*;
17-
1816
mod entry;
1917
pub use entry::{Entry, OccupiedEntry, VacantEntry};
2018
use Entry::*;
@@ -1154,40 +1152,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
11541152

11551153
let mut right = Self::new();
11561154
let right_root = Self::ensure_is_owned(&mut right.root);
1157-
for _ in 0..left_root.height() {
1158-
right_root.push_internal_level();
1159-
}
1160-
1161-
{
1162-
let mut left_node = left_root.node_as_mut();
1163-
let mut right_node = right_root.node_as_mut();
1164-
1165-
loop {
1166-
let mut split_edge = match search::search_node(left_node, key) {
1167-
// key is going to the right tree
1168-
Found(handle) => handle.left_edge(),
1169-
GoDown(handle) => handle,
1170-
};
11711155

1172-
split_edge.move_suffix(&mut right_node);
1173-
1174-
match (split_edge.force(), right_node.force()) {
1175-
(Internal(edge), Internal(node)) => {
1176-
left_node = edge.descend();
1177-
right_node = node.first_edge().descend();
1178-
}
1179-
(Leaf(_), Leaf(_)) => {
1180-
break;
1181-
}
1182-
_ => {
1183-
unreachable!();
1184-
}
1185-
}
1186-
}
1187-
}
1188-
1189-
left_root.fix_right_border();
1190-
right_root.fix_left_border();
1156+
left_root.split_off(right_root, key);
11911157

11921158
if left_root.height() < right_root.height() {
11931159
self.length = left_root.node_as_ref().calc_length();
@@ -2250,193 +2216,6 @@ impl<K, V> BTreeMap<K, V> {
22502216
}
22512217
}
22522218

2253-
impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
2254-
/// Removes a key/value-pair from the map, and returns that pair, as well as
2255-
/// the leaf edge corresponding to that former pair.
2256-
fn remove_kv_tracking<F: FnOnce()>(
2257-
self,
2258-
handle_emptied_internal_root: F,
2259-
) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
2260-
let (old_kv, mut pos, was_internal) = match self.force() {
2261-
Leaf(leaf) => {
2262-
let (old_kv, pos) = leaf.remove();
2263-
(old_kv, pos, false)
2264-
}
2265-
Internal(mut internal) => {
2266-
// Replace the location freed in the internal node with an
2267-
// adjacent KV, and remove that adjacent KV from its leaf.
2268-
// Always choose the adjacent KV on the left side because
2269-
// it is typically faster to pop an element from the end
2270-
// of the KV arrays without needing to shift other elements.
2271-
2272-
let key_loc = internal.kv_mut().0 as *mut K;
2273-
let val_loc = internal.kv_mut().1 as *mut V;
2274-
2275-
let to_remove = internal.left_edge().descend().last_leaf_edge().left_kv().ok();
2276-
let to_remove = unsafe { unwrap_unchecked(to_remove) };
2277-
2278-
let (kv, pos) = to_remove.remove();
2279-
2280-
let old_key = unsafe { mem::replace(&mut *key_loc, kv.0) };
2281-
let old_val = unsafe { mem::replace(&mut *val_loc, kv.1) };
2282-
2283-
((old_key, old_val), pos, true)
2284-
}
2285-
};
2286-
2287-
// Handle underflow
2288-
let mut cur_node = unsafe { ptr::read(&pos).into_node().forget_type() };
2289-
let mut at_leaf = true;
2290-
while cur_node.len() < node::MIN_LEN {
2291-
match handle_underfull_node(cur_node) {
2292-
AtRoot => break,
2293-
Merged(edge, merged_with_left, offset) => {
2294-
// If we merged with our right sibling then our tracked
2295-
// position has not changed. However if we merged with our
2296-
// left sibling then our tracked position is now dangling.
2297-
if at_leaf && merged_with_left {
2298-
let idx = pos.idx() + offset;
2299-
let node = match unsafe { ptr::read(&edge).descend().force() } {
2300-
Leaf(leaf) => leaf,
2301-
Internal(_) => unreachable!(),
2302-
};
2303-
pos = unsafe { Handle::new_edge(node, idx) };
2304-
}
2305-
2306-
let parent = edge.into_node();
2307-
if parent.len() == 0 {
2308-
// The parent that was just emptied must be the root,
2309-
// because nodes on a lower level would not have been
2310-
// left with a single child.
2311-
handle_emptied_internal_root();
2312-
break;
2313-
} else {
2314-
cur_node = parent.forget_type();
2315-
at_leaf = false;
2316-
}
2317-
}
2318-
Stole(stole_from_left) => {
2319-
// Adjust the tracked position if we stole from a left sibling
2320-
if stole_from_left && at_leaf {
2321-
// SAFETY: This is safe since we just added an element to our node.
2322-
unsafe {
2323-
pos.move_next_unchecked();
2324-
}
2325-
}
2326-
break;
2327-
}
2328-
}
2329-
}
2330-
2331-
// If we deleted from an internal node then we need to compensate for
2332-
// the earlier swap and adjust the tracked position to point to the
2333-
// next element.
2334-
if was_internal {
2335-
pos = unsafe { unwrap_unchecked(pos.next_kv().ok()).next_leaf_edge() };
2336-
}
2337-
2338-
(old_kv, pos)
2339-
}
2340-
}
2341-
2342-
impl<K, V> node::Root<K, V> {
2343-
/// Removes empty levels on the top, but keep an empty leaf if the entire tree is empty.
2344-
fn fix_top(&mut self) {
2345-
while self.height() > 0 && self.node_as_ref().len() == 0 {
2346-
self.pop_internal_level();
2347-
}
2348-
}
2349-
2350-
fn fix_right_border(&mut self) {
2351-
self.fix_top();
2352-
2353-
{
2354-
let mut cur_node = self.node_as_mut();
2355-
2356-
while let Internal(node) = cur_node.force() {
2357-
let mut last_kv = node.last_kv();
2358-
2359-
if last_kv.can_merge() {
2360-
cur_node = last_kv.merge().descend();
2361-
} else {
2362-
let right_len = last_kv.reborrow().right_edge().descend().len();
2363-
// `MINLEN + 1` to avoid readjust if merge happens on the next level.
2364-
if right_len < node::MIN_LEN + 1 {
2365-
last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
2366-
}
2367-
cur_node = last_kv.right_edge().descend();
2368-
}
2369-
}
2370-
}
2371-
2372-
self.fix_top();
2373-
}
2374-
2375-
/// The symmetric clone of `fix_right_border`.
2376-
fn fix_left_border(&mut self) {
2377-
self.fix_top();
2378-
2379-
{
2380-
let mut cur_node = self.node_as_mut();
2381-
2382-
while let Internal(node) = cur_node.force() {
2383-
let mut first_kv = node.first_kv();
2384-
2385-
if first_kv.can_merge() {
2386-
cur_node = first_kv.merge().descend();
2387-
} else {
2388-
let left_len = first_kv.reborrow().left_edge().descend().len();
2389-
if left_len < node::MIN_LEN + 1 {
2390-
first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
2391-
}
2392-
cur_node = first_kv.left_edge().descend();
2393-
}
2394-
}
2395-
}
2396-
2397-
self.fix_top();
2398-
}
2399-
}
2400-
2401-
enum UnderflowResult<'a, K, V> {
2402-
AtRoot,
2403-
Merged(Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge>, bool, usize),
2404-
Stole(bool),
2405-
}
2406-
2407-
fn handle_underfull_node<'a, K: 'a, V: 'a>(
2408-
node: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>,
2409-
) -> UnderflowResult<'_, K, V> {
2410-
let parent = match node.ascend() {
2411-
Ok(parent) => parent,
2412-
Err(_) => return AtRoot,
2413-
};
2414-
2415-
// Prefer the left KV if it exists. Merging with the left side is faster,
2416-
// since merging happens towards the left and `node` has fewer elements.
2417-
// Stealing from the left side is faster, since we can pop from the end of
2418-
// the KV arrays.
2419-
let (is_left, mut handle) = match parent.left_kv() {
2420-
Ok(left) => (true, left),
2421-
Err(parent) => {
2422-
let right = unsafe { unwrap_unchecked(parent.right_kv().ok()) };
2423-
(false, right)
2424-
}
2425-
};
2426-
2427-
if handle.can_merge() {
2428-
let offset = if is_left { handle.reborrow().left_edge().descend().len() + 1 } else { 0 };
2429-
Merged(handle.merge(), is_left, offset)
2430-
} else {
2431-
if is_left {
2432-
handle.steal_left();
2433-
} else {
2434-
handle.steal_right();
2435-
}
2436-
Stole(is_left)
2437-
}
2438-
}
2439-
24402219
impl<K: Ord, V, I: Iterator<Item = (K, V)>> Iterator for MergeIter<K, V, I> {
24412220
type Item = (K, V);
24422221

library/alloc/src/collections/btree/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ mod borrow;
22
pub mod map;
33
mod navigate;
44
mod node;
5+
mod remove;
56
mod search;
67
pub mod set;
8+
mod split;
79

810
#[doc(hidden)]
911
trait Recover<Q: ?Sized> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use super::node::{self, marker, ForceResult, Handle, NodeRef};
2+
use super::unwrap_unchecked;
3+
use core::mem;
4+
use core::ptr;
5+
6+
impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
7+
/// Removes a key/value-pair from the map, and returns that pair, as well as
8+
/// the leaf edge corresponding to that former pair.
9+
pub fn remove_kv_tracking<F: FnOnce()>(
10+
self,
11+
handle_emptied_internal_root: F,
12+
) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
13+
let (old_kv, mut pos, was_internal) = match self.force() {
14+
ForceResult::Leaf(leaf) => {
15+
let (old_kv, pos) = leaf.remove();
16+
(old_kv, pos, false)
17+
}
18+
ForceResult::Internal(mut internal) => {
19+
// Replace the location freed in the internal node with an
20+
// adjacent KV, and remove that adjacent KV from its leaf.
21+
// Always choose the adjacent KV on the left side because
22+
// it is typically faster to pop an element from the end
23+
// of the KV arrays without needing to shift other elements.
24+
25+
let key_loc = internal.kv_mut().0 as *mut K;
26+
let val_loc = internal.kv_mut().1 as *mut V;
27+
28+
let to_remove = internal.left_edge().descend().last_leaf_edge().left_kv().ok();
29+
let to_remove = unsafe { unwrap_unchecked(to_remove) };
30+
31+
let (kv, pos) = to_remove.remove();
32+
33+
let old_key = unsafe { mem::replace(&mut *key_loc, kv.0) };
34+
let old_val = unsafe { mem::replace(&mut *val_loc, kv.1) };
35+
36+
((old_key, old_val), pos, true)
37+
}
38+
};
39+
40+
// Handle underflow
41+
let mut cur_node = unsafe { ptr::read(&pos).into_node().forget_type() };
42+
let mut at_leaf = true;
43+
while cur_node.len() < node::MIN_LEN {
44+
match handle_underfull_node(cur_node) {
45+
UnderflowResult::AtRoot => break,
46+
UnderflowResult::Merged(edge, merged_with_left, offset) => {
47+
// If we merged with our right sibling then our tracked
48+
// position has not changed. However if we merged with our
49+
// left sibling then our tracked position is now dangling.
50+
if at_leaf && merged_with_left {
51+
let idx = pos.idx() + offset;
52+
let node = match unsafe { ptr::read(&edge).descend().force() } {
53+
ForceResult::Leaf(leaf) => leaf,
54+
ForceResult::Internal(_) => unreachable!(),
55+
};
56+
pos = unsafe { Handle::new_edge(node, idx) };
57+
}
58+
59+
let parent = edge.into_node();
60+
if parent.len() == 0 {
61+
// The parent that was just emptied must be the root,
62+
// because nodes on a lower level would not have been
63+
// left with a single child.
64+
handle_emptied_internal_root();
65+
break;
66+
} else {
67+
cur_node = parent.forget_type();
68+
at_leaf = false;
69+
}
70+
}
71+
UnderflowResult::Stole(stole_from_left) => {
72+
// Adjust the tracked position if we stole from a left sibling
73+
if stole_from_left && at_leaf {
74+
// SAFETY: This is safe since we just added an element to our node.
75+
unsafe {
76+
pos.move_next_unchecked();
77+
}
78+
}
79+
break;
80+
}
81+
}
82+
}
83+
84+
// If we deleted from an internal node then we need to compensate for
85+
// the earlier swap and adjust the tracked position to point to the
86+
// next element.
87+
if was_internal {
88+
pos = unsafe { unwrap_unchecked(pos.next_kv().ok()).next_leaf_edge() };
89+
}
90+
91+
(old_kv, pos)
92+
}
93+
}
94+
95+
enum UnderflowResult<'a, K, V> {
96+
AtRoot,
97+
Merged(Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge>, bool, usize),
98+
Stole(bool),
99+
}
100+
101+
fn handle_underfull_node<'a, K: 'a, V: 'a>(
102+
node: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>,
103+
) -> UnderflowResult<'_, K, V> {
104+
let parent = match node.ascend() {
105+
Ok(parent) => parent,
106+
Err(_) => return UnderflowResult::AtRoot,
107+
};
108+
109+
// Prefer the left KV if it exists. Merging with the left side is faster,
110+
// since merging happens towards the left and `node` has fewer elements.
111+
// Stealing from the left side is faster, since we can pop from the end of
112+
// the KV arrays.
113+
let (is_left, mut handle) = match parent.left_kv() {
114+
Ok(left) => (true, left),
115+
Err(parent) => {
116+
let right = unsafe { unwrap_unchecked(parent.right_kv().ok()) };
117+
(false, right)
118+
}
119+
};
120+
121+
if handle.can_merge() {
122+
let offset = if is_left { handle.reborrow().left_edge().descend().len() + 1 } else { 0 };
123+
UnderflowResult::Merged(handle.merge(), is_left, offset)
124+
} else {
125+
if is_left {
126+
handle.steal_left();
127+
} else {
128+
handle.steal_right();
129+
}
130+
UnderflowResult::Stole(is_left)
131+
}
132+
}

0 commit comments

Comments
 (0)