priority_queue: replace copies with moves

This commit is contained in:
Daniel Micay 2012-12-15 13:24:10 -05:00 committed by Brian Anderson
parent 6c433f22a1
commit b3463ea657

View File

@ -1,12 +1,18 @@
/// A priority queue implemented with a binary heap
use core::cmp::Ord;
use ptr::addr_of;
pub struct PriorityQueue <T: Copy Ord>{
#[abi = "rust-intrinsic"]
extern "C" mod rusti {
fn move_val_init<T>(dst: &mut T, -src: T);
}
pub struct PriorityQueue <T: Ord>{
priv data: ~[T],
}
impl <T: Copy Ord> PriorityQueue<T> {
impl <T: Ord> PriorityQueue<T> {
/// Returns the greatest item in the queue - fails if empty
pure fn top(&self) -> &self/T { &self.data[0] }
@ -97,26 +103,33 @@ impl <T: Copy Ord> PriorityQueue<T> {
q
}
priv fn siftup(&mut self, start: uint, pos: uint) {
// The implementations of siftup and siftdown use unsafe blocks in order to
// move an element out of the vector (leaving behind a junk element), shift
// along the others and move it back into the vector over the junk element.
// This reduces the constant factor compared to using swaps, which involves
// twice as many moves.
priv fn siftup(&mut self, start: uint, pos: uint) unsafe {
let mut pos = pos;
let new = self.data[pos];
let new = move *addr_of(&self.data[pos]);
while pos > start {
let parent = (pos - 1) >> 1;
if new > self.data[parent] {
self.data[pos] = self.data[parent];
rusti::move_val_init(&mut self.data[pos],
move *addr_of(&self.data[parent]));
pos = parent;
loop
}
break
}
self.data[pos] = new;
rusti::move_val_init(&mut self.data[pos], move new);
}
priv fn siftdown_range(&mut self, pos: uint, end: uint) {
priv fn siftdown_range(&mut self, pos: uint, end: uint) unsafe {
let mut pos = pos;
let start = pos;
let new = self.data[pos];
let new = move *addr_of(&self.data[pos]);
let mut child = 2 * pos + 1;
while child < end {
@ -124,11 +137,12 @@ impl <T: Copy Ord> PriorityQueue<T> {
if right < end && !(self.data[child] > self.data[right]) {
child = right;
}
self.data[pos] = self.data[child];
rusti::move_val_init(&mut self.data[pos],
move *addr_of(&self.data[child]));
pos = child;
child = 2 * pos + 1;
}
self.data[pos] = new;
rusti::move_val_init(&mut self.data[pos], move new);
self.siftup(start, pos);
}