diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 335e77c647803..b5d5b8a6149bd 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -157,8 +157,7 @@ impl HashMap { vec::from_fn(new_capacity, |_| None)); self.size = 0; - // move_rev_iter is more efficient - for bucket in old_buckets.move_rev_iter() { + for bucket in old_buckets.move_iter() { self.insert_opt_bucket(bucket); } } @@ -477,8 +476,7 @@ impl HashMap { /// pair out of the map in arbitrary order. The map cannot be used after /// calling this. pub fn move_iter(self) -> HashMapMoveIterator { - // `move_rev_iter` is more efficient than `move_iter` for vectors - HashMapMoveIterator {iter: self.buckets.move_rev_iter()} + HashMapMoveIterator {iter: self.buckets.move_iter()} } } @@ -532,7 +530,7 @@ pub struct HashMapMutIterator<'a, K, V> { /// HashMap move iterator pub struct HashMapMoveIterator { - priv iter: vec::MoveRevIterator>>, + priv iter: vec::MoveIterator>>, } /// HashSet iterator @@ -543,7 +541,7 @@ pub struct HashSetIterator<'a, K> { /// HashSet move iterator pub struct HashSetMoveIterator { - priv iter: vec::MoveRevIterator>>, + priv iter: vec::MoveIterator>>, } impl<'a, K, V> Iterator<(&'a K, &'a V)> for HashMapIterator<'a, K, V> { @@ -729,8 +727,7 @@ impl HashSet { /// of the set in arbitrary order. The set cannot be used after calling /// this. pub fn move_iter(self) -> HashSetMoveIterator { - // `move_rev_iter` is more efficient than `move_iter` for vectors - HashSetMoveIterator {iter: self.map.buckets.move_rev_iter()} + HashSetMoveIterator {iter: self.map.buckets.move_iter()} } /// Visit the values representing the difference diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index be9adc91e0311..dd926305cc514 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -102,20 +102,21 @@ There are a number of free functions that create or take vectors, for example: #[warn(non_camel_case_types)]; use cast; +use ops::Drop; use clone::{Clone, DeepClone}; use container::{Container, Mutable}; use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater}; use cmp; use default::Default; use iter::*; -use libc::c_void; +use libc::{c_char, c_void}; use num::{Integer, CheckedAdd, Saturating}; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; use ptr; use ptr::RawPtr; -use rt::global_heap::malloc_raw; -use rt::global_heap::realloc_raw; +use rt::global_heap::{malloc_raw, realloc_raw, exchange_free}; +use rt::local_heap::local_free; use mem; use mem::size_of; use uint; @@ -1325,9 +1326,6 @@ pub trait OwnedVector { /// value out of the vector (from start to end). The vector cannot /// be used after calling this. /// - /// Note that this performs O(n) swaps, and so `move_rev_iter` - /// (which just calls `pop` repeatedly) is more efficient. - /// /// # Examples /// /// ```rust @@ -1339,8 +1337,7 @@ pub trait OwnedVector { /// ``` fn move_iter(self) -> MoveIterator; /// Creates a consuming iterator that moves out of the vector in - /// reverse order. Also see `move_iter`, however note that this - /// is more efficient. + /// reverse order. fn move_rev_iter(self) -> MoveRevIterator; /** @@ -1469,11 +1466,18 @@ pub trait OwnedVector { } impl OwnedVector for ~[T] { + #[inline] fn move_iter(self) -> MoveIterator { - MoveIterator { v: self, idx: 0 } + unsafe { + let iter = cast::transmute(self.iter()); + let ptr = cast::transmute(self); + MoveIterator { allocation: ptr, iter: iter } + } } + + #[inline] fn move_rev_iter(self) -> MoveRevIterator { - MoveRevIterator { v: self } + self.move_iter().invert() } fn reserve(&mut self, n: uint) { @@ -2660,58 +2664,54 @@ impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunkIter<'a, T> { } /// An iterator that moves out of a vector. -#[deriving(Clone)] pub struct MoveIterator { - priv v: ~[T], - priv idx: uint, + priv allocation: *mut u8, // the block of memory allocated for the vector + priv iter: VecIterator<'static, T> } impl Iterator for MoveIterator { #[inline] fn next(&mut self) -> Option { - // this is peculiar, but is required for safety with respect - // to dtors. It traverses the first half of the vec, and - // removes them by swapping them with the last element (and - // popping), which results in the second half in reverse - // order, and so these can just be pop'd off. That is, - // - // [1,2,3,4,5] => 1, [5,2,3,4] => 2, [5,4,3] => 3, [5,4] => 4, - // [5] -> 5, [] - let l = self.v.len(); - if self.idx < l { - self.v.swap(self.idx, l - 1); - self.idx += 1; + unsafe { + self.iter.next().map(|x| ptr::read_ptr(x)) } - - self.v.pop_opt() } #[inline] fn size_hint(&self) -> (uint, Option) { - let l = self.v.len(); - (l, Some(l)) + self.iter.size_hint() } } -/// An iterator that moves out of a vector in reverse order. -#[deriving(Clone)] -pub struct MoveRevIterator { - priv v: ~[T] -} - -impl Iterator for MoveRevIterator { +impl DoubleEndedIterator for MoveIterator { #[inline] - fn next(&mut self) -> Option { - self.v.pop_opt() + fn next_back(&mut self) -> Option { + unsafe { + self.iter.next_back().map(|x| ptr::read_ptr(x)) + } } +} - #[inline] - fn size_hint(&self) -> (uint, Option) { - let l = self.v.len(); - (l, Some(l)) +#[unsafe_destructor] +impl Drop for MoveIterator { + fn drop(&mut self) { + unsafe { + // destroy the remaining elements + for x in self.iter { + ptr::read_ptr(x); + } + if owns_managed::() { + local_free(self.allocation as *u8 as *c_char) + } else { + exchange_free(self.allocation as *u8 as *c_char) + } + } } } +/// An iterator that moves out of a vector in reverse order. +pub type MoveRevIterator = Invert>; + impl FromIterator for ~[A] { fn from_iterator>(iterator: &mut T) -> ~[A] { let (lower, _) = iterator.size_hint();