Skip to content

Commit 6218462

Browse files
committed
cleanup: to be rebased
1 parent b069a5e commit 6218462

File tree

2 files changed

+298
-292
lines changed

2 files changed

+298
-292
lines changed

src/libstd/collections/hash/map.rs

+82-45
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use cmp::{max, Eq, PartialEq};
1919
use default::Default;
2020
use fmt::{self, Debug};
2121
use hash::{self, Hash, SipHasher};
22-
use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
22+
use iter::{Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
2323
use marker::Sized;
2424
use mem::{self, replace};
2525
use num::{Int, UnsignedInt};
@@ -38,6 +38,8 @@ use super::table::{
3838
RawTable,
3939
SafeHash,
4040
TableRef,
41+
PartialRawTable,
42+
Put,
4143
};
4244
use super::table::BucketState::{
4345
Empty,
@@ -307,7 +309,6 @@ fn test_resize_policy() {
307309
/// }
308310
/// ```
309311
#[stable(feature = "rust1", since = "1.0.0")]
310-
#[derive(Clone)]
311312
pub struct HashMap<K, V, S = RandomState> {
312313
// All hashes are keyed on these values, to prevent hash collision attacks.
313314
hash_state: S,
@@ -389,7 +390,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
389390
/// to recalculate it.
390391
///
391392
/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
392-
fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
393+
fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
393394
mut ib: usize,
394395
mut hash: SafeHash,
395396
mut k: K,
@@ -400,9 +401,10 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
400401
let table = bucket.table(); // FIXME "lifetime too short".
401402
table.size()
402403
};
403-
// There can be at most `size - dib` buckets to displace, because
404+
let mut bucket = bucket.stash();
405+
// There can be at most `size - displacement` buckets to displace, because
404406
// in the worst case, there are `size` elements and we already are
405-
// `distance` buckets away from the initial one.
407+
// `displacement` buckets away from the initial one.
406408
let idx_end = starting_index + size - bucket.displacement();
407409

408410
loop {
@@ -420,14 +422,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
420422
let b = bucket.put(old_hash, old_key, old_val);
421423
// Now that it's stolen, just read the value's pointer
422424
// right out of the table!
423-
let starting_bucket = Bucket::at_index(b.into_table(), starting_index).ok()
424-
.unwrap()
425-
.peek();
426-
if let Full(starting_bucket) = starting_bucket {
427-
return starting_bucket.into_mut_refs().1;
428-
} else {
429-
panic!("Expected full bucket");
430-
}
425+
return b.into_table().into_mut_refs().1;
431426
},
432427
Full(bucket) => bucket
433428
};
@@ -450,7 +445,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
450445

451446
// Performs insertion with relaxed requirements.
452447
// The caller should ensure that invariants of Robin Hood linear probing hold.
453-
fn insert_hashed_ordered<M, K, V>(arg: M, h: SafeHash, k: K, v: V) -> M
448+
fn insert_hashed_ordered<M: Put, K, V>(arg: M, h: SafeHash, k: K, v: V) -> M
454449
where RawTable<K, V>: BorrowFromMut<M>
455450
{
456451
let table = TableRef(arg);
@@ -720,27 +715,34 @@ impl<K, V, S, H> HashMap<K, V, S>
720715
// ^ exit once table.size == 0
721716
let idx_end = bucket.index() + old_capacity;
722717

723-
while bucket.index() != idx_end {
724-
bucket = match bucket.peek() {
725-
Full(bucket) => {
726-
let h = *bucket.read().0;
727-
let (b, k, v) = bucket.take();
728-
729-
if let Some(ref mut dest) = destination {
730-
insert_hashed_ordered(dest, h, k, v);
718+
if let Some(mut dest) = destination {
719+
while bucket.index() != idx_end {
720+
bucket = match bucket.peek() {
721+
Full(bucket) => {
722+
let h = *bucket.read().0;
723+
let (b, k, v) = bucket.take();
724+
insert_hashed_ordered(&mut dest, h, k, v);
731725
b.into_bucket()
732-
} else {
733-
// Resizing in-place.
734-
insert_hashed_ordered(b.into_bucket(), h, k, v)
735726
}
736-
}
737-
Empty(b) => b.into_bucket()
738-
};
739-
bucket.next(); // wraps at old_capacity
740-
}
727+
Empty(b) => b.into_bucket()
728+
};
729+
bucket.next(); // wraps at old_capacity
730+
}
741731

742-
if let Some(dest) = destination {
743732
replace(bucket.into_table(), dest);
733+
} else {
734+
while bucket.index() != idx_end {
735+
bucket = match bucket.peek() {
736+
Full(bucket) => {
737+
let h = *bucket.read().0;
738+
let (b, k, v) = bucket.take();
739+
// Resizing in-place.
740+
insert_hashed_ordered(b.into_bucket(), h, k, v)
741+
}
742+
Empty(b) => b.into_bucket()
743+
};
744+
bucket.next(); // wraps at old_capacity
745+
}
744746
}
745747
}
746748

@@ -769,11 +771,12 @@ impl<K, V, S, H> HashMap<K, V, S>
769771
debug_assert!(self.len() <= min_capacity);
770772

771773
if self.table.capacity() != min_capacity {
772-
let old_table = replace(&mut self.table, RawTable::new(min_capacity));
774+
let mut old_table = PartialRawTable::new(replace(&mut self.table,
775+
RawTable::new(min_capacity)));
773776
let old_size = old_table.size();
774777

775778
// Shrink the table. Naive algorithm for resizing:
776-
for (h, k, v) in old_table.into_iter() {
779+
while let Some((h, k, v)) = old_table.take_front() {
777780
self.insert_hashed_nocheck(h, k, v);
778781
}
779782

@@ -925,11 +928,8 @@ impl<K, V, S, H> HashMap<K, V, S>
925928
/// ```
926929
#[stable(feature = "rust1", since = "1.0.0")]
927930
pub fn into_iter(self) -> IntoIter<K, V> {
928-
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
929-
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
930-
931931
IntoIter {
932-
inner: self.table.into_iter().map(last_two)
932+
table: PartialRawTable::new(self.table)
933933
}
934934
}
935935

@@ -1231,6 +1231,37 @@ impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
12311231
}
12321232
}
12331233

1234+
impl<K: Clone, V: Clone, S: Clone> Clone for HashMap<K, V, S> {
1235+
fn clone(&self) -> HashMap<K, V, S> {
1236+
let mut new_ht = RawTable::new_uninitialized(self.table.capacity());
1237+
1238+
let cap = self.table.capacity();
1239+
if let Ok(mut buckets) = Bucket::at_index(&self.table, 0) {
1240+
while buckets.index() != cap {
1241+
match buckets.peek() {
1242+
Full(full) => {
1243+
let (h, k, v) = {
1244+
let (h, k, v) = full.read();
1245+
(*h, k.clone(), v.clone())
1246+
};
1247+
new_ht.push_back(Some((h, k, v)));
1248+
}
1249+
Empty(..) => {
1250+
new_ht.push_back(None);
1251+
}
1252+
}
1253+
buckets.next();
1254+
}
1255+
}
1256+
1257+
HashMap {
1258+
table: new_ht.unwrap(),
1259+
hash_state: self.hash_state.clone(),
1260+
resize_policy: self.resize_policy.clone(),
1261+
}
1262+
}
1263+
}
1264+
12341265
/// HashMap iterator.
12351266
#[stable(feature = "rust1", since = "1.0.0")]
12361267
pub struct Iter<'a, K: 'a, V: 'a> {
@@ -1258,7 +1289,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
12581289
/// HashMap move iterator.
12591290
#[stable(feature = "rust1", since = "1.0.0")]
12601291
pub struct IntoIter<K, V> {
1261-
inner: iter::Map<table::IntoIter<K, V>, fn((SafeHash, K, V)) -> (K, V)>
1292+
table: PartialRawTable<K, V>,
12621293
}
12631294

12641295
/// HashMap keys iterator.
@@ -1427,17 +1458,17 @@ impl<K, V> Iterator for IntoIter<K, V> {
14271458

14281459
#[inline]
14291460
fn next(&mut self) -> Option<(K, V)> {
1430-
self.inner.next()
1461+
self.table.take_front().map(|(_, k, v)| (k, v))
14311462
}
14321463

14331464
#[inline]
14341465
fn size_hint(&self) -> (usize, Option<usize>) {
1435-
self.inner.size_hint()
1466+
(self.table.size(), Some(self.table.size()))
14361467
}
14371468
}
14381469
#[stable(feature = "rust1", since = "1.0.0")]
14391470
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
1440-
#[inline] fn len(&self) -> usize { self.inner.len() }
1471+
#[inline] fn len(&self) -> usize { self.table.size() }
14411472
}
14421473

14431474
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1469,13 +1500,19 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> {
14691500
type Item = (K, V);
14701501

14711502
fn next(&mut self) -> Option<(K, V)> {
1472-
if let Some(ref mut bucket) = self.inner {
1503+
if let Some(mut bucket) = self.inner.take() {
14731504
let cap = bucket.table().capacity();
14741505
while bucket.index() < cap {
1475-
if let Some(kv_pair) = bucket.peek_take() {
1476-
return Some(kv_pair);
1506+
match bucket.peek() {
1507+
Full(bucket) => {
1508+
let (empty, k, v) = bucket.take();
1509+
self.inner = Some(empty.into_bucket());
1510+
return Some((k, v));
1511+
}
1512+
Empty(empty) => {
1513+
bucket = empty.into_next();
1514+
}
14771515
}
1478-
bucket.next();
14791516
}
14801517
}
14811518

0 commit comments

Comments
 (0)