Skip to content

Commit b7317cd

Browse files
committedFeb 27, 2015
Docs, further cleanup.
1 parent 1662f69 commit b7317cd

File tree

2 files changed

+98
-99
lines changed

2 files changed

+98
-99
lines changed
 

Diff for: ‎src/libstd/collections/hash/map.rs

+44-45
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ use fmt::{self, Debug};
2121
use hash::{Hash, SipHasher};
2222
use iter::{Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
2323
use marker::Sized;
24-
use mem::{self, replace};
24+
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,11 +33,9 @@ use super::table::{
3333
Bucket,
3434
EmptyBucket,
3535
FullBucket,
36-
FullBucketImm,
3736
FullBucketMut,
3837
RawTable,
3938
SafeHash,
40-
TableRef,
4139
PartialRawTable,
4240
Put,
4341
};
@@ -322,13 +320,12 @@ fn search_hashed<K, V, M, F>(table: M,
322320
hash: SafeHash,
323321
mut is_match: F)
324322
-> InternalEntry<K, V, M> where
325-
RawTable<K, V>: BorrowFrom<M>,
323+
M: Borrow<RawTable<K, V>>,
326324
F: FnMut(&K) -> bool,
327325
{
328326
// Worst case, we'll find one empty bucket among `size + 1` buckets.
329-
let table = TableRef(table);
330-
let size = table.size();
331-
let mut probe = match Bucket::new(table.0, hash) {
327+
let size = table.borrow().size();
328+
let mut probe = match Bucket::new(table, hash) {
332329
Some(probe) => probe,
333330
None => return InternalEntry::TableIsEmpty,
334331
};
@@ -392,8 +389,8 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
392389
fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
393390
mut ib: usize,
394391
mut hash: SafeHash,
395-
mut k: K,
396-
mut v: V)
392+
mut key: K,
393+
mut val: V)
397394
-> &'a mut V {
398395
let starting_index = bucket.index();
399396
let size = {
@@ -407,9 +404,11 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
407404
let idx_end = starting_index + size - bucket.displacement();
408405

409406
loop {
410-
let (old_hash, old_key, old_val) = {
407+
{
411408
let (h_ref, k_ref, v_ref) = bucket.read_mut();
412-
(replace(h_ref, hash), replace(k_ref, k), replace(v_ref, v))
409+
swap(h_ref, &mut hash);
410+
swap(k_ref, &mut key);
411+
swap(v_ref, &mut val);
413412
};
414413
loop {
415414
let probe = bucket.into_next();
@@ -418,7 +417,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
418417
let full_bucket = match probe.peek() {
419418
Empty(bucket) => {
420419
// Found a hole!
421-
let b = bucket.put(old_hash, old_key, old_val);
420+
let b = bucket.put(hash, key, val);
422421
// Now that it's stolen, just read the value's pointer
423422
// right out of the table!
424423
return b.into_table().into_mut_refs().1;
@@ -433,9 +432,6 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
433432
// Robin hood! Steal the spot.
434433
if ib < probe_ib {
435434
ib = probe_ib;
436-
hash = old_hash;
437-
k = old_key;
438-
v = old_val;
439435
break;
440436
}
441437
}
@@ -444,20 +440,19 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
444440

445441
// Performs insertion with relaxed requirements.
446442
// The caller should ensure that invariants of Robin Hood linear probing hold.
447-
fn insert_hashed_ordered<M: Put, K, V>(arg: M, h: SafeHash, k: K, v: V) -> M
448-
where RawTable<K, V>: BorrowFromMut<M>
443+
fn insert_hashed_ordered<M: Put, K, V>(table: M, hash: SafeHash, key: K, val: V) -> M
444+
where M: BorrowMut<RawTable<K, V>>
449445
{
450-
let table = TableRef(arg);
451-
let cap = table.capacity();
452-
let mut buckets = Bucket::new(table.0, h).unwrap();
446+
let cap = table.borrow().capacity();
447+
let mut buckets = Bucket::new(table, hash).unwrap();
453448
let ib = buckets.index();
454449

455450
while buckets.index() != ib + cap {
456451
// We don't need to compare hashes for value swap.
457452
// Not even DIBs for Robin Hood.
458453
buckets = match buckets.peek() {
459454
Empty(empty) => {
460-
return empty.put(h, k, v).into_table();
455+
return empty.put(hash, key, val).into_table();
461456
}
462457
Full(full) => full.into_bucket()
463458
};
@@ -477,24 +472,20 @@ impl<K, V, S> HashMap<K, V, S>
477472
/// Search for a key, yielding the index if it's found in the hashtable.
478473
/// If you already have the hash for the key lying around, use
479474
/// search_hashed.
480-
fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
475+
fn search<'a, Q: ?Sized>(&'a self, q: &Q)
476+
-> InternalEntry<K, V, &'a RawTable<K, V>>
481477
where K: Borrow<Q>, Q: Eq + Hash
482478
{
483479
let hash = self.make_hash(q);
484-
match search_hashed(&self.table, hash, |k| q.eq(k.borrow())) {
485-
InternalEntry::Occupied(bucket) => Some(bucket.elem),
486-
_ => None,
487-
}
480+
search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
488481
}
489482

490-
fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
483+
fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q)
484+
-> InternalEntry<K, V, &'a mut RawTable<K, V>>
491485
where K: Borrow<Q>, Q: Eq + Hash
492486
{
493487
let hash = self.make_hash(q);
494-
match search_hashed(&mut self.table, hash, |k| q.eq(k.borrow())) {
495-
InternalEntry::Occupied(bucket) => Some(bucket.elem),
496-
_ => None,
497-
}
488+
search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
498489
}
499490
}
500491

@@ -653,7 +644,7 @@ impl<K, V, S> HashMap<K, V, S>
653644
// Grow the table.
654645
let is_inplace = self.table.grow_inplace(new_capacity);
655646

656-
let mut destination = if is_inplace {
647+
let destination = if is_inplace {
657648
// Resizing in-place.
658649
None
659650
} else {
@@ -933,14 +924,13 @@ impl<K, V, S> HashMap<K, V, S>
933924
pub fn entry(&mut self, key: K) -> Entry<K, V> {
934925
// Gotta resize now.
935926
self.reserve(1);
936-
937927
let hash = self.make_hash(&key);
938-
match search_hashed(&mut self.table, hash, |k| *k == key) {
928+
match search_hashed(&mut self.table, hash, |k| key.eq(k.borrow())) {
939929
InternalEntry::Occupied(state) => Occupied(state),
940930
InternalEntry::Vacant(bucket) => Vacant(VacantEntry {
941-
elem: bucket,
942-
hash: hash,
943931
key: key,
932+
hash: hash,
933+
elem: bucket,
944934
}),
945935
InternalEntry::TableIsEmpty => unreachable!()
946936
}
@@ -1044,7 +1034,7 @@ impl<K, V, S> HashMap<K, V, S>
10441034
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
10451035
where K: Borrow<Q>, Q: Hash + Eq
10461036
{
1047-
self.search(k).map(|bucket| bucket.into_refs().1)
1037+
self.search(k).into_option().map(|bucket| bucket.into_refs().1)
10481038
}
10491039

10501040
/// Returns true if the map contains a value for the specified key.
@@ -1067,7 +1057,7 @@ impl<K, V, S> HashMap<K, V, S>
10671057
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
10681058
where K: Borrow<Q>, Q: Hash + Eq
10691059
{
1070-
self.search(k).is_some()
1060+
self.search(k).into_option().is_some()
10711061
}
10721062

10731063
/// Returns a mutable reference to the value corresponding to the key.
@@ -1093,7 +1083,7 @@ impl<K, V, S> HashMap<K, V, S>
10931083
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
10941084
where K: Borrow<Q>, Q: Hash + Eq
10951085
{
1096-
self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
1086+
self.search_mut(k).into_option().map(|bucket| bucket.into_mut_refs().1)
10971087
}
10981088

10991089
/// Inserts a key-value pair from the map. If the key already had a value
@@ -1113,10 +1103,10 @@ impl<K, V, S> HashMap<K, V, S>
11131103
/// assert_eq!(map[37], "c");
11141104
/// ```
11151105
#[stable(feature = "rust1", since = "1.0.0")]
1116-
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
1117-
let hash = self.make_hash(&k);
1106+
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
11181107
self.reserve(1);
1119-
self.insert_hashed_nocheck(hash, k, v)
1108+
let hash = self.make_hash(&key);
1109+
self.insert_hashed_nocheck(hash, key, value)
11201110
}
11211111

11221112
/// Removes a key from the map, returning the value at the key if the key
@@ -1144,7 +1134,7 @@ impl<K, V, S> HashMap<K, V, S>
11441134
return None
11451135
}
11461136

1147-
self.search_mut(k).map(|bucket| pop_internal(bucket).1)
1137+
self.search_mut(k).into_option().map(|bucket| pop_internal(bucket).1)
11481138
}
11491139
}
11501140

@@ -1397,6 +1387,15 @@ enum InternalEntry<K, V, M> {
13971387
TableIsEmpty,
13981388
}
13991389

1390+
impl<K, V, M> InternalEntry<K, V, M> {
1391+
fn into_option(self) -> Option<FullBucket<K, V, M>> {
1392+
match self {
1393+
InternalEntry::Occupied(bucket) => Some(bucket.elem),
1394+
_ => None,
1395+
}
1396+
}
1397+
}
1398+
14001399
#[stable(feature = "rust1", since = "1.0.0")]
14011400
impl<'a, K, V> Iterator for Iter<'a, K, V> {
14021401
type Item = (&'a K, &'a V);
@@ -1547,7 +1546,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
15471546

15481547
#[unstable(feature = "std_misc",
15491548
reason = "matches collection reform v2 specification, waiting for dust to settle")]
1550-
impl<'a, K: 'a, V: 'a, M: 'a> OccupiedEntryState<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
1549+
impl<'a, K: 'a, V: 'a, M: 'a> OccupiedEntryState<K, V, M> where M: BorrowMut<RawTable<K, V>> {
15511550
/// Gets a mutable reference to the value in the entry.
15521551
#[stable(feature = "rust1", since = "1.0.0")]
15531552
pub fn get_mut(&mut self) -> &mut V {

Diff for: ‎src/libstd/collections/hash/table.rs

+54-54
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};
@@ -77,20 +77,17 @@ struct RawBucket<K, V> {
7777
kval: *mut (K, V),
7878
}
7979

80-
impl<K, V> Copy for RawBucket<K, V> {}
81-
82-
#[derive(Clone)]
83-
pub struct TableRef<M>(pub M);
84-
85-
impl<M: Copy> Copy for TableRef<M> {}
86-
8780
pub struct Bucket<K, V, M, S = ()> {
8881
raw: RawBucket<K, V>,
8982
idx: usize,
9083
capacity: usize,
91-
table: TableRef<M>,
84+
table: M,
85+
marker: PhantomData<S>,
86+
9287
}
9388

89+
impl<K, V> Copy for RawBucket<K, V> {}
90+
9491
impl<K, V, M: Copy, S> Copy for Bucket<K,V,M,S> where M: Borrow<RawTable<K, V>> {}
9592

9693
mod bucket {
@@ -151,20 +148,6 @@ fn can_alias_safehash_as_option() {
151148
assert_eq!(size_of::<SafeHash>(), size_of::<Option<SafeHash>>())
152149
}
153150

154-
impl<K, V, M> Deref for TableRef<M> where M: Borrow<RawTable<K, V>> {
155-
type Target = RawTable<K, V>;
156-
157-
fn deref(&self) -> &RawTable<K, V> {
158-
self.0.borrow()
159-
}
160-
}
161-
162-
impl<K, V, M> DerefMut for TableRef<M> where M: Borrow<RawTable<K, V>> {
163-
fn deref_mut(&mut self) -> &mut RawTable<K, V> {
164-
self.0.borrow_mut()
165-
}
166-
}
167-
168151
impl<K, V> RawBucket<K, V> {
169152
unsafe fn offset(self, count: isize) -> RawBucket<K, V> {
170153
RawBucket {
@@ -180,19 +163,21 @@ impl<K, V, M, S> Borrow<RawTable<K, V>> for Bucket<K, V, M, S>
180163
where M: Borrow<RawTable<K, V>>
181164
{
182165
fn borrow(&self) -> &RawTable<K, V> {
183-
self.table.0.borrow()
166+
self.table.borrow().borrow()
184167
}
185168
}
186169

187170
impl<K, V, M, S> BorrowMut<RawTable<K, V>> for Bucket<K, V, M, S>
188-
where M: Borrow<RawTable<K, V>>
171+
where M: BorrowMut<RawTable<K, V>>
189172
{
190173
fn borrow_mut(&mut self) -> &mut RawTable<K, V> {
191-
self.table.0.borrow_mut()
174+
self.table.borrow_mut().borrow_mut()
192175
}
193176
}
194177

195-
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> {}
196181
impl<K, V> Put for RawTable<K, V> {}
197182
impl<'t, K, V> Put for &'t mut RawTable<K, V> {}
198183
impl<K, V, M: Put> Put for Bucket<K, V, M> {}
@@ -202,11 +187,11 @@ impl<K, V, M: Put> Put for FullBucket<K, V, M> {}
202187
impl<K, V, M, S> Bucket<K, V, M, S> {
203188
/// Borrow a reference to the table.
204189
pub fn table(&self) -> &M {
205-
&self.table.0
190+
&self.table
206191
}
207192
/// Move out the reference to the table.
208193
pub fn into_table(self) -> M {
209-
self.table.0
194+
self.table
210195
}
211196
/// Get the raw index.
212197
pub fn index(&self) -> usize {
@@ -232,14 +217,14 @@ impl<K, V, M> Bucket<K, V, M> where M: Borrow<RawTable<K, V>> {
232217
pub fn at_index(table: M, ib_index: uint)
233218
-> Result<Bucket<K, V, M>, Bucket<K, V, M, bucket::TableIsEmpty>>
234219
{
235-
let table = TableRef(table);
236-
let capacity = table.capacity();
220+
let capacity = table.borrow().capacity();
237221
let idx = ib_index & (capacity - 1);
238222
let bucket: Bucket<K, V, M> = Bucket {
239-
raw: unsafe { table.first_bucket_raw().offset(idx as isize) },
223+
raw: unsafe { table.borrow().first_bucket_raw().offset(idx as isize) },
240224
idx: idx,
241225
capacity: capacity,
242226
table: table,
227+
marker: PhantomData,
243228
};
244229
if capacity == 0 {
245230
Err(bucket.unsafe_cast())
@@ -254,7 +239,7 @@ impl<K, V, M> Bucket<K, V, M> where M: Borrow<RawTable<K, V>> {
254239

255240
/// Narrows down the range of iteration, which must be a power of 2.
256241
pub fn iter_to(mut self, limit: usize) -> Bucket<K, V, M> {
257-
assert!(limit <= self.table.capacity());
242+
assert!(limit <= self.table.borrow().capacity());
258243
assert!(limit.is_power_of_two());
259244
self.capacity = limit;
260245
self
@@ -295,6 +280,7 @@ impl<K, V, M, S> Bucket<K, V, M, S> where M: Borrow<RawTable<K, V>> {
295280
idx: self.idx,
296281
capacity: self.capacity,
297282
table: self.table,
283+
marker: PhantomData,
298284
}
299285
}
300286

@@ -315,18 +301,20 @@ impl<K, V, M, S> Bucket<K, V, M, S> where M: Borrow<RawTable<K, V>> {
315301
raw: self.raw,
316302
idx: self.idx,
317303
capacity: self.capacity,
318-
table: TableRef(self),
304+
table: self,
305+
marker: PhantomData,
319306
}
320307
}
321308
}
322309

323310
impl<K, V, M> EmptyBucket<K, V, M> where M: Borrow<RawTable<K, V>> {
324311
pub fn gap_peek(self) -> Option<GapThenFull<K, V, M>> {
325312
let gap = Bucket {
326-
table: TableRef(()),
313+
table: (),
327314
idx: self.idx,
328315
capacity: self.capacity,
329316
raw: self.raw,
317+
marker: PhantomData,
330318
};
331319

332320
match self.into_next().peek() {
@@ -341,7 +329,7 @@ impl<K, V, M> EmptyBucket<K, V, M> where M: Borrow<RawTable<K, V>> {
341329
}
342330
}
343331

344-
impl<K, V, M> EmptyBucket<K, V, M> where M: Borrow<RawTable<K, V>>, M: Put {
332+
impl<K, V, M> EmptyBucket<K, V, M> where M: BorrowMut<RawTable<K, V>>, M: Put {
345333
/// Puts given key and value pair, along with the key's hash,
346334
/// into this bucket in the hashtable. Note how `self` is 'moved' into
347335
/// this function, because this slot will no longer be empty when
@@ -356,7 +344,7 @@ impl<K, V, M> EmptyBucket<K, V, M> where M: Borrow<RawTable<K, V>>, M: Put {
356344
ptr::write(self.raw.kval, (key, value));
357345
}
358346

359-
self.table.size += 1;
347+
self.table.borrow_mut().size += 1;
360348

361349
self.unsafe_cast()
362350
}
@@ -413,7 +401,7 @@ impl<'t, K, V, M: 't> FullBucket<K, V, M> where M: BorrowMut<RawTable<K, V>> {
413401
/// This works similarly to `put`, building an `EmptyBucket` out of the
414402
/// taken bucket.
415403
pub fn take(mut self) -> (EmptyBucket<K, V, M>, K, V) {
416-
self.table.size -= 1;
404+
self.table.borrow_mut().size -= 1;
417405

418406
unsafe {
419407
*self.raw.hash = None;
@@ -497,46 +485,47 @@ impl<K, V> RawTable<K, V> {
497485
}
498486
} else {
499487
RawBucket {
500-
hash: self.middle.ptr as *mut Option<SafeHash>,
501-
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)),
502490
}
503491
}
504492
}
505493

494+
/// Grows a non-empty table in-place.
506495
pub fn grow_inplace(&mut self, capacity: uint) -> bool {
507496
assert!(capacity.is_power_of_two());
508497
assert!(capacity >= self.capacity);
509498

510-
if self.middle.ptr.is_null() {
499+
if self.capacity == 0 {
511500
return false;
512501
}
513502

514503
let new_size = checked_size_generic::<K, V>(capacity);
515504

516505
unsafe {
517-
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;
518507
let is_inplace = reallocate_inplace(ptr,
519508
size_generic::<K, V>(self.capacity),
520509
new_size,
521510
align::<K, V>()) >= new_size;
522511

523512
if is_inplace {
524513
let cap_diff = (capacity - self.capacity) as isize;
525-
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>;
526515
// Copy the array of hashes. Maybe it's already in cache.
527516
if size_of::<(K, V)>() >= size_of::<Option<SafeHash>>() {
528517
// The regions of memory occupied by old and new hash arrays are disjoint.
529518
// before: [KVKVKVKV|h h h h ]
530519
// after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
531-
ptr::copy_nonoverlapping(hashes, self.middle.ptr as *const _, self.capacity);
520+
ptr::copy_nonoverlapping(hashes, self.as_mut_ptr() as *const _, self.capacity);
532521
} else {
533522
// before: [KVKVKVKV|h h |h h ]
534523
// after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
535-
ptr::copy(hashes, self.middle.ptr as *const _, self.capacity);
524+
ptr::copy(hashes, self.as_mut_ptr() as *const _, self.capacity);
536525
}
537-
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);
538527

539-
self.middle = Unique::new(self.middle.ptr.offset(cap_diff));
528+
self.middle = Unique::new(self.as_mut_ptr().offset(cap_diff));
540529
self.capacity = capacity;
541530
}
542531

@@ -554,6 +543,11 @@ impl<K, V> RawTable<K, V> {
554543
pub fn size(&self) -> usize {
555544
self.size
556545
}
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+
}
557551
}
558552

559553
/// Rounds up to a multiple of a power of two. Returns the closest multiple
@@ -598,7 +592,7 @@ fn align<K, V>() -> usize {
598592
}
599593

600594
/// A newtyped RawBucket. Not copyable.
601-
pub struct RawFullBucket<K, V, M>(RawBucket<K, V>);
595+
pub struct RawFullBucket<K, V, M>(RawBucket<K, V>, PhantomData<M>);
602596

603597
impl<'t, K, V, M: 't> RawFullBucket<K, V, M> where M: Borrow<RawTable<K, V>> {
604598
pub fn into_refs(self) -> (&'t K, &'t V) {
@@ -617,7 +611,7 @@ impl<'t, K, V, M: 't> RawFullBucket<K, V, M> where M: BorrowMut<RawTable<K, V>>
617611
pub struct RawFullBuckets<K, V, M> {
618612
raw: RawBucket<K, V>,
619613
hashes_end: *mut Option<SafeHash>,
620-
table: TableRef<M>,
614+
table: M,
621615
}
622616

623617
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
@@ -641,7 +635,7 @@ impl<K, V, M> Iterator for RawFullBuckets<K, V, M> {
641635
// it with the pointer to the next one.
642636
let prev = ptr::replace(&mut self.raw, self.raw.offset(1));
643637
if *prev.hash != None {
644-
return Some(RawFullBucket(prev));
638+
return Some(RawFullBucket(prev, PhantomData));
645639
}
646640
}
647641
}
@@ -666,12 +660,13 @@ impl<K, V> Drop for RawTable<K, V> {
666660
}
667661
}
668662

669-
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;
670664
deallocate(ptr, size_generic::<K, V>(self.capacity), align::<K, V>());
671665
}
672666
}
673667
}
674668

669+
/// A partial table provides safe and cheap draining and incremental construction.
675670
pub struct PartialRawTable<K, V> {
676671
table: RawTable<K, V>,
677672
front: RawBucket<K, V>,
@@ -681,6 +676,7 @@ pub struct PartialRawTable<K, V> {
681676
}
682677

683678
impl<K, V> PartialRawTable<K, V> {
679+
/// Turn a table into a partial table. All buckets are already initialized.
684680
pub fn new(table: RawTable<K, V>) -> PartialRawTable<K, V> {
685681
unsafe {
686682
PartialRawTable {
@@ -693,6 +689,7 @@ impl<K, V> PartialRawTable<K, V> {
693689
}
694690
}
695691

692+
/// Initialize a bucket. Has no effect if there are no uninitialized buckets at the back.
696693
pub fn push_back(&mut self, bucket: Option<(SafeHash, K, V)>) {
697694
unsafe {
698695
if self.back_num != 0 {
@@ -709,6 +706,7 @@ impl<K, V> PartialRawTable<K, V> {
709706
}
710707
}
711708

709+
/// Takes out an initialized bucket. Returns None if all buckets are uninitialized.
712710
pub fn take_front(&mut self) -> Option<(SafeHash, K, V)> {
713711
unsafe {
714712
while self.front.hash != self.back.hash {
@@ -725,10 +723,11 @@ impl<K, V> PartialRawTable<K, V> {
725723
None
726724
}
727725

726+
/// Unwrap the table by zeroing uninitialized ranges.
728727
pub fn unwrap(self) -> RawTable<K, V> {
729728
unsafe {
730-
ptr::write_bytes(self.table.first_bucket_raw().hash, self.front_num);
731-
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);
732731
let table = ptr::read(&self.table);
733732
mem::forget(self);
734733
table
@@ -740,6 +739,7 @@ impl<K, V> PartialRawTable<K, V> {
740739
}
741740
}
742741

742+
/// Drops all initialized buckets in the partial table.
743743
#[unsafe_destructor]
744744
impl<K, V> Drop for PartialRawTable<K, V> {
745745
fn drop(&mut self) {

0 commit comments

Comments
 (0)
Please sign in to comment.