diff options
| author | Daniel Micay <danielmicay@gmail.com> | 2012-12-15 13:24:10 -0500 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2012-12-16 19:27:06 -0800 |
| commit | b3463ea65773972e4b5ec9ba4ef35b5f9e595284 (patch) | |
| tree | 10b7289166711edeadf5638cca0db7bfaf11e394 /src/libstd/priority_queue.rs | |
| parent | 6c433f22a152f6825f3610382176aaa191ebf7cb (diff) | |
| download | rust-b3463ea65773972e4b5ec9ba4ef35b5f9e595284.tar.gz rust-b3463ea65773972e4b5ec9ba4ef35b5f9e595284.zip | |
priority_queue: replace copies with moves
Diffstat (limited to 'src/libstd/priority_queue.rs')
| -rw-r--r-- | src/libstd/priority_queue.rs | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index 4f29c1ea970..c62b3897c30 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -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); } |
