about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-12-16 05:26:25 -0500
committerDaniel Micay <danielmicay@gmail.com>2013-12-16 05:56:42 -0500
commite3b168dab34b7fc765aebda301e4a0aeaf556f67 (patch)
tree0c71fc8d2c06b5baa3c165be9b6a8cdba1b75284 /src
parentdc7a2e12223c297695d12ce6e428c44075ed080e (diff)
downloadrust-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.rs13
-rw-r--r--src/libstd/vec.rs84
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();