diff options
| author | Daniel Micay <danielmicay@gmail.com> | 2013-12-16 05:26:25 -0500 |
|---|---|---|
| committer | Daniel Micay <danielmicay@gmail.com> | 2013-12-16 05:56:42 -0500 |
| commit | e3b168dab34b7fc765aebda301e4a0aeaf556f67 (patch) | |
| tree | 0c71fc8d2c06b5baa3c165be9b6a8cdba1b75284 /src | |
| parent | dc7a2e12223c297695d12ce6e428c44075ed080e (diff) | |
| download | rust-e3b168dab34b7fc765aebda301e4a0aeaf556f67.tar.gz rust-e3b168dab34b7fc765aebda301e4a0aeaf556f67.zip | |
vec: make the move iterator fast for all types
Closes #10976
Diffstat (limited to 'src')
| -rw-r--r-- | src/libstd/hashmap.rs | 13 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 84 |
2 files changed, 47 insertions, 50 deletions
diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 335e77c6478..b5d5b8a6149 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -157,8 +157,7 @@ impl<K:Hash + Eq,V> HashMap<K, V> { 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<K: Hash + Eq, V> HashMap<K, V> { /// pair out of the map in arbitrary order. The map cannot be used after /// calling this. pub fn move_iter(self) -> HashMapMoveIterator<K, V> { - // `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<K, V> { - priv iter: vec::MoveRevIterator<Option<Bucket<K, V>>>, + priv iter: vec::MoveIterator<Option<Bucket<K, V>>>, } /// HashSet iterator @@ -543,7 +541,7 @@ pub struct HashSetIterator<'a, K> { /// HashSet move iterator pub struct HashSetMoveIterator<K> { - priv iter: vec::MoveRevIterator<Option<Bucket<K, ()>>>, + priv iter: vec::MoveIterator<Option<Bucket<K, ()>>>, } impl<'a, K, V> Iterator<(&'a K, &'a V)> for HashMapIterator<'a, K, V> { @@ -729,8 +727,7 @@ impl<T:Hash + Eq> HashSet<T> { /// of the set in arbitrary order. The set cannot be used after calling /// this. pub fn move_iter(self) -> HashSetMoveIterator<T> { - // `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 be9adc91e03..dd926305cc5 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<T> { /// 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<T> { /// ``` fn move_iter(self) -> MoveIterator<T>; /// 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<T>; /** @@ -1469,11 +1466,18 @@ pub trait OwnedVector<T> { } impl<T> OwnedVector<T> for ~[T] { + #[inline] fn move_iter(self) -> MoveIterator<T> { - 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<T> { - 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<T> { - priv v: ~[T], - priv idx: uint, + priv allocation: *mut u8, // the block of memory allocated for the vector + priv iter: VecIterator<'static, T> } impl<T> Iterator<T> for MoveIterator<T> { #[inline] fn next(&mut self) -> Option<T> { - // 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<uint>) { - 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<T> { - priv v: ~[T] -} - -impl<T> Iterator<T> for MoveRevIterator<T> { +impl<T> DoubleEndedIterator<T> for MoveIterator<T> { #[inline] - fn next(&mut self) -> Option<T> { - self.v.pop_opt() + fn next_back(&mut self) -> Option<T> { + unsafe { + self.iter.next_back().map(|x| ptr::read_ptr(x)) + } } +} - #[inline] - fn size_hint(&self) -> (uint, Option<uint>) { - let l = self.v.len(); - (l, Some(l)) +#[unsafe_destructor] +impl<T> Drop for MoveIterator<T> { + fn drop(&mut self) { + unsafe { + // destroy the remaining elements + for x in self.iter { + ptr::read_ptr(x); + } + if owns_managed::<T>() { + 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<T> = Invert<MoveIterator<T>>; + impl<A> FromIterator<A> for ~[A] { fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> ~[A] { let (lower, _) = iterator.size_hint(); |
