mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-28 03:07:24 +03:00
Auto merge of #39062 - martinhath:placement-in-binaryheap, r=nagisa
Implement placement-in protocol for `BinaryHeap` Related to #30172, and loosley based on #38551. At the moment, this PR is in a pretty rough state, but I wanted to get some feedback to see if I'm going in the right direction. I hope the Mentor label of #30172 is still applicable, even though it's a year old 😄
This commit is contained in:
@@ -151,7 +151,7 @@
|
|||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut, Place, Placer, InPlace};
|
||||||
use core::iter::{FromIterator, FusedIterator};
|
use core::iter::{FromIterator, FusedIterator};
|
||||||
use core::mem::{swap, size_of};
|
use core::mem::{swap, size_of};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
@@ -673,7 +673,7 @@ pub fn into_sorted_vec(mut self) -> Vec<T> {
|
|||||||
// the hole is filled back at the end of its scope, even on panic.
|
// the hole is filled back at the end of its scope, even on panic.
|
||||||
// Using a hole reduces the constant factor compared to using swaps,
|
// Using a hole reduces the constant factor compared to using swaps,
|
||||||
// which involves twice as many moves.
|
// which involves twice as many moves.
|
||||||
fn sift_up(&mut self, start: usize, pos: usize) {
|
fn sift_up(&mut self, start: usize, pos: usize) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Take out the value at `pos` and create a hole.
|
// Take out the value at `pos` and create a hole.
|
||||||
let mut hole = Hole::new(&mut self.data, pos);
|
let mut hole = Hole::new(&mut self.data, pos);
|
||||||
@@ -685,6 +685,7 @@ fn sift_up(&mut self, start: usize, pos: usize) {
|
|||||||
}
|
}
|
||||||
hole.move_to(parent);
|
hole.move_to(parent);
|
||||||
}
|
}
|
||||||
|
hole.pos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,3 +1190,56 @@ fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
|
|||||||
self.extend(iter.into_iter().cloned());
|
self.extend(iter.into_iter().cloned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "collection_placement",
|
||||||
|
reason = "placement protocol is subject to change",
|
||||||
|
issue = "30172")]
|
||||||
|
pub struct BinaryHeapPlace<'a, T: 'a>
|
||||||
|
where T: Clone + Ord {
|
||||||
|
heap: *mut BinaryHeap<T>,
|
||||||
|
place: vec::PlaceBack<'a, T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "collection_placement",
|
||||||
|
reason = "placement protocol is subject to change",
|
||||||
|
issue = "30172")]
|
||||||
|
impl<'a, T: 'a> Placer<T> for &'a mut BinaryHeap<T>
|
||||||
|
where T: Clone + Ord {
|
||||||
|
type Place = BinaryHeapPlace<'a, T>;
|
||||||
|
|
||||||
|
fn make_place(self) -> Self::Place {
|
||||||
|
let ptr = self as *mut BinaryHeap<T>;
|
||||||
|
let place = Placer::make_place(self.data.place_back());
|
||||||
|
BinaryHeapPlace {
|
||||||
|
heap: ptr,
|
||||||
|
place: place,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "collection_placement",
|
||||||
|
reason = "placement protocol is subject to change",
|
||||||
|
issue = "30172")]
|
||||||
|
impl<'a, T> Place<T> for BinaryHeapPlace<'a, T>
|
||||||
|
where T: Clone + Ord {
|
||||||
|
fn pointer(&mut self) -> *mut T {
|
||||||
|
self.place.pointer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "collection_placement",
|
||||||
|
reason = "placement protocol is subject to change",
|
||||||
|
issue = "30172")]
|
||||||
|
impl<'a, T> InPlace<T> for BinaryHeapPlace<'a, T>
|
||||||
|
where T: Clone + Ord {
|
||||||
|
type Owner = &'a T;
|
||||||
|
|
||||||
|
unsafe fn finalize(self) -> &'a T {
|
||||||
|
self.place.finalize();
|
||||||
|
|
||||||
|
let heap: &mut BinaryHeap<T> = &mut *self.heap;
|
||||||
|
let len = heap.len();
|
||||||
|
let i = heap.sift_up(0, len - 1);
|
||||||
|
heap.data.get_unchecked(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use std::panic;
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
use std::collections::binary_heap::{Drain, PeekMut};
|
use std::collections::binary_heap::{Drain, PeekMut};
|
||||||
|
|
||||||
@@ -310,6 +311,26 @@ fn test_extend_specialization() {
|
|||||||
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
|
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_placement() {
|
||||||
|
let mut a = BinaryHeap::new();
|
||||||
|
&mut a <- 2;
|
||||||
|
&mut a <- 4;
|
||||||
|
&mut a <- 3;
|
||||||
|
assert_eq!(a.peek(), Some(&4));
|
||||||
|
assert_eq!(a.len(), 3);
|
||||||
|
&mut a <- 1;
|
||||||
|
assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_placement_panic() {
|
||||||
|
let mut heap = BinaryHeap::from(vec![1, 2, 3]);
|
||||||
|
fn mkpanic() -> usize { panic!() }
|
||||||
|
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); }));
|
||||||
|
assert_eq!(heap.len(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn assert_covariance() {
|
fn assert_covariance() {
|
||||||
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
|
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
|
||||||
|
|||||||
Reference in New Issue
Block a user