Skip to content

Commit fb3483c

Browse files
author
Martin Hafskjold Thoresen
committed
Add initial impl of placement-in for BinaryHeap
1 parent 7d82d95 commit fb3483c

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

src/libcollections/binary_heap.rs

+76-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
#![allow(missing_docs)]
152152
#![stable(feature = "rust1", since = "1.0.0")]
153153

154-
use core::ops::{Deref, DerefMut};
154+
use core::ops::{Deref, DerefMut, Place, Placer, InPlace};
155155
use core::iter::{FromIterator, FusedIterator};
156156
use core::mem::{swap, size_of};
157157
use core::ptr;
@@ -688,6 +688,22 @@ impl<T: Ord> BinaryHeap<T> {
688688
}
689689
}
690690

691+
fn sift_up_ind(&mut self, start: usize, pos: usize) -> usize {
692+
unsafe {
693+
// Take out the value at `pos` and create a hole.
694+
let mut hole = Hole::new(&mut self.data, pos);
695+
696+
while hole.pos() > start {
697+
let parent = (hole.pos() - 1) / 2;
698+
if hole.element() <= hole.get(parent) {
699+
return hole.pos();
700+
}
701+
hole.move_to(parent);
702+
}
703+
hole.pos()
704+
}
705+
}
706+
691707
/// Take an element at `pos` and move it down the heap,
692708
/// while its children are larger.
693709
fn sift_down_range(&mut self, pos: usize, end: usize) {
@@ -889,6 +905,19 @@ impl<T: Ord> BinaryHeap<T> {
889905
}
890906
}
891907

908+
impl<T> BinaryHeap<T>
909+
where T: Clone + Ord {
910+
/// kek
911+
#[unstable(feature = "collection_placement",
912+
reason = "placement protocol is subject to change",
913+
issue = "30172")]
914+
pub fn place(&mut self) -> PlaceIn<T> {
915+
PlaceIn {
916+
heap: self,
917+
}
918+
}
919+
}
920+
892921
/// Hole represents a hole in a slice i.e. an index without valid value
893922
/// (because it was moved from or duplicated).
894923
/// In drop, `Hole` will restore the slice by filling the hole
@@ -1189,3 +1218,49 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
11891218
self.extend(iter.into_iter().cloned());
11901219
}
11911220
}
1221+
1222+
#[unstable(feature = "collection_placement",
1223+
reason = "placement protocol is subject to change",
1224+
issue = "30172")]
1225+
pub struct PlaceIn<'a, T: 'a>
1226+
where T: Clone + Ord {
1227+
heap: &'a mut BinaryHeap<T>,
1228+
}
1229+
1230+
#[unstable(feature = "collection_placement",
1231+
reason = "placement protocol is subject to change",
1232+
issue = "30172")]
1233+
impl<'a, T> Place<T> for PlaceIn<'a, T>
1234+
where T: Clone + Ord {
1235+
fn pointer(&mut self) -> *mut T {
1236+
self.heap.data.place_back().pointer()
1237+
}
1238+
}
1239+
1240+
#[unstable(feature = "collection_placement",
1241+
reason = "placement protocol is subject to change",
1242+
issue = "30172")]
1243+
impl<'a, T> Placer<T> for PlaceIn<'a, T>
1244+
where T: Clone + Ord {
1245+
type Place = PlaceIn<'a, T>;
1246+
1247+
fn make_place(self) -> Self {
1248+
let _ = self.heap.data.place_back().make_place();
1249+
self
1250+
}
1251+
}
1252+
1253+
#[unstable(feature = "collection_placement",
1254+
reason = "placement protocol is subject to change",
1255+
issue = "30172")]
1256+
impl<'a, T> InPlace<T> for PlaceIn<'a, T>
1257+
where T: Clone + Ord {
1258+
type Owner = &'a T;
1259+
1260+
unsafe fn finalize(self) -> &'a T {
1261+
let len = self.heap.len();
1262+
let _ = self.heap.data.place_back().finalize();
1263+
let i = self.heap.sift_up_ind(0, len);
1264+
&mut self.heap.data[i]
1265+
}
1266+
}

src/libcollectionstest/binary_heap.rs

+21
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::panic;
1112
use std::collections::BinaryHeap;
1213
use std::collections::binary_heap::{Drain, PeekMut};
1314

@@ -310,6 +311,26 @@ fn test_extend_specialization() {
310311
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
311312
}
312313

314+
#[test]
315+
fn test_placement() {
316+
let mut a = BinaryHeap::new();
317+
a.place() <- 2;
318+
a.place() <- 4;
319+
a.place() <- 3;
320+
assert_eq!(a.peek(), Some(&4));
321+
assert_eq!(a.len(), 3);
322+
a.place() <- 1;
323+
assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]);
324+
}
325+
326+
#[test]
327+
fn test_placement_panic() {
328+
let mut heap = BinaryHeap::from(vec![1, 2, 3]);
329+
fn mkpanic() -> usize { panic!() }
330+
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { heap.place() <- mkpanic(); }));
331+
assert_eq!(heap.len(), 3);
332+
}
333+
313334
#[allow(dead_code)]
314335
fn assert_covariance() {
315336
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {

0 commit comments

Comments
 (0)