Skip to content

Commit edcddb1

Browse files
committed
f
1 parent 596b0e9 commit edcddb1

File tree

2 files changed

+76
-64
lines changed

2 files changed

+76
-64
lines changed

src/libstd/collections/hash/map.rs

+43-44
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use iter::{Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator,
2323
use marker::Sized;
2424
use mem::{self, swap, replace};
2525
use num::{Int, UnsignedInt};
26-
use ops::{Deref, DerefMut, Drop, FnMut, Index, IndexMut};
26+
use ops::{Drop, FnMut, Index, IndexMut};
2727
use option::Option::{self, Some, None};
2828
use rand::{self, Rng};
2929
use result::Result::{self, Ok, Err};
@@ -33,7 +33,6 @@ use super::table::{
3333
Bucket,
3434
EmptyBucket,
3535
FullBucket,
36-
FullBucketImm,
3736
FullBucketMut,
3837
RawTable,
3938
SafeHash,
@@ -441,19 +440,19 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
441440

442441
// Performs insertion with relaxed requirements.
443442
// The caller should ensure that invariants of Robin Hood linear probing hold.
444-
fn insert_hashed_ordered<M: Put, K, V>(arg: M, hash: SafeHash, key: K, val: V) -> M
443+
fn insert_hashed_ordered<M: Put, K, V>(table: M, hash: SafeHash, key: K, val: V) -> M
445444
where M: BorrowMut<RawTable<K, V>>
446445
{
447446
let cap = table.borrow().capacity();
448-
let mut buckets = Bucket::new(table, h).unwrap();
447+
let mut buckets = Bucket::new(table, hash).unwrap();
449448
let ib = buckets.index();
450449

451450
while buckets.index() != ib + cap {
452451
// We don't need to compare hashes for value swap.
453452
// Not even DIBs for Robin Hood.
454453
buckets = match buckets.peek() {
455454
Empty(empty) => {
456-
return empty.put(h, k, v).into_table();
455+
return empty.put(hash, key, val).into_table();
457456
}
458457
Full(full) => full.into_bucket()
459458
};
@@ -474,19 +473,19 @@ impl<K, V, S> HashMap<K, V, S>
474473
/// If you already have the hash for the key lying around, use
475474
/// search_hashed.
476475
fn search<'a, Q: ?Sized>(&'a self, q: &Q)
477-
-> Option<InternalEntry<K, V, &'a RawTable<K, V>>>
476+
-> (InternalEntry<K, V, &'a RawTable<K, V>>, SafeHash)
478477
where K: Borrow<Q>, Q: Eq + Hash
479478
{
480479
let hash = self.make_hash(q);
481-
search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
480+
(search_hashed(&self.table, hash, |k| q.eq(k.borrow())), hash)
482481
}
483482

484483
fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q)
485-
-> Option<InternalEntry<K, V, &'a mut RawTable<K, V>>>
484+
-> (InternalEntry<K, V, &'a mut RawTable<K, V>>, SafeHash)
486485
where K: Borrow<Q>, Q: Eq + Hash
487486
{
488487
let hash = self.make_hash(q);
489-
search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
488+
(search_hashed(&mut self.table, hash, |k| q.eq(k.borrow())), hash)
490489
}
491490
}
492491

@@ -645,7 +644,7 @@ impl<K, V, S> HashMap<K, V, S>
645644
// Grow the table.
646645
let is_inplace = self.table.grow_inplace(new_capacity);
647646

648-
let mut destination = if is_inplace {
647+
let destination = if is_inplace {
649648
// Resizing in-place.
650649
None
651650
} else {
@@ -764,9 +763,9 @@ impl<K, V, S> HashMap<K, V, S>
764763

765764
// Shrink the table. Naive algorithm for resizing:
766765
while let Some((h, k, v)) = old_table.take_front() {
767-
match search_hashed(&mut self.table, hash, |key| *key == k) {
766+
match search_hashed(&mut self.table, h, |key| *key == k) {
768767
InternalEntry::Vacant(entry) => {
769-
entry.insert(hash, k, v);
768+
entry.insert(h, k, v);
770769
}
771770
InternalEntry::Occupied(mut entry) => {
772771
entry.insert(v);
@@ -779,24 +778,24 @@ impl<K, V, S> HashMap<K, V, S>
779778
}
780779
}
781780

782-
/// Insert a pre-hashed key-value pair, without first checking
783-
/// that there's enough room in the buckets. Returns a reference to the
784-
/// newly insert value.
785-
///
786-
/// If the key already exists, the hashtable will be returned untouched
787-
/// and a reference to the existing element will be returned.
788-
fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> Option<V> {
789-
match search_hashed(&mut self.table, hash, |key| *key == k) {
790-
InternalEntry::Vacant(entry) => {
791-
entry.insert(hash, k, v);
792-
return None;
793-
}
794-
InternalEntry::Occupied(mut entry) => {
795-
return Some(entry.insert(v));
796-
}
797-
InternalEntry::TableIsEmpty => unreachable!()
798-
}
799-
}
781+
// /// Insert a pre-hashed key-value pair, without first checking
782+
// /// that there's enough room in the buckets. Returns a reference to the
783+
// /// newly insert value.
784+
// ///
785+
// /// If the key already exists, the hashtable will be returned untouched
786+
// /// and a reference to the existing element will be returned.
787+
// fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> Option<V> {
788+
// match search_hashed(&mut self.table, hash, |key| *key == k) {
789+
// InternalEntry::Vacant(entry) => {
790+
// entry.insert(hash, k, v);
791+
// return None;
792+
// }
793+
// InternalEntry::Occupied(mut entry) => {
794+
// return Some(entry.insert(v));
795+
// }
796+
// InternalEntry::TableIsEmpty => unreachable!()
797+
// }
798+
// }
800799

801800
/// An iterator visiting all keys in arbitrary order.
802801
/// Iterator element type is `&'a K`.
@@ -935,13 +934,13 @@ impl<K, V, S> HashMap<K, V, S>
935934
self.reserve(1);
936935

937936
match self.search_mut(&key) {
938-
InternalEntry::Occupied(state) => Occupied(state),
939-
InternalEntry::Vacant(bucket) => Vacant(VacantEntry {
940-
elem: bucket,
941-
hash: hash,
937+
(InternalEntry::Occupied(state), _) => Occupied(state),
938+
(InternalEntry::Vacant(bucket), hash) => Vacant(VacantEntry {
942939
key: key,
940+
hash: hash,
941+
elem: bucket,
943942
}),
944-
InternalEntry::TableIsEmpty => unreachable!()
943+
(InternalEntry::TableIsEmpty, _) => unreachable!()
945944
}
946945
}
947946

@@ -1043,7 +1042,7 @@ impl<K, V, S> HashMap<K, V, S>
10431042
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
10441043
where K: Borrow<Q>, Q: Hash + Eq
10451044
{
1046-
self.search(k).into_option().map(|bucket| bucket.into_refs().1)
1045+
self.search(k).0.into_option().map(|bucket| bucket.into_refs().1)
10471046
}
10481047

10491048
/// Returns true if the map contains a value for the specified key.
@@ -1066,7 +1065,7 @@ impl<K, V, S> HashMap<K, V, S>
10661065
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
10671066
where K: Borrow<Q>, Q: Hash + Eq
10681067
{
1069-
self.search(k).into_option().is_some()
1068+
self.search(k).0.into_option().is_some()
10701069
}
10711070

10721071
/// Returns a mutable reference to the value corresponding to the key.
@@ -1092,7 +1091,7 @@ impl<K, V, S> HashMap<K, V, S>
10921091
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
10931092
where K: Borrow<Q>, Q: Hash + Eq
10941093
{
1095-
self.search_mut(k).into_option().map(|bucket| bucket.into_mut_refs().1)
1094+
self.search_mut(k).0.into_option().map(|bucket| bucket.into_mut_refs().1)
10961095
}
10971096

10981097
/// Inserts a key-value pair from the map. If the key already had a value
@@ -1116,14 +1115,14 @@ impl<K, V, S> HashMap<K, V, S>
11161115
self.reserve(1);
11171116

11181117
match self.search_mut(&key) {
1119-
InternalEntry::Vacant(entry) => {
1118+
(InternalEntry::Occupied(mut entry), _) => {
1119+
return Some(entry.insert(value));
1120+
}
1121+
(InternalEntry::Vacant(entry), hash) => {
11201122
entry.insert(hash, key, value);
11211123
return None;
11221124
}
1123-
InternalEntry::Occupied(mut entry) => {
1124-
return Some(entry.insert(value));
1125-
}
1126-
InternalEntry::TableIsEmpty => unreachable!()
1125+
(InternalEntry::TableIsEmpty, _) => unreachable!()
11271126
}
11281127
}
11291128

@@ -1152,7 +1151,7 @@ impl<K, V, S> HashMap<K, V, S>
11521151
return None
11531152
}
11541153

1155-
self.search_mut(k).into_option().map(|bucket| pop_internal(bucket).1)
1154+
self.search_mut(k).0.into_option().map(|bucket| pop_internal(bucket).1)
11561155
}
11571156
}
11581157

src/libstd/collections/hash/table.rs

+33-20
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use clone::Clone;
1717
use cmp;
1818
use hash::{Hash, Hasher};
1919
use iter::{Iterator, IteratorExt, count};
20-
use marker::{Copy, Sized};
20+
use marker::{Copy, Sized, PhantomData, PhantomFn};
2121
use mem::{self, min_align_of, size_of};
2222
use num::{Int, UnsignedInt};
23-
use ops::{Deref, DerefMut, Drop};
23+
use ops::Drop;
2424
use option::Option::{self, Some, None};
2525
use ptr::{self, Unique, PtrExt};
2626
use result::Result::{self, Ok, Err};
@@ -82,6 +82,8 @@ pub struct Bucket<K, V, M, S = ()> {
8282
idx: usize,
8383
capacity: usize,
8484
table: M,
85+
marker: PhantomData<S>,
86+
8587
}
8688

8789
impl<K, V> Copy for RawBucket<K, V> {}
@@ -161,19 +163,21 @@ impl<K, V, M, S> Borrow<RawTable<K, V>> for Bucket<K, V, M, S>
161163
where M: Borrow<RawTable<K, V>>
162164
{
163165
fn borrow(&self) -> &RawTable<K, V> {
164-
self.table.borrow()
166+
self.table.borrow().borrow()
165167
}
166168
}
167169

168170
impl<K, V, M, S> BorrowMut<RawTable<K, V>> for Bucket<K, V, M, S>
169-
where M: Borrow<RawTable<K, V>>
171+
where M: BorrowMut<RawTable<K, V>>
170172
{
171173
fn borrow_mut(&mut self) -> &mut RawTable<K, V> {
172-
self.table.borrow_mut()
174+
self.table.borrow_mut().borrow_mut()
173175
}
174176
}
175177

176-
pub trait Put {}
178+
/// `Put` is implemented for types which that provide access to a table and cannot be invalidated
179+
/// by filling a bucket. A similar implementation for `Take` is possible.
180+
pub trait Put: PhantomFn<Self> {}
177181
impl<K, V> Put for RawTable<K, V> {}
178182
impl<'t, K, V> Put for &'t mut RawTable<K, V> {}
179183
impl<K, V, M: Put> Put for Bucket<K, V, M> {}
@@ -220,6 +224,7 @@ impl<K, V, M> Bucket<K, V, M> where M: Borrow<RawTable<K, V>> {
220224
idx: idx,
221225
capacity: capacity,
222226
table: table,
227+
marker: PhantomData,
223228
};
224229
if capacity == 0 {
225230
Err(bucket.unsafe_cast())
@@ -275,6 +280,7 @@ impl<K, V, M, S> Bucket<K, V, M, S> where M: Borrow<RawTable<K, V>> {
275280
idx: self.idx,
276281
capacity: self.capacity,
277282
table: self.table,
283+
marker: PhantomData,
278284
}
279285
}
280286

@@ -296,6 +302,7 @@ impl<K, V, M, S> Bucket<K, V, M, S> where M: Borrow<RawTable<K, V>> {
296302
idx: self.idx,
297303
capacity: self.capacity,
298304
table: self,
305+
marker: PhantomData,
299306
}
300307
}
301308
}
@@ -307,6 +314,7 @@ impl<K, V, M> EmptyBucket<K, V, M> where M: Borrow<RawTable<K, V>> {
307314
idx: self.idx,
308315
capacity: self.capacity,
309316
raw: self.raw,
317+
marker: PhantomData,
310318
};
311319

312320
match self.into_next().peek() {
@@ -477,8 +485,8 @@ impl<K, V> RawTable<K, V> {
477485
}
478486
} else {
479487
RawBucket {
480-
hash: self.middle.ptr as *mut Option<SafeHash>,
481-
kval: self.middle.ptr.offset(-(self.capacity as isize)),
488+
hash: self.as_mut_ptr() as *mut Option<SafeHash>,
489+
kval: self.as_mut_ptr().offset(-(self.capacity as isize)),
482490
}
483491
}
484492
}
@@ -488,36 +496,36 @@ impl<K, V> RawTable<K, V> {
488496
assert!(capacity.is_power_of_two());
489497
assert!(capacity >= self.capacity);
490498

491-
if self.middle.ptr.is_null() {
499+
if self.capacity == 0 {
492500
return false;
493501
}
494502

495503
let new_size = checked_size_generic::<K, V>(capacity);
496504

497505
unsafe {
498-
let ptr = self.middle.ptr.offset(-(self.capacity as isize)) as *mut u8;
506+
let ptr = self.as_mut_ptr().offset(-(self.capacity as isize)) as *mut u8;
499507
let is_inplace = reallocate_inplace(ptr,
500508
size_generic::<K, V>(self.capacity),
501509
new_size,
502510
align::<K, V>()) >= new_size;
503511

504512
if is_inplace {
505513
let cap_diff = (capacity - self.capacity) as isize;
506-
let hashes = self.middle.ptr.offset(cap_diff) as *mut Option<SafeHash>;
514+
let hashes = self.as_mut_ptr().offset(cap_diff) as *mut Option<SafeHash>;
507515
// Copy the array of hashes. Maybe it's already in cache.
508516
if size_of::<(K, V)>() >= size_of::<Option<SafeHash>>() {
509517
// The regions of memory occupied by old and new hash arrays are disjoint.
510518
// before: [KVKVKVKV|h h h h ]
511519
// after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
512-
ptr::copy_nonoverlapping(hashes, self.middle.ptr as *const _, self.capacity);
520+
ptr::copy_nonoverlapping(hashes, self.as_mut_ptr() as *const _, self.capacity);
513521
} else {
514522
// before: [KVKVKVKV|h h |h h ]
515523
// after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
516-
ptr::copy(hashes, self.middle.ptr as *const _, self.capacity);
524+
ptr::copy(hashes, self.as_mut_ptr() as *const _, self.capacity);
517525
}
518-
zero_memory(hashes.offset(self.capacity as int), capacity - self.capacity);
526+
ptr::write_bytes(hashes.offset(self.capacity as int), 0, capacity - self.capacity);
519527

520-
self.middle = Unique::new(self.middle.ptr.offset(cap_diff));
528+
self.middle = Unique::new(self.as_mut_ptr().offset(cap_diff));
521529
self.capacity = capacity;
522530
}
523531

@@ -535,6 +543,11 @@ impl<K, V> RawTable<K, V> {
535543
pub fn size(&self) -> usize {
536544
self.size
537545
}
546+
547+
/// Pointer to one-past-the-last key-value pair.
548+
pub fn as_mut_ptr(&self) -> *mut (K, V) {
549+
unsafe { self.middle.get() as *const _ as *mut _ }
550+
}
538551
}
539552

540553
/// Rounds up to a multiple of a power of two. Returns the closest multiple
@@ -579,7 +592,7 @@ fn align<K, V>() -> usize {
579592
}
580593

581594
/// A newtyped RawBucket. Not copyable.
582-
pub struct RawFullBucket<K, V, M>(RawBucket<K, V>);
595+
pub struct RawFullBucket<K, V, M>(RawBucket<K, V>, PhantomData<M>);
583596

584597
impl<'t, K, V, M: 't> RawFullBucket<K, V, M> where M: Borrow<RawTable<K, V>> {
585598
pub fn into_refs(self) -> (&'t K, &'t V) {
@@ -622,7 +635,7 @@ impl<K, V, M> Iterator for RawFullBuckets<K, V, M> {
622635
// it with the pointer to the next one.
623636
let prev = ptr::replace(&mut self.raw, self.raw.offset(1));
624637
if *prev.hash != None {
625-
return Some(RawFullBucket(prev));
638+
return Some(RawFullBucket(prev, PhantomData));
626639
}
627640
}
628641
}
@@ -647,7 +660,7 @@ impl<K, V> Drop for RawTable<K, V> {
647660
}
648661
}
649662

650-
let ptr = self.middle.ptr.offset(-(self.capacity as isize)) as *mut u8;
663+
let ptr = self.as_mut_ptr().offset(-(self.capacity as isize)) as *mut u8;
651664
deallocate(ptr, size_generic::<K, V>(self.capacity), align::<K, V>());
652665
}
653666
}
@@ -713,8 +726,8 @@ impl<K, V> PartialRawTable<K, V> {
713726
/// Unwrap the table by zeroing uninitialized ranges.
714727
pub fn unwrap(self) -> RawTable<K, V> {
715728
unsafe {
716-
ptr::write_bytes(self.table.first_bucket_raw().hash, self.front_num);
717-
ptr::write_bytes(self.back.hash, self.back_num);
729+
ptr::write_bytes(self.table.first_bucket_raw().hash, 0, self.front_num);
730+
ptr::write_bytes(self.back.hash, 0, self.back_num);
718731
let table = ptr::read(&self.table);
719732
mem::forget(self);
720733
table

0 commit comments

Comments
 (0)