auto merge of #10995 : thestinger/rust/fast_move_iter, r=huonw
Closes #10976
Taken from 863fbaaa12
, so it will be easily updated to the better vector representation too.
This commit is contained in:
commit
7b42497453
@ -157,8 +157,7 @@ fn resize(&mut self, new_capacity: uint) {
|
||||
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 @@ pub fn mut_iter<'a>(&'a mut self) -> HashMapMutIterator<'a, 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 @@ pub fn iter<'a>(&'a self) -> HashSetIterator<'a, 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
|
||||
|
@ -102,20 +102,21 @@
|
||||
#[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,57 +2664,53 @@ fn next_back(&mut self) -> Option<&'a mut [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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DoubleEndedIterator<T> for MoveIterator<T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
unsafe {
|
||||
self.iter.next_back().map(|x| ptr::read_ptr(x))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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.
|
||||
#[deriving(Clone)]
|
||||
pub struct MoveRevIterator<T> {
|
||||
priv v: ~[T]
|
||||
}
|
||||
|
||||
impl<T> Iterator<T> for MoveRevIterator<T> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.v.pop_opt()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let l = self.v.len();
|
||||
(l, Some(l))
|
||||
}
|
||||
}
|
||||
pub type MoveRevIterator<T> = Invert<MoveIterator<T>>;
|
||||
|
||||
impl<A> FromIterator<A> for ~[A] {
|
||||
fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> ~[A] {
|
||||
|
Loading…
Reference in New Issue
Block a user