Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6218462

Browse files
committedFeb 16, 2015
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

Lines changed: 82 additions & 45 deletions
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

‎src/libstd/collections/hash/table.rs

Lines changed: 216 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use borrow::{BorrowFrom, BorrowFromMut};
1616
use clone::Clone;
1717
use cmp;
1818
use hash::{Hash, Hasher};
19-
use iter::{Iterator, IteratorExt, ExactSizeIterator, count};
19+
use iter::{Iterator, IteratorExt, count};
2020
use marker::{Copy, Sized};
2121
use mem::{self, min_align_of, size_of};
2222
use num::{Int, UnsignedInt};
@@ -72,30 +72,26 @@ pub struct RawTable<K, V> {
7272
middle: Unique<(K, V)>,
7373
}
7474

75-
struct RawBucket<K, V, M> {
75+
struct RawBucket<K, V> {
7676
hash: *mut Option<SafeHash>,
7777
kval: *mut (K, V),
7878
}
7979

80-
impl<K,V,M> Copy for RawBucket<K,V,M> {}
80+
impl<K, V> Copy for RawBucket<K, V> {}
8181

8282
#[derive(Clone)]
8383
pub struct TableRef<M>(pub M);
8484

8585
impl<M: Copy> Copy for TableRef<M> {}
8686

87-
struct BareBucket<K, V, M> {
88-
raw: RawBucket<K, V, M>,
87+
pub struct Bucket<K, V, M, S = ()> {
88+
raw: RawBucket<K, V>,
8989
idx: usize,
9090
capacity: usize,
9191
table: TableRef<M>,
9292
}
9393

94-
impl<K,V,M:Copy> Copy for BareBucket<K,V,M> {}
95-
96-
pub struct Bucket<K, V, M, S = ()>(BareBucket<K, V, M>);
97-
98-
impl<K,V,M:Copy,S> Copy for Bucket<K,V,M,S> {}
94+
impl<K, V, M: Copy, S> Copy for Bucket<K,V,M,S> where RawTable<K, V>: BorrowFrom<M> {}
9995

10096
mod bucket {
10197
pub enum Empty {}
@@ -173,75 +169,61 @@ impl<K, V, M> DerefMut for TableRef<M> where RawTable<K, V>: BorrowFromMut<M> {
173169
}
174170
}
175171

176-
impl<K, V, M> RawBucket<K, V, M> {
177-
unsafe fn offset(self, count: int) -> RawBucket<K, V, M> {
172+
impl<K, V> RawBucket<K, V> {
173+
unsafe fn offset(self, count: int) -> RawBucket<K, V> {
178174
RawBucket {
179175
hash: self.hash.offset(count),
180176
kval: self.kval.offset(count),
181177
}
182178
}
183179
}
184180

185-
impl<'t, K, V, M: 't> RawBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
186-
pub fn into_refs(self) -> (&'t K, &'t V) {
187-
let &(ref k, ref v) = unsafe {
188-
&*self.kval
189-
};
190-
(k, v)
191-
}
192-
}
193-
194-
impl<'t, K, V, M> RawBucket<K, V, M>
195-
where RawTable<K, V>: BorrowFromMut<M>, M: 't
196-
{
197-
pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
198-
let &mut (ref mut k, ref mut v) = unsafe {
199-
&mut *self.kval
200-
};
201-
(k, v)
202-
}
203-
}
204-
205181
// Chain buckets! This is perfectly safe as long as operations on one
206182
// `Bucket` can't invalidate other `Bucket`s.
207-
impl<K, V, M> BorrowFrom<Bucket<K, V, M>> for RawTable<K, V>
183+
impl<K, V, M, S> BorrowFrom<Bucket<K, V, M, S>> for RawTable<K, V>
208184
where RawTable<K, V>: BorrowFrom<M>
209185
{
210-
fn borrow_from(bucket: &Bucket<K, V, M>) -> &RawTable<K, V> {
211-
BorrowFrom::borrow_from(&bucket.0.table.0)
186+
fn borrow_from(bucket: &Bucket<K, V, M, S>) -> &RawTable<K, V> {
187+
BorrowFrom::borrow_from(&bucket.table.0)
212188
}
213189
}
214190

215-
impl<K, V, M> BorrowFromMut<Bucket<K, V, M>> for RawTable<K, V>
191+
impl<K, V, M, S> BorrowFromMut<Bucket<K, V, M, S>> for RawTable<K, V>
216192
where RawTable<K, V>: BorrowFromMut<M>
217193
{
218-
fn borrow_from_mut(bucket: &mut Bucket<K, V, M>) -> &mut RawTable<K, V> {
219-
BorrowFromMut::borrow_from_mut(&mut bucket.0.table.0)
194+
fn borrow_from_mut(bucket: &mut Bucket<K, V, M, S>) -> &mut RawTable<K, V> {
195+
BorrowFromMut::borrow_from_mut(&mut bucket.table.0)
220196
}
221197
}
222198

199+
pub trait Put {}
200+
impl<K, V> Put for RawTable<K, V> {}
201+
impl<'t, K, V> Put for &'t mut RawTable<K, V> {}
202+
impl<K, V, M: Put> Put for Bucket<K, V, M> {}
203+
impl<K, V, M: Put> Put for FullBucket<K, V, M> {}
204+
223205
// Buckets hold references to the table.
224206
impl<K, V, M, S> Bucket<K, V, M, S> {
225207
/// Borrow a reference to the table.
226208
pub fn table(&self) -> &M {
227-
&self.0.table.0
209+
&self.table.0
228210
}
229211
/// Move out the reference to the table.
230212
pub fn into_table(self) -> M {
231-
self.0.table.0
213+
self.table.0
232214
}
233215
/// Get the raw index.
234216
pub fn index(&self) -> usize {
235-
self.0.idx
217+
self.idx
236218
}
237219
/// Turn the bucket into an iterator over full buckets.
238220
pub fn into_iter(self) -> RawFullBuckets<K, V, M> {
239221
RawFullBuckets {
240-
raw: self.0.raw,
222+
raw: self.raw,
241223
hashes_end: unsafe {
242-
self.0.raw.hash.offset(self.0.capacity as isize - self.index() as isize)
224+
self.raw.hash.offset(self.capacity as isize - self.index() as isize)
243225
},
244-
table: self.0.table,
226+
table: self.table,
245227
}
246228
}
247229
}
@@ -256,20 +238,17 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
256238
{
257239
let table = TableRef(table);
258240
let capacity = table.capacity();
259-
let ib_index = ib_index & (table.capacity() - 1);
260-
let bb = BareBucket {
261-
raw: unsafe {
262-
table.first_bucket_raw().offset(ib_index as isize)
263-
},
264-
idx: ib_index,
241+
let idx = ib_index & (capacity - 1);
242+
let bucket: Bucket<K, V, M> = Bucket {
243+
raw: unsafe { table.first_bucket_raw().offset(idx as isize) },
244+
idx: idx,
265245
capacity: capacity,
266246
table: table,
267247
};
268-
269248
if capacity == 0 {
270-
Err(Bucket(bb))
249+
Err(bucket.unsafe_cast())
271250
} else {
272-
Ok(Bucket(bb))
251+
Ok(bucket.unsafe_cast())
273252
}
274253
}
275254

@@ -279,9 +258,9 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
279258

280259
/// Narrows down the range of iteration, which must be a power of 2.
281260
pub fn iter_to(mut self, limit: usize) -> Bucket<K, V, M> {
282-
assert!(limit <= self.0.table.capacity());
261+
assert!(limit <= self.table.capacity());
283262
assert!(limit.is_power_of_two());
284-
self.0.capacity = limit;
263+
self.capacity = limit;
285264
self
286265
}
287266

@@ -290,69 +269,69 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
290269
/// the appropriate types to call most of the other functions in
291270
/// this module.
292271
pub fn peek(self) -> BucketState<K, V, M> {
293-
match unsafe { *self.0.raw.hash } {
294-
None => Empty(Bucket(self.0)),
295-
_ => Full(Bucket(self.0)),
272+
match unsafe { *self.raw.hash } {
273+
None => Empty(self.unsafe_cast()),
274+
_ => Full(self.unsafe_cast()),
296275
}
297276
}
298277

299278
/// Modifies the bucket pointer in place to make it point to the next slot.
300279
pub fn next(&mut self) {
301-
self.0.idx += 1;
280+
self.idx += 1;
302281

303-
let dist = if self.0.idx & (self.0.capacity - 1) == 0 {
304-
1i - self.0.capacity as int
282+
let dist = if self.idx & (self.capacity - 1) == 0 {
283+
1i - self.capacity as int
305284
} else {
306285
1
307286
};
308287

309288
unsafe {
310-
self.0.raw = self.0.raw.offset(dist);
289+
self.raw = self.raw.offset(dist);
311290
}
312291
}
313292
}
314293

315-
impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
316-
/// A combination of `peek` and `take` which doesn't consume the bucket.
317-
pub fn peek_take(&mut self) -> Option<(K, V)> {
318-
unsafe {
319-
if *self.0.raw.hash != None {
320-
*self.0.raw.hash = None;
321-
self.0.table.size -= 1;
322-
let (k, v) = ptr::read(self.0.raw.kval);
323-
Some((k, v))
324-
} else {
325-
None
326-
}
294+
impl<K, V, M, S> Bucket<K, V, M, S> where RawTable<K, V>: BorrowFrom<M> {
295+
#[inline]
296+
fn unsafe_cast<S2>(self) -> Bucket<K, V, M, S2> {
297+
Bucket {
298+
raw: self.raw,
299+
idx: self.idx,
300+
capacity: self.capacity,
301+
table: self.table,
327302
}
328303
}
329-
}
330304

331-
impl<K, V, M, S> Bucket<K, V, M, S> where RawTable<K, V>: BorrowFrom<M> {
305+
#[inline]
306+
pub fn into_bucket(self) -> Bucket<K, V, M> {
307+
self.unsafe_cast()
308+
}
309+
332310
#[inline]
333311
pub fn into_next(self) -> Bucket<K, V, M> {
334312
let mut bucket = self.into_bucket();
335313
bucket.next();
336314
bucket
337315
}
338316

339-
#[inline]
340-
pub fn into_bucket(self) -> Bucket<K, V, M> {
341-
Bucket(self.0)
317+
pub fn stash(self) -> Bucket<K, V, Bucket<K, V, M, S>, S> {
318+
Bucket {
319+
raw: self.raw,
320+
idx: self.idx,
321+
capacity: self.capacity,
322+
table: TableRef(self),
323+
}
342324
}
343325
}
344326

345327
impl<K, V, M> EmptyBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
346328
pub fn gap_peek(self) -> Option<GapThenFull<K, V, M>> {
347-
let gap = Bucket(BareBucket {
329+
let gap = Bucket {
348330
table: TableRef(()),
349-
idx: self.0.idx,
350-
capacity: self.0.capacity,
351-
raw: RawBucket {
352-
hash: self.0.raw.hash,
353-
kval: self.0.raw.kval,
354-
},
355-
});
331+
idx: self.idx,
332+
capacity: self.capacity,
333+
raw: self.raw,
334+
};
356335

357336
match self.into_next().peek() {
358337
Full(bucket) => {
@@ -366,7 +345,7 @@ impl<K, V, M> EmptyBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
366345
}
367346
}
368347

369-
impl<K, V, M> EmptyBucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
348+
impl<K, V, M> EmptyBucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M>, M: Put {
370349
/// Puts given key and value pair, along with the key's hash,
371350
/// into this bucket in the hashtable. Note how `self` is 'moved' into
372351
/// this function, because this slot will no longer be empty when
@@ -377,17 +356,17 @@ impl<K, V, M> EmptyBucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
377356
pub fn put(mut self, hash: SafeHash, key: K, value: V)
378357
-> FullBucket<K, V, M> {
379358
unsafe {
380-
*self.0.raw.hash = Some(hash);
381-
ptr::write(self.0.raw.kval, (key, value));
359+
*self.raw.hash = Some(hash);
360+
ptr::write(self.raw.kval, (key, value));
382361
}
383362

384-
self.0.table.size += 1;
363+
self.table.size += 1;
385364

386-
Bucket(self.0)
365+
self.unsafe_cast()
387366
}
388367
}
389368

390-
impl<K, V, M> FullBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
369+
impl<'t, K, V, M: 't> FullBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
391370
/// Get the distance between this bucket and the 'ideal' location
392371
/// as determined by the key's hash stored in it.
393372
///
@@ -397,58 +376,53 @@ impl<K, V, M> FullBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
397376
// Calculates the distance one has to travel when going from
398377
// `hash mod capacity` onwards to `idx mod capacity`, wrapping around
399378
// if the destination is not reached before the end of the table.
400-
(self.0.idx - **self.read().0 as usize) & (self.0.capacity - 1)
379+
(self.idx - **self.read().0 as usize) & (self.capacity - 1)
401380
}
402381

403382
/// Gets references to the key and value at a given index.
404383
pub fn read(&self) -> (&SafeHash, &K, &V) {
405384
let (&ref h, &(ref k, ref v)) = unsafe {
406-
(&*(self.0.raw.hash as *mut SafeHash), &*self.0.raw.kval)
407-
};
408-
(h, k, v)
409-
}
410-
}
411-
412-
impl<K, V, M> FullBucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
413-
/// Removes this bucket's key and value from the hashtable.
414-
///
415-
/// This works similarly to `put`, building an `EmptyBucket` out of the
416-
/// taken bucket.
417-
pub fn take(mut self) -> (EmptyBucket<K, V, M>, K, V) {
418-
self.0.table.size -= 1;
419-
420-
unsafe {
421-
*self.0.raw.hash = None;
422-
let (k, v) = ptr::read(self.0.raw.kval);
423-
(Bucket(self.0), k, v)
424-
}
425-
}
426-
427-
/// Gets mutable references to the key and value at a given index.
428-
pub fn read_mut(&mut self) -> (&mut SafeHash, &mut K, &mut V) {
429-
let (&mut ref mut h, &mut (ref mut k, ref mut v)) = unsafe {
430-
(&mut *(self.0.raw.hash as *mut SafeHash), &mut *self.0.raw.kval)
385+
(&*(self.raw.hash as *mut SafeHash), &*self.raw.kval)
431386
};
432387
(h, k, v)
433388
}
434-
}
435-
436-
impl<'t, K, V, M: 't> FullBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
437389
/// Exchange a bucket state for immutable references into the table.
438390
/// Because the underlying reference to the table is also consumed,
439391
/// no further changes to the structure of the table are possible;
440392
/// in exchange for this, the returned references have a longer lifetime
441393
/// than the references returned by `read()`.
442394
pub fn into_refs(self) -> (&'t K, &'t V) {
443-
self.0.raw.into_refs()
395+
unsafe { (&(*self.raw.kval).0, &(*self.raw.kval).1) }
444396
}
445397
}
446398

447399
impl<'t, K, V, M: 't> FullBucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
400+
/// Gets mutable references to the key and value at a given index.
401+
pub fn read_mut(&mut self) -> (&mut SafeHash, &mut K, &mut V) {
402+
let (&mut ref mut h, &mut (ref mut k, ref mut v)) = unsafe {
403+
(&mut *(self.raw.hash as *mut SafeHash), &mut *self.raw.kval)
404+
};
405+
(h, k, v)
406+
}
407+
448408
/// This works similarly to `into_refs`, exchanging a bucket state
449409
/// for mutable references into the table.
450410
pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
451-
self.0.raw.into_mut_refs()
411+
unsafe { (&mut (*self.raw.kval).0, &mut (*self.raw.kval).1) }
412+
}
413+
414+
/// Removes this bucket's key and value from the hashtable.
415+
///
416+
/// This works similarly to `put`, building an `EmptyBucket` out of the
417+
/// taken bucket.
418+
pub fn take(mut self) -> (EmptyBucket<K, V, M>, K, V) {
419+
self.table.size -= 1;
420+
421+
unsafe {
422+
*self.raw.hash = None;
423+
let (k, v) = ptr::read(self.raw.kval);
424+
(self.unsafe_cast(), k, v)
425+
}
452426
}
453427
}
454428

@@ -460,19 +434,16 @@ impl<K, V, M> GapThenFull<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
460434

461435
pub fn shift(mut self) -> Option<GapThenFull<K, V, M>> {
462436
unsafe {
463-
*self.gap.0.raw.hash = mem::replace(&mut *self.full.0.raw.hash, None);
464-
copy_nonoverlapping_memory(self.gap.0.raw.kval, self.full.0.raw.kval, 1);
437+
*self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, None);
438+
copy_nonoverlapping_memory(self.gap.raw.kval, self.full.raw.kval, 1);
465439
}
466440

467-
let Bucket(BareBucket { raw: prev_raw, idx: prev_idx, .. }) = self.full;
441+
let Bucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
468442

469443
match self.full.into_next().peek() {
470444
Full(bucket) => {
471-
self.gap.0.raw = RawBucket {
472-
hash: prev_raw.hash,
473-
kval: prev_raw.kval,
474-
};
475-
self.gap.0.idx = prev_idx;
445+
self.gap.raw = prev_raw;
446+
self.gap.idx = prev_idx;
476447

477448
self.full = bucket;
478449

@@ -485,27 +456,43 @@ impl<K, V, M> GapThenFull<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
485456

486457
impl<K, V> RawTable<K, V> {
487458
/// Does not initialize the buckets.
488-
unsafe fn new_uninitialized(capacity: uint) -> RawTable<K, V> {
489-
if capacity == 0 {
490-
return RawTable {
491-
size: 0,
492-
capacity: 0,
493-
middle: Unique::null(),
494-
};
495-
}
459+
pub fn new_uninitialized(capacity: uint) -> PartialRawTable<K, V> {
460+
unsafe {
461+
let table = if capacity == 0 {
462+
RawTable {
463+
size: 0,
464+
capacity: 0,
465+
middle: Unique::null(),
466+
}
467+
} else {
468+
let hashes = allocate(checked_size_generic::<K, V>(capacity), align::<K, V>());
469+
if hashes.is_null() { ::alloc::oom() }
496470

497-
let hashes = allocate(checked_size_generic::<K, V>(capacity), align::<K, V>());
498-
if hashes.is_null() { ::alloc::oom() }
471+
RawTable {
472+
capacity: capacity,
473+
size: 0,
474+
middle: Unique((hashes as *mut (K, V)).offset(capacity as isize)),
475+
}
476+
};
499477

500-
RawTable {
501-
capacity: capacity,
502-
size: 0,
503-
middle: Unique((hashes as *mut (K, V)).offset(capacity as isize)),
478+
PartialRawTable {
479+
front: table.first_bucket_raw(),
480+
back: table.first_bucket_raw(),
481+
front_num: 0,
482+
back_num: capacity,
483+
table: table,
484+
}
504485
}
505486
}
506487

488+
/// Creates a new raw table from a given capacity. All buckets are
489+
/// initially empty.
490+
pub fn new(capacity: usize) -> RawTable<K, V> {
491+
RawTable::new_uninitialized(capacity).unwrap()
492+
}
493+
507494
#[inline]
508-
unsafe fn first_bucket_raw<M>(&self) -> RawBucket<K, V, M> {
495+
unsafe fn first_bucket_raw(&self) -> RawBucket<K, V> {
509496
if self.capacity() == 0 {
510497
RawBucket {
511498
hash: ptr::null_mut(),
@@ -519,16 +506,6 @@ impl<K, V> RawTable<K, V> {
519506
}
520507
}
521508

522-
/// Creates a new raw table from a given capacity. All buckets are
523-
/// initially empty.
524-
pub fn new(capacity: usize) -> RawTable<K, V> {
525-
unsafe {
526-
let table = RawTable::new_uninitialized(capacity);
527-
zero_memory(table.middle.ptr as *mut Option<SafeHash>, capacity);
528-
table
529-
}
530-
}
531-
532509
pub fn grow_inplace(&mut self, capacity: uint) -> bool {
533510
assert!(capacity.is_power_of_two());
534511
assert!(capacity >= self.capacity);
@@ -580,13 +557,6 @@ impl<K, V> RawTable<K, V> {
580557
pub fn size(&self) -> usize {
581558
self.size
582559
}
583-
584-
pub fn into_iter(self) -> IntoIter<K, V> {
585-
// Replace the marker regardless of lifetime bounds on parameters.
586-
IntoIter {
587-
iter: Bucket::raw_full_buckets(self),
588-
}
589-
}
590560
}
591561

592562
/// Rounds up to a multiple of a power of two. Returns the closest multiple
@@ -631,26 +601,24 @@ fn align<K, V>() -> usize {
631601
}
632602

633603
/// A newtyped RawBucket. Not copyable.
634-
pub struct RawFullBucket<K, V, M>(RawBucket<K, V, M>);
604+
pub struct RawFullBucket<K, V, M>(RawBucket<K, V>);
635605

636-
impl<K, V, M> Deref for RawFullBucket<K, V, M> {
637-
type Target = RawBucket<K, V, M>;
638-
639-
fn deref(&self) -> &RawBucket<K, V, M> {
640-
&self.0
606+
impl<'t, K, V, M: 't> RawFullBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
607+
pub fn into_refs(self) -> (&'t K, &'t V) {
608+
unsafe { (&(*self.0.kval).0, &(*self.0.kval).1) }
641609
}
642610
}
643611

644-
impl<K, V, M> DerefMut for RawFullBucket<K, V, M> {
645-
fn deref_mut(&mut self) -> &mut RawBucket<K, V, M> {
646-
&mut self.0
612+
impl<'t, K, V, M: 't> RawFullBucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
613+
pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
614+
unsafe { (&mut (*self.0.kval).0, &mut (*self.0.kval).1) }
647615
}
648616
}
649617

650618
/// A raw iterator. The basis for some other iterators in this module. Although
651619
/// this interface is safe, it's not used outside this module.
652620
pub struct RawFullBuckets<K, V, M> {
653-
raw: RawBucket<K, V, M>,
621+
raw: RawBucket<K, V>,
654622
hashes_end: *mut Option<SafeHash>,
655623
table: TableRef<M>,
656624
}
@@ -685,99 +653,100 @@ impl<K, V, M> Iterator for RawFullBuckets<K, V, M> {
685653
}
686654
}
687655

688-
/// Iterator over the entries in a table, consuming the table.
689-
pub struct IntoIter<K, V> {
690-
iter: RawFullBuckets<K, V, RawTable<K, V>>
691-
}
692-
693-
impl<K, V> Iterator for IntoIter<K, V> {
694-
type Item = (SafeHash, K, V);
695-
696-
fn next(&mut self) -> Option<(SafeHash, K, V)> {
697-
self.iter.next().map(|bucket| {
698-
self.iter.table.size -= 1;
699-
unsafe {
700-
let (k, v) = ptr::read(bucket.kval);
701-
(*(bucket.hash as *mut SafeHash), k, v)
656+
#[unsafe_destructor]
657+
impl<K, V> Drop for RawTable<K, V> {
658+
fn drop(&mut self) {
659+
if self.middle.ptr.is_null() {
660+
return;
661+
}
662+
// Check if the size is 0, so we don't do a useless scan when
663+
// dropping empty tables such as on resize.
664+
// Avoid double drop of elements that have been already moved out.
665+
unsafe {
666+
if self.size != 0 {
667+
for bucket in Bucket::raw_full_buckets(&mut *self) {
668+
ptr::read(bucket.0.kval);
669+
}
702670
}
703-
})
704-
}
705671

706-
fn size_hint(&self) -> (usize, Option<usize>) {
707-
let size = self.iter.table.size();
708-
(size, Some(size))
672+
let ptr = self.middle.ptr.offset(-(self.capacity as isize)) as *mut u8;
673+
deallocate(ptr, size_generic::<K, V>(self.capacity), align::<K, V>());
674+
}
709675
}
710676
}
711-
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
712-
fn len(&self) -> usize { self.iter.table.size() }
713-
}
714677

715-
#[unsafe_destructor]
716-
impl<K, V> Drop for IntoIter<K, V> {
717-
fn drop(&mut self) {
718-
for _ in self {}
719-
}
678+
pub struct PartialRawTable<K, V> {
679+
table: RawTable<K, V>,
680+
front: RawBucket<K, V>,
681+
back: RawBucket<K, V>,
682+
front_num: usize,
683+
back_num: usize,
720684
}
721685

722-
impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
723-
fn clone(&self) -> RawTable<K, V> {
686+
impl<K, V> PartialRawTable<K, V> {
687+
pub fn new(table: RawTable<K, V>) -> PartialRawTable<K, V> {
724688
unsafe {
725-
let mut new_ht = RawTable::new_uninitialized(self.capacity());
689+
PartialRawTable {
690+
front: table.first_bucket_raw(),
691+
back: table.first_bucket_raw().offset(table.capacity() as isize),
692+
front_num: 0,
693+
back_num: 0,
694+
table: table,
695+
}
696+
}
697+
}
726698

727-
{
728-
let cap = self.capacity();
729-
let mut buckets = if let Ok(buckets) = Bucket::at_index(self, 0) {
730-
buckets
699+
pub fn push_back(&mut self, bucket: Option<(SafeHash, K, V)>) {
700+
unsafe {
701+
if self.back_num != 0 {
702+
self.back_num -= 1;
703+
let back = ptr::replace(&mut self.back, self.back.offset(1));
704+
if let Some((h, k, v)) = bucket {
705+
*back.hash = Some(h);
706+
ptr::write(back.kval, (k, v));
707+
self.table.size += 1;
731708
} else {
732-
return new_ht;
733-
};
734-
let mut new_buckets = Bucket::at_index(&mut new_ht, 0).ok().unwrap();
735-
while buckets.index() != cap {
736-
match buckets.peek() {
737-
Full(full) => {
738-
let (h, k, v) = {
739-
let (h, k, v) = full.read();
740-
(*h, k.clone(), v.clone())
741-
};
742-
*new_buckets.0.raw.hash = Some(h);
743-
ptr::write(new_buckets.0.raw.kval, (k, v));
744-
}
745-
Empty(..) => {
746-
*new_buckets.0.raw.hash = None;
747-
}
748-
}
749-
new_buckets.next();
750-
buckets.next();
709+
*back.hash = None;
751710
}
752-
};
753-
754-
new_ht.size = self.size();
755-
756-
new_ht
711+
}
757712
}
758713
}
759-
}
760714

761-
#[unsafe_destructor]
762-
impl<K, V> Drop for RawTable<K, V> {
763-
fn drop(&mut self) {
764-
if self.middle.ptr.is_null() {
765-
return;
766-
}
767-
// Check if the size is 0, so we don't do a useless scan when
768-
// dropping empty tables such as on resize.
769-
// Avoid double drop of elements that have been already moved out.
715+
pub fn take_front(&mut self) -> Option<(SafeHash, K, V)> {
770716
unsafe {
771-
if self.size != 0 {
772-
for bucket in Bucket::raw_full_buckets(&mut *self) {
773-
ptr::read(bucket.kval);
717+
while self.front.hash != self.back.hash {
718+
self.front_num += 1;
719+
let front = ptr::replace(&mut self.front, self.front.offset(1));
720+
if let Some(h) = *front.hash {
721+
self.table.size -= 1;
722+
let (k, v) = ptr::read(front.kval);
723+
return Some((h, k, v));
774724
}
775725
}
776726
}
777727

728+
None
729+
}
730+
731+
pub fn unwrap(self) -> RawTable<K, V> {
778732
unsafe {
779-
let ptr = self.middle.ptr.offset(-(self.capacity as isize)) as *mut u8;
780-
deallocate(ptr, size_generic::<K, V>(self.capacity), align::<K, V>());
733+
zero_memory(self.table.first_bucket_raw().hash, self.front_num);
734+
zero_memory(self.back.hash, self.back_num);
735+
let table = ptr::read(&self.table);
736+
mem::forget(self);
737+
table
781738
}
782739
}
740+
741+
pub fn size(&self) -> usize {
742+
self.table.size()
743+
}
744+
}
745+
746+
#[unsafe_destructor]
747+
impl<K, V> Drop for PartialRawTable<K, V> {
748+
fn drop(&mut self) {
749+
while let Some(_) = self.take_front() {}
750+
debug_assert_eq!(self.table.size, 0);
751+
}
783752
}

0 commit comments

Comments
 (0)
Please sign in to comment.