BTreeMap: introduce marker::ValMut and reserve marker::Mut for unique access
This commit is contained in:
parent
443e177c7f
commit
e5f9d7ff92
3 changed files with 319 additions and 171 deletions
|
@ -5,7 +5,6 @@ use core::hash::{Hash, Hasher};
|
||||||
use core::iter::{FromIterator, FusedIterator, Peekable};
|
use core::iter::{FromIterator, FusedIterator, Peekable};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem::{self, ManuallyDrop};
|
use core::mem::{self, ManuallyDrop};
|
||||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
|
||||||
use core::ops::{Index, RangeBounds};
|
use core::ops::{Index, RangeBounds};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
|
@ -408,8 +407,8 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Range<'_, K, V> {
|
||||||
/// [`range_mut`]: BTreeMap::range_mut
|
/// [`range_mut`]: BTreeMap::range_mut
|
||||||
#[stable(feature = "btree_range", since = "1.17.0")]
|
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||||
pub struct RangeMut<'a, K: 'a, V: 'a> {
|
pub struct RangeMut<'a, K: 'a, V: 'a> {
|
||||||
front: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
front: Option<Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
back: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
back: Option<Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
||||||
|
|
||||||
// Be invariant in `K` and `V`
|
// Be invariant in `K` and `V`
|
||||||
_marker: PhantomData<&'a mut (K, V)>,
|
_marker: PhantomData<&'a mut (K, V)>,
|
||||||
|
@ -999,7 +998,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
R: RangeBounds<T>,
|
R: RangeBounds<T>,
|
||||||
{
|
{
|
||||||
if let Some(root) = &self.root {
|
if let Some(root) = &self.root {
|
||||||
let (f, b) = range_search(root.node_as_ref(), range);
|
let (f, b) = root.node_as_ref().range_search(range);
|
||||||
|
|
||||||
Range { front: Some(f), back: Some(b) }
|
Range { front: Some(f), back: Some(b) }
|
||||||
} else {
|
} else {
|
||||||
|
@ -1045,7 +1044,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||||
R: RangeBounds<T>,
|
R: RangeBounds<T>,
|
||||||
{
|
{
|
||||||
if let Some(root) = &mut self.root {
|
if let Some(root) = &mut self.root {
|
||||||
let (f, b) = range_search(root.node_as_mut(), range);
|
let (f, b) = root.node_as_valmut().range_search(range);
|
||||||
|
|
||||||
RangeMut { front: Some(f), back: Some(b), _marker: PhantomData }
|
RangeMut { front: Some(f), back: Some(b), _marker: PhantomData }
|
||||||
} else {
|
} else {
|
||||||
|
@ -1478,7 +1477,7 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
|
||||||
fn into_iter(self) -> IntoIter<K, V> {
|
fn into_iter(self) -> IntoIter<K, V> {
|
||||||
let mut me = ManuallyDrop::new(self);
|
let mut me = ManuallyDrop::new(self);
|
||||||
if let Some(root) = me.root.take() {
|
if let Some(root) = me.root.take() {
|
||||||
let (f, b) = full_range_search(root.into_ref());
|
let (f, b) = root.into_ref().full_range();
|
||||||
|
|
||||||
IntoIter { front: Some(f), back: Some(b), length: me.length }
|
IntoIter { front: Some(f), back: Some(b), length: me.length }
|
||||||
} else {
|
} else {
|
||||||
|
@ -1942,7 +1941,7 @@ impl<'a, K, V> RangeMut<'a, K, V> {
|
||||||
self.front == self.back
|
self.front == self.back
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
|
||||||
unsafe { unwrap_unchecked(self.front.as_mut()).next_unchecked() }
|
unsafe { unwrap_unchecked(self.front.as_mut()).next_unchecked() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1963,7 +1962,7 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
|
||||||
impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
|
impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
|
||||||
|
|
||||||
impl<'a, K, V> RangeMut<'a, K, V> {
|
impl<'a, K, V> RangeMut<'a, K, V> {
|
||||||
unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
|
||||||
unsafe { unwrap_unchecked(self.back.as_mut()).next_back_unchecked() }
|
unsafe { unwrap_unchecked(self.back.as_mut()).next_back_unchecked() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2073,119 +2072,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the leaf edges delimiting a specified range in or underneath a node.
|
|
||||||
fn range_search<BorrowType, K, V, Q: ?Sized, R: RangeBounds<Q>>(
|
|
||||||
root: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
|
||||||
range: R,
|
|
||||||
) -> (
|
|
||||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
|
||||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
|
||||||
)
|
|
||||||
where
|
|
||||||
Q: Ord,
|
|
||||||
K: Borrow<Q>,
|
|
||||||
{
|
|
||||||
match (range.start_bound(), range.end_bound()) {
|
|
||||||
(Excluded(s), Excluded(e)) if s == e => {
|
|
||||||
panic!("range start and end are equal and excluded in BTreeMap")
|
|
||||||
}
|
|
||||||
(Included(s) | Excluded(s), Included(e) | Excluded(e)) if s > e => {
|
|
||||||
panic!("range start is greater than range end in BTreeMap")
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// We duplicate the root NodeRef here -- we will never access it in a way
|
|
||||||
// that overlaps references obtained from the root.
|
|
||||||
let mut min_node = unsafe { ptr::read(&root) };
|
|
||||||
let mut max_node = root;
|
|
||||||
let mut min_found = false;
|
|
||||||
let mut max_found = false;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let front = match (min_found, range.start_bound()) {
|
|
||||||
(false, Included(key)) => match search::search_node(min_node, key) {
|
|
||||||
Found(kv) => {
|
|
||||||
min_found = true;
|
|
||||||
kv.left_edge()
|
|
||||||
}
|
|
||||||
GoDown(edge) => edge,
|
|
||||||
},
|
|
||||||
(false, Excluded(key)) => match search::search_node(min_node, key) {
|
|
||||||
Found(kv) => {
|
|
||||||
min_found = true;
|
|
||||||
kv.right_edge()
|
|
||||||
}
|
|
||||||
GoDown(edge) => edge,
|
|
||||||
},
|
|
||||||
(true, Included(_)) => min_node.last_edge(),
|
|
||||||
(true, Excluded(_)) => min_node.first_edge(),
|
|
||||||
(_, Unbounded) => min_node.first_edge(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let back = match (max_found, range.end_bound()) {
|
|
||||||
(false, Included(key)) => match search::search_node(max_node, key) {
|
|
||||||
Found(kv) => {
|
|
||||||
max_found = true;
|
|
||||||
kv.right_edge()
|
|
||||||
}
|
|
||||||
GoDown(edge) => edge,
|
|
||||||
},
|
|
||||||
(false, Excluded(key)) => match search::search_node(max_node, key) {
|
|
||||||
Found(kv) => {
|
|
||||||
max_found = true;
|
|
||||||
kv.left_edge()
|
|
||||||
}
|
|
||||||
GoDown(edge) => edge,
|
|
||||||
},
|
|
||||||
(true, Included(_)) => max_node.first_edge(),
|
|
||||||
(true, Excluded(_)) => max_node.last_edge(),
|
|
||||||
(_, Unbounded) => max_node.last_edge(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if front.partial_cmp(&back) == Some(Ordering::Greater) {
|
|
||||||
panic!("Ord is ill-defined in BTreeMap range");
|
|
||||||
}
|
|
||||||
match (front.force(), back.force()) {
|
|
||||||
(Leaf(f), Leaf(b)) => {
|
|
||||||
return (f, b);
|
|
||||||
}
|
|
||||||
(Internal(min_int), Internal(max_int)) => {
|
|
||||||
min_node = min_int.descend();
|
|
||||||
max_node = max_int.descend();
|
|
||||||
}
|
|
||||||
_ => unreachable!("BTreeMap has different depths"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Equivalent to `range_search(k, v, ..)` without the `Ord` bound.
|
|
||||||
fn full_range_search<BorrowType, K, V>(
|
|
||||||
root: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
|
||||||
) -> (
|
|
||||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
|
||||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
|
||||||
) {
|
|
||||||
// We duplicate the root NodeRef here -- we will never access it in a way
|
|
||||||
// that overlaps references obtained from the root.
|
|
||||||
let mut min_node = unsafe { ptr::read(&root) };
|
|
||||||
let mut max_node = root;
|
|
||||||
loop {
|
|
||||||
let front = min_node.first_edge();
|
|
||||||
let back = max_node.last_edge();
|
|
||||||
match (front.force(), back.force()) {
|
|
||||||
(Leaf(f), Leaf(b)) => {
|
|
||||||
return (f, b);
|
|
||||||
}
|
|
||||||
(Internal(min_int), Internal(max_int)) => {
|
|
||||||
min_node = min_int.descend();
|
|
||||||
max_node = max_int.descend();
|
|
||||||
}
|
|
||||||
_ => unreachable!("BTreeMap has different depths"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V> BTreeMap<K, V> {
|
impl<K, V> BTreeMap<K, V> {
|
||||||
/// Gets an iterator over the entries of the map, sorted by key.
|
/// Gets an iterator over the entries of the map, sorted by key.
|
||||||
///
|
///
|
||||||
|
@ -2211,7 +2097,7 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn iter(&self) -> Iter<'_, K, V> {
|
pub fn iter(&self) -> Iter<'_, K, V> {
|
||||||
if let Some(root) = &self.root {
|
if let Some(root) = &self.root {
|
||||||
let (f, b) = full_range_search(root.node_as_ref());
|
let (f, b) = root.node_as_ref().full_range();
|
||||||
|
|
||||||
Iter { range: Range { front: Some(f), back: Some(b) }, length: self.length }
|
Iter { range: Range { front: Some(f), back: Some(b) }, length: self.length }
|
||||||
} else {
|
} else {
|
||||||
|
@ -2243,7 +2129,7 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
|
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
|
||||||
if let Some(root) = &mut self.root {
|
if let Some(root) = &mut self.root {
|
||||||
let (f, b) = full_range_search(root.node_as_mut());
|
let (f, b) = root.node_as_valmut().full_range();
|
||||||
|
|
||||||
IterMut {
|
IterMut {
|
||||||
range: RangeMut { front: Some(f), back: Some(b), _marker: PhantomData },
|
range: RangeMut { front: Some(f), back: Some(b), _marker: PhantomData },
|
||||||
|
@ -2826,7 +2712,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInter
|
||||||
if stole_from_left && at_leaf {
|
if stole_from_left && at_leaf {
|
||||||
// SAFETY: This is safe since we just added an element to our node.
|
// SAFETY: This is safe since we just added an element to our node.
|
||||||
unsafe {
|
unsafe {
|
||||||
pos.next_unchecked();
|
pos.move_next_unchecked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,10 +1,210 @@
|
||||||
|
use core::borrow::Borrow;
|
||||||
|
use core::cmp::Ordering;
|
||||||
use core::intrinsics;
|
use core::intrinsics;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||||
|
use core::ops::RangeBounds;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
use super::node::{marker, ForceResult::*, Handle, NodeRef};
|
use super::node::{marker, ForceResult::*, Handle, NodeRef};
|
||||||
|
use super::search::{self, SearchResult};
|
||||||
use super::unwrap_unchecked;
|
use super::unwrap_unchecked;
|
||||||
|
|
||||||
|
/// Finds the leaf edges delimiting a specified range in or underneath a node.
|
||||||
|
fn range_search<BorrowType, K, V, Q, R>(
|
||||||
|
root1: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||||
|
root2: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||||
|
range: R,
|
||||||
|
) -> (
|
||||||
|
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
Q: ?Sized + Ord,
|
||||||
|
K: Borrow<Q>,
|
||||||
|
R: RangeBounds<Q>,
|
||||||
|
{
|
||||||
|
match (range.start_bound(), range.end_bound()) {
|
||||||
|
(Excluded(s), Excluded(e)) if s == e => {
|
||||||
|
panic!("range start and end are equal and excluded in BTreeMap")
|
||||||
|
}
|
||||||
|
(Included(s) | Excluded(s), Included(e) | Excluded(e)) if s > e => {
|
||||||
|
panic!("range start is greater than range end in BTreeMap")
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut min_node = root1;
|
||||||
|
let mut max_node = root2;
|
||||||
|
let mut min_found = false;
|
||||||
|
let mut max_found = false;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let front = match (min_found, range.start_bound()) {
|
||||||
|
(false, Included(key)) => match search::search_node(min_node, key) {
|
||||||
|
SearchResult::Found(kv) => {
|
||||||
|
min_found = true;
|
||||||
|
kv.left_edge()
|
||||||
|
}
|
||||||
|
SearchResult::GoDown(edge) => edge,
|
||||||
|
},
|
||||||
|
(false, Excluded(key)) => match search::search_node(min_node, key) {
|
||||||
|
SearchResult::Found(kv) => {
|
||||||
|
min_found = true;
|
||||||
|
kv.right_edge()
|
||||||
|
}
|
||||||
|
SearchResult::GoDown(edge) => edge,
|
||||||
|
},
|
||||||
|
(true, Included(_)) => min_node.last_edge(),
|
||||||
|
(true, Excluded(_)) => min_node.first_edge(),
|
||||||
|
(_, Unbounded) => min_node.first_edge(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let back = match (max_found, range.end_bound()) {
|
||||||
|
(false, Included(key)) => match search::search_node(max_node, key) {
|
||||||
|
SearchResult::Found(kv) => {
|
||||||
|
max_found = true;
|
||||||
|
kv.right_edge()
|
||||||
|
}
|
||||||
|
SearchResult::GoDown(edge) => edge,
|
||||||
|
},
|
||||||
|
(false, Excluded(key)) => match search::search_node(max_node, key) {
|
||||||
|
SearchResult::Found(kv) => {
|
||||||
|
max_found = true;
|
||||||
|
kv.left_edge()
|
||||||
|
}
|
||||||
|
SearchResult::GoDown(edge) => edge,
|
||||||
|
},
|
||||||
|
(true, Included(_)) => max_node.first_edge(),
|
||||||
|
(true, Excluded(_)) => max_node.last_edge(),
|
||||||
|
(_, Unbounded) => max_node.last_edge(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if front.partial_cmp(&back) == Some(Ordering::Greater) {
|
||||||
|
panic!("Ord is ill-defined in BTreeMap range");
|
||||||
|
}
|
||||||
|
match (front.force(), back.force()) {
|
||||||
|
(Leaf(f), Leaf(b)) => {
|
||||||
|
return (f, b);
|
||||||
|
}
|
||||||
|
(Internal(min_int), Internal(max_int)) => {
|
||||||
|
min_node = min_int.descend();
|
||||||
|
max_node = max_int.descend();
|
||||||
|
}
|
||||||
|
_ => unreachable!("BTreeMap has different depths"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Equivalent to `range_search(k, v, ..)` but without the `Ord` bound.
|
||||||
|
fn full_range<BorrowType, K, V>(
|
||||||
|
root1: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||||
|
root2: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
|
||||||
|
) -> (
|
||||||
|
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
) {
|
||||||
|
let mut min_node = root1;
|
||||||
|
let mut max_node = root2;
|
||||||
|
loop {
|
||||||
|
let front = min_node.first_edge();
|
||||||
|
let back = max_node.last_edge();
|
||||||
|
match (front.force(), back.force()) {
|
||||||
|
(Leaf(f), Leaf(b)) => {
|
||||||
|
return (f, b);
|
||||||
|
}
|
||||||
|
(Internal(min_int), Internal(max_int)) => {
|
||||||
|
min_node = min_int.descend();
|
||||||
|
max_node = max_int.descend();
|
||||||
|
}
|
||||||
|
_ => unreachable!("BTreeMap has different depths"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> {
|
||||||
|
/// Creates a pair of leaf edges delimiting a specified range in or underneath a node.
|
||||||
|
pub fn range_search<Q, R>(
|
||||||
|
self,
|
||||||
|
range: R,
|
||||||
|
) -> (
|
||||||
|
Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
Q: ?Sized + Ord,
|
||||||
|
K: Borrow<Q>,
|
||||||
|
R: RangeBounds<Q>,
|
||||||
|
{
|
||||||
|
range_search(self, self, range)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns (self.first_leaf_edge(), self.last_leaf_edge()), but more efficiently.
|
||||||
|
pub fn full_range(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
) {
|
||||||
|
full_range(self, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: 'a, V: 'a> NodeRef<marker::ValMut<'a>, K, V, marker::LeafOrInternal> {
|
||||||
|
/// Splits a unique reference into a pair of leaf edges delimiting a specified range.
|
||||||
|
/// The result are non-unique references allowing (some) mutation, which must be used
|
||||||
|
/// carefully.
|
||||||
|
pub fn range_search<Q, R>(
|
||||||
|
self,
|
||||||
|
range: R,
|
||||||
|
) -> (
|
||||||
|
Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
Q: ?Sized + Ord,
|
||||||
|
K: Borrow<Q>,
|
||||||
|
R: RangeBounds<Q>,
|
||||||
|
{
|
||||||
|
// We duplicate the root NodeRef here -- we will never visit the same KV
|
||||||
|
// twice, and never end up with overlapping value references.
|
||||||
|
let self2 = unsafe { ptr::read(&self) };
|
||||||
|
range_search(self, self2, range)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree.
|
||||||
|
/// The results are non-unique references allowing mutation (of values only), so must be used
|
||||||
|
/// with care.
|
||||||
|
pub fn full_range(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
) {
|
||||||
|
// We duplicate the root NodeRef here -- we will never visit the same KV
|
||||||
|
// twice, and never end up with overlapping value references.
|
||||||
|
let self2 = unsafe { ptr::read(&self) };
|
||||||
|
full_range(self, self2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
|
||||||
|
/// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree.
|
||||||
|
/// The results are non-unique references allowing massively destructive mutation, so must be
|
||||||
|
/// used with the utmost care.
|
||||||
|
pub fn full_range(
|
||||||
|
self,
|
||||||
|
) -> (
|
||||||
|
Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
|
||||||
|
) {
|
||||||
|
// We duplicate the root NodeRef here -- we will never access it in a way
|
||||||
|
// that overlaps references obtained from the root.
|
||||||
|
let self2 = unsafe { ptr::read(&self) };
|
||||||
|
full_range(self, self2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
|
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
|
||||||
/// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
|
/// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
|
||||||
/// on the right side, which is either in the same leaf node or in an ancestor node.
|
/// on the right side, which is either in the same leaf node or in an ancestor node.
|
||||||
|
@ -75,12 +275,13 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marke
|
||||||
macro_rules! def_next_kv_uncheched_dealloc {
|
macro_rules! def_next_kv_uncheched_dealloc {
|
||||||
{ unsafe fn $name:ident : $adjacent_kv:ident } => {
|
{ unsafe fn $name:ident : $adjacent_kv:ident } => {
|
||||||
/// Given a leaf edge handle into an owned tree, returns a handle to the next KV,
|
/// Given a leaf edge handle into an owned tree, returns a handle to the next KV,
|
||||||
/// while deallocating any node left behind.
|
/// while deallocating any node left behind yet leaving the corresponding edge
|
||||||
/// Unsafe for two reasons:
|
/// in its parent node dangling.
|
||||||
/// - The caller must ensure that the leaf edge is not the last one in the tree.
|
///
|
||||||
/// - The node pointed at by the given handle, and its ancestors, may be deallocated,
|
/// # Safety
|
||||||
/// while the reference to those nodes in the surviving ancestors is left dangling;
|
/// - The leaf edge must not be the last one in the direction travelled.
|
||||||
/// thus using the returned handle to navigate further is dangerous.
|
/// - The node carrying the next KV returned must not have been deallocated by a
|
||||||
|
/// previous call on any handle obtained for this tree.
|
||||||
unsafe fn $name <K, V>(
|
unsafe fn $name <K, V>(
|
||||||
leaf_edge: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
|
leaf_edge: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
|
||||||
) -> Handle<NodeRef<marker::Owned, K, V, marker::LeafOrInternal>, marker::KV> {
|
) -> Handle<NodeRef<marker::Owned, K, V, marker::LeafOrInternal>, marker::KV> {
|
||||||
|
@ -103,6 +304,15 @@ macro_rules! def_next_kv_uncheched_dealloc {
|
||||||
def_next_kv_uncheched_dealloc! {unsafe fn next_kv_unchecked_dealloc: right_kv}
|
def_next_kv_uncheched_dealloc! {unsafe fn next_kv_unchecked_dealloc: right_kv}
|
||||||
def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_kv}
|
def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_kv}
|
||||||
|
|
||||||
|
/// This replaces the value behind the `v` unique reference by calling the
|
||||||
|
/// relevant function.
|
||||||
|
///
|
||||||
|
/// If a panic occurs in the `change` closure, the entire process will be aborted.
|
||||||
|
#[inline]
|
||||||
|
fn take_mut<T>(v: &mut T, change: impl FnOnce(T) -> T) {
|
||||||
|
replace(v, |value| (change(value), ()))
|
||||||
|
}
|
||||||
|
|
||||||
/// This replaces the value behind the `v` unique reference by calling the
|
/// This replaces the value behind the `v` unique reference by calling the
|
||||||
/// relevant function, and returns a result obtained along the way.
|
/// relevant function, and returns a result obtained along the way.
|
||||||
///
|
///
|
||||||
|
@ -128,7 +338,9 @@ fn replace<T, R>(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R {
|
||||||
impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge> {
|
impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge> {
|
||||||
/// Moves the leaf edge handle to the next leaf edge and returns references to the
|
/// Moves the leaf edge handle to the next leaf edge and returns references to the
|
||||||
/// key and value in between.
|
/// key and value in between.
|
||||||
/// Unsafe because the caller must ensure that the leaf edge is not the last one in the tree.
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// There must be another KV in the direction travelled.
|
||||||
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
|
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
|
||||||
replace(self, |leaf_edge| {
|
replace(self, |leaf_edge| {
|
||||||
let kv = leaf_edge.next_kv();
|
let kv = leaf_edge.next_kv();
|
||||||
|
@ -139,7 +351,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
|
||||||
|
|
||||||
/// Moves the leaf edge handle to the previous leaf edge and returns references to the
|
/// Moves the leaf edge handle to the previous leaf edge and returns references to the
|
||||||
/// key and value in between.
|
/// key and value in between.
|
||||||
/// Unsafe because the caller must ensure that the leaf edge is not the first one in the tree.
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// There must be another KV in the direction travelled.
|
||||||
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
|
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
|
||||||
replace(self, |leaf_edge| {
|
replace(self, |leaf_edge| {
|
||||||
let kv = leaf_edge.next_back_kv();
|
let kv = leaf_edge.next_back_kv();
|
||||||
|
@ -149,53 +363,69 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge> {
|
impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge> {
|
||||||
/// Moves the leaf edge handle to the next leaf edge and returns references to the
|
/// Moves the leaf edge handle to the next leaf edge and returns references to the
|
||||||
/// key and value in between.
|
/// key and value in between.
|
||||||
/// Unsafe for two reasons:
|
/// The returned references might be invalidated when the updated handle is used again.
|
||||||
/// - The caller must ensure that the leaf edge is not the last one in the tree.
|
///
|
||||||
/// - Using the updated handle may well invalidate the returned references.
|
/// # Safety
|
||||||
pub unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
/// There must be another KV in the direction travelled.
|
||||||
|
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
|
||||||
let kv = replace(self, |leaf_edge| {
|
let kv = replace(self, |leaf_edge| {
|
||||||
let kv = leaf_edge.next_kv();
|
let kv = leaf_edge.next_kv();
|
||||||
let kv = unsafe { unwrap_unchecked(kv.ok()) };
|
let kv = unsafe { unwrap_unchecked(kv.ok()) };
|
||||||
(unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)
|
(unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)
|
||||||
});
|
});
|
||||||
// Doing the descend (and perhaps another move) invalidates the references
|
// Doing the descend (and perhaps another move) invalidates the references
|
||||||
// returned by `into_kv_mut`, so we have to do this last.
|
// returned by `into_kv_valmut`, so we have to do this last.
|
||||||
kv.into_kv_mut()
|
kv.into_kv_valmut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the leaf edge handle to the previous leaf and returns references to the
|
/// Moves the leaf edge handle to the previous leaf and returns references to the
|
||||||
/// key and value in between.
|
/// key and value in between.
|
||||||
/// Unsafe for two reasons:
|
/// The returned references might be invalidated when the updated handle is used again.
|
||||||
/// - The caller must ensure that the leaf edge is not the first one in the tree.
|
///
|
||||||
/// - Using the updated handle may well invalidate the returned references.
|
/// # Safety
|
||||||
pub unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
|
/// There must be another KV in the direction travelled.
|
||||||
|
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
|
||||||
let kv = replace(self, |leaf_edge| {
|
let kv = replace(self, |leaf_edge| {
|
||||||
let kv = leaf_edge.next_back_kv();
|
let kv = leaf_edge.next_back_kv();
|
||||||
let kv = unsafe { unwrap_unchecked(kv.ok()) };
|
let kv = unsafe { unwrap_unchecked(kv.ok()) };
|
||||||
(unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)
|
(unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)
|
||||||
});
|
});
|
||||||
// Doing the descend (and perhaps another move) invalidates the references
|
// Doing the descend (and perhaps another move) invalidates the references
|
||||||
// returned by `into_kv_mut`, so we have to do this last.
|
// returned by `into_kv_valmut`, so we have to do this last.
|
||||||
kv.into_kv_mut()
|
kv.into_kv_valmut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge> {
|
||||||
|
/// Moves the leaf edge handle to the next leaf edge.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// There must be another KV in the direction travelled.
|
||||||
|
pub unsafe fn move_next_unchecked(&mut self) {
|
||||||
|
take_mut(self, |leaf_edge| {
|
||||||
|
let kv = leaf_edge.next_kv();
|
||||||
|
let kv = unsafe { unwrap_unchecked(kv.ok()) };
|
||||||
|
kv.next_leaf_edge()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
|
impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
|
||||||
/// Moves the leaf edge handle to the next leaf edge and returns the key and value
|
/// Moves the leaf edge handle to the next leaf edge and returns the key and value
|
||||||
/// in between, while deallocating any node left behind.
|
/// in between, deallocating any node left behind while leaving the corresponding
|
||||||
/// Unsafe for two reasons:
|
/// edge in its parent node dangling.
|
||||||
/// - The caller must ensure that the leaf edge is not the last one in the tree
|
///
|
||||||
/// and is not a handle previously resulting from counterpart `next_back_unchecked`.
|
/// # Safety
|
||||||
/// - Further use of the updated leaf edge handle is very dangerous. In particular,
|
/// - There must be another KV in the direction travelled.
|
||||||
/// if the leaf edge is the last edge of a node, that node and possibly ancestors
|
/// - That KV was not previously returned by counterpart `next_back_unchecked`
|
||||||
/// will be deallocated, while the reference to those nodes in the surviving ancestor
|
/// on any copy of the handles being used to traverse the tree.
|
||||||
/// is left dangling.
|
///
|
||||||
/// The only safe way to proceed with the updated handle is to compare it, drop it,
|
/// The only safe way to proceed with the updated handle is to compare it, drop it,
|
||||||
/// call this method again subject to both preconditions listed in the first point,
|
/// call this method again subject to its safety conditions, or call counterpart
|
||||||
/// or call counterpart `next_back_unchecked` subject to its preconditions.
|
/// `next_back_unchecked` subject to its safety conditions.
|
||||||
pub unsafe fn next_unchecked(&mut self) -> (K, V) {
|
pub unsafe fn next_unchecked(&mut self) -> (K, V) {
|
||||||
replace(self, |leaf_edge| {
|
replace(self, |leaf_edge| {
|
||||||
let kv = unsafe { next_kv_unchecked_dealloc(leaf_edge) };
|
let kv = unsafe { next_kv_unchecked_dealloc(leaf_edge) };
|
||||||
|
@ -205,18 +435,18 @@ impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the leaf edge handle to the previous leaf edge and returns the key
|
/// Moves the leaf edge handle to the previous leaf edge and returns the key and value
|
||||||
/// and value in between, while deallocating any node left behind.
|
/// in between, deallocating any node left behind while leaving the corresponding
|
||||||
/// Unsafe for two reasons:
|
/// edge in its parent node dangling.
|
||||||
/// - The caller must ensure that the leaf edge is not the first one in the tree
|
///
|
||||||
/// and is not a handle previously resulting from counterpart `next_unchecked`.
|
/// # Safety
|
||||||
/// - Further use of the updated leaf edge handle is very dangerous. In particular,
|
/// - There must be another KV in the direction travelled.
|
||||||
/// if the leaf edge is the first edge of a node, that node and possibly ancestors
|
/// - That leaf edge was not previously returned by counterpart `next_unchecked`
|
||||||
/// will be deallocated, while the reference to those nodes in the surviving ancestor
|
/// on any copy of the handles being used to traverse the tree.
|
||||||
/// is left dangling.
|
///
|
||||||
/// The only safe way to proceed with the updated handle is to compare it, drop it,
|
/// The only safe way to proceed with the updated handle is to compare it, drop it,
|
||||||
/// call this method again subject to both preconditions listed in the first point,
|
/// call this method again subject to its safety conditions, or call counterpart
|
||||||
/// or call counterpart `next_unchecked` subject to its preconditions.
|
/// `next_unchecked` subject to its safety conditions.
|
||||||
pub unsafe fn next_back_unchecked(&mut self) -> (K, V) {
|
pub unsafe fn next_back_unchecked(&mut self) -> (K, V) {
|
||||||
replace(self, |leaf_edge| {
|
replace(self, |leaf_edge| {
|
||||||
let kv = unsafe { next_back_kv_unchecked_dealloc(leaf_edge) };
|
let kv = unsafe { next_back_kv_unchecked_dealloc(leaf_edge) };
|
||||||
|
|
|
@ -186,6 +186,15 @@ impl<K, V> Root<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn node_as_valmut(&mut self) -> NodeRef<marker::ValMut<'_>, K, V, marker::LeafOrInternal> {
|
||||||
|
NodeRef {
|
||||||
|
height: self.height,
|
||||||
|
node: self.node.as_ptr(),
|
||||||
|
root: ptr::null(),
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_ref(self) -> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
|
pub fn into_ref(self) -> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
|
||||||
NodeRef {
|
NodeRef {
|
||||||
height: self.height,
|
height: self.height,
|
||||||
|
@ -253,9 +262,12 @@ impl<K, V> Root<K, V> {
|
||||||
/// A reference to a node.
|
/// A reference to a node.
|
||||||
///
|
///
|
||||||
/// This type has a number of parameters that controls how it acts:
|
/// This type has a number of parameters that controls how it acts:
|
||||||
/// - `BorrowType`: This can be `Immut<'a>` or `Mut<'a>` for some `'a` or `Owned`.
|
/// - `BorrowType`: This can be `Immut<'a>`, `Mut<'a>` or `ValMut<'a>' for some `'a`
|
||||||
|
/// or `Owned`.
|
||||||
/// When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`,
|
/// When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`,
|
||||||
/// when this is `Mut<'a>`, the `NodeRef` acts roughly like `&'a mut Node`,
|
/// when this is `Mut<'a>`, the `NodeRef` acts roughly like `&'a mut Node`,
|
||||||
|
/// when this is `ValMut<'a>`, the `NodeRef` acts as immutable with respect
|
||||||
|
/// to keys and tree structure, but allows mutable references to values,
|
||||||
/// and when this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`.
|
/// and when this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`.
|
||||||
/// - `K` and `V`: These control what types of things are stored in the nodes.
|
/// - `K` and `V`: These control what types of things are stored in the nodes.
|
||||||
/// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is
|
/// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is
|
||||||
|
@ -282,6 +294,7 @@ unsafe impl<BorrowType, K: Sync, V: Sync, Type> Sync for NodeRef<BorrowType, K,
|
||||||
|
|
||||||
unsafe impl<'a, K: Sync + 'a, V: Sync + 'a, Type> Send for NodeRef<marker::Immut<'a>, K, V, Type> {}
|
unsafe impl<'a, K: Sync + 'a, V: Sync + 'a, Type> Send for NodeRef<marker::Immut<'a>, K, V, Type> {}
|
||||||
unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::Mut<'a>, K, V, Type> {}
|
unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::Mut<'a>, K, V, Type> {}
|
||||||
|
unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::ValMut<'a>, K, V, Type> {}
|
||||||
unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Owned, K, V, Type> {}
|
unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Owned, K, V, Type> {}
|
||||||
|
|
||||||
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
|
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
|
||||||
|
@ -515,6 +528,22 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::ValMut<'a>, K, V, Type> {
|
||||||
|
/// Same as the marker::Mut method, but far more dangerous because ValMut-based iterators:
|
||||||
|
/// - have front and back handles often refering to the same node, so `self` is not unique;
|
||||||
|
/// - hand out mutable references to parts of these slices to the public.
|
||||||
|
fn into_slices_mut(self) -> (&'a [K], &'a mut [V]) {
|
||||||
|
let len = self.len();
|
||||||
|
let leaf = self.node.as_ptr();
|
||||||
|
// SAFETY: The keys and values of a node must always be initialized up to length.
|
||||||
|
let keys = unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&(*leaf).keys), len) };
|
||||||
|
let vals = unsafe {
|
||||||
|
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len)
|
||||||
|
};
|
||||||
|
(keys, vals)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
||||||
/// Adds a key/value pair to the end of the node.
|
/// Adds a key/value pair to the end of the node.
|
||||||
pub fn push(&mut self, key: K, val: V) {
|
pub fn push(&mut self, key: K, val: V) {
|
||||||
|
@ -1053,11 +1082,13 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
|
||||||
let vals = self.node.into_val_slice_mut();
|
let vals = self.node.into_val_slice_mut();
|
||||||
unsafe { vals.get_unchecked_mut(self.idx) }
|
unsafe { vals.get_unchecked_mut(self.idx) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
|
impl<'a, K, V, NodeType> Handle<NodeRef<marker::ValMut<'a>, K, V, NodeType>, marker::KV> {
|
||||||
|
pub fn into_kv_valmut(self) -> (&'a K, &'a mut V) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (keys, vals) = self.node.into_slices_mut();
|
let (keys, vals) = self.node.into_slices_mut();
|
||||||
(keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx))
|
(keys.get_unchecked(self.idx), vals.get_unchecked_mut(self.idx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1558,6 +1589,7 @@ pub mod marker {
|
||||||
pub enum Owned {}
|
pub enum Owned {}
|
||||||
pub struct Immut<'a>(PhantomData<&'a ()>);
|
pub struct Immut<'a>(PhantomData<&'a ()>);
|
||||||
pub struct Mut<'a>(PhantomData<&'a mut ()>);
|
pub struct Mut<'a>(PhantomData<&'a mut ()>);
|
||||||
|
pub struct ValMut<'a>(PhantomData<&'a mut ()>);
|
||||||
|
|
||||||
pub enum KV {}
|
pub enum KV {}
|
||||||
pub enum Edge {}
|
pub enum Edge {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue