]> git.proxmox.com Git - rustc.git/blame - src/libstd/collections/hash/table.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / libstd / collections / hash / table.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
1a4d82fc
JJ
10
11use self::BucketState::*;
12
13use clone::Clone;
14use cmp;
15use hash::{Hash, Hasher};
c34b1796 16use iter::{Iterator, ExactSizeIterator};
85aaf69f 17use marker::{Copy, Send, Sync, Sized, self};
62682a34 18use mem::{align_of, size_of};
1a4d82fc 19use mem;
9346a6ac 20use num::wrapping::OverflowingOps;
1a4d82fc
JJ
21use ops::{Deref, DerefMut, Drop};
22use option::Option;
23use option::Option::{Some, None};
c34b1796 24use ptr::{self, Unique};
85aaf69f 25use rt::heap::{allocate, deallocate, EMPTY};
1a4d82fc
JJ
26use collections::hash_state::HashState;
27
c34b1796 28const EMPTY_BUCKET: u64 = 0;
1a4d82fc
JJ
29
30/// The raw hashtable, providing safe-ish access to the unzipped and highly
31/// optimized arrays of hashes, keys, and values.
32///
33/// This design uses less memory and is a lot faster than the naive
34/// `Vec<Option<u64, K, V>>`, because we don't pay for the overhead of an
35/// option on every element, and we get a generally more cache-aware design.
36///
37/// Essential invariants of this structure:
38///
39/// - if t.hashes[i] == EMPTY_BUCKET, then `Bucket::at_index(&t, i).raw`
40/// points to 'undefined' contents. Don't read from it. This invariant is
41/// enforced outside this module with the `EmptyBucket`, `FullBucket`,
42/// and `SafeHash` types.
43///
44/// - An `EmptyBucket` is only constructed at an index with
45/// a hash of EMPTY_BUCKET.
46///
47/// - A `FullBucket` is only constructed at an index with a
48/// non-EMPTY_BUCKET hash.
49///
50/// - A `SafeHash` is only constructed for non-`EMPTY_BUCKET` hash. We get
51/// around hashes of zero by changing them to 0x8000_0000_0000_0000,
52/// which will likely map to the same bucket, while not being confused
53/// with "empty".
54///
55/// - All three "arrays represented by pointers" are the same length:
56/// `capacity`. This is set at creation and never changes. The arrays
57/// are unzipped to save space (we don't have to pay for the padding
58/// between odd sized elements, such as in a map from u64 to u8), and
59/// be more cache aware (scanning through 8 hashes brings in at most
60/// 2 cache lines, since they're all right beside each other).
61///
62/// You can kind of think of this module/data structure as a safe wrapper
63/// around just the "table" part of the hashtable. It enforces some
64/// invariants at the type level and employs some performance trickery,
65/// but in general is just a tricked out `Vec<Option<u64, K, V>>`.
66#[unsafe_no_drop_flag]
67pub struct RawTable<K, V> {
85aaf69f
SL
68 capacity: usize,
69 size: usize,
1a4d82fc 70 hashes: Unique<u64>,
85aaf69f 71
1a4d82fc
JJ
72 // Because K/V do not appear directly in any of the types in the struct,
73 // inform rustc that in fact instances of K and V are reachable from here.
85aaf69f 74 marker: marker::PhantomData<(K,V)>,
1a4d82fc
JJ
75}
76
85aaf69f
SL
77unsafe impl<K: Send, V: Send> Send for RawTable<K, V> {}
78unsafe impl<K: Sync, V: Sync> Sync for RawTable<K, V> {}
79
1a4d82fc
JJ
80struct RawBucket<K, V> {
81 hash: *mut u64,
82 key: *mut K,
85aaf69f
SL
83 val: *mut V,
84 _marker: marker::PhantomData<(K,V)>,
1a4d82fc
JJ
85}
86
87impl<K,V> Copy for RawBucket<K,V> {}
c34b1796
AL
88impl<K,V> Clone for RawBucket<K,V> {
89 fn clone(&self) -> RawBucket<K, V> { *self }
90}
1a4d82fc
JJ
91
92pub struct Bucket<K, V, M> {
93 raw: RawBucket<K, V>,
85aaf69f 94 idx: usize,
1a4d82fc
JJ
95 table: M
96}
97
98impl<K,V,M:Copy> Copy for Bucket<K,V,M> {}
c34b1796
AL
99impl<K,V,M:Copy> Clone for Bucket<K,V,M> {
100 fn clone(&self) -> Bucket<K,V,M> { *self }
101}
1a4d82fc
JJ
102
103pub struct EmptyBucket<K, V, M> {
104 raw: RawBucket<K, V>,
85aaf69f 105 idx: usize,
1a4d82fc
JJ
106 table: M
107}
108
109pub struct FullBucket<K, V, M> {
110 raw: RawBucket<K, V>,
85aaf69f 111 idx: usize,
1a4d82fc
JJ
112 table: M
113}
114
115pub type EmptyBucketImm<'table, K, V> = EmptyBucket<K, V, &'table RawTable<K, V>>;
116pub type FullBucketImm<'table, K, V> = FullBucket<K, V, &'table RawTable<K, V>>;
117
118pub type EmptyBucketMut<'table, K, V> = EmptyBucket<K, V, &'table mut RawTable<K, V>>;
119pub type FullBucketMut<'table, K, V> = FullBucket<K, V, &'table mut RawTable<K, V>>;
120
121pub enum BucketState<K, V, M> {
122 Empty(EmptyBucket<K, V, M>),
123 Full(FullBucket<K, V, M>),
124}
125
126// A GapThenFull encapsulates the state of two consecutive buckets at once.
127// The first bucket, called the gap, is known to be empty.
128// The second bucket is full.
129struct GapThenFull<K, V, M> {
130 gap: EmptyBucket<K, V, ()>,
131 full: FullBucket<K, V, M>,
132}
133
134/// A hash that is not zero, since we use a hash of zero to represent empty
135/// buckets.
c34b1796 136#[derive(PartialEq, Copy, Clone)]
1a4d82fc
JJ
137pub struct SafeHash {
138 hash: u64,
139}
140
141impl SafeHash {
142 /// Peek at the hash value, which is guaranteed to be non-zero.
143 #[inline(always)]
144 pub fn inspect(&self) -> u64 { self.hash }
145}
146
147/// We need to remove hashes of 0. That's reserved for empty buckets.
148/// This function wraps up `hash_keyed` to be the only way outside this
149/// module to generate a SafeHash.
85aaf69f
SL
150pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
151 where T: Hash, S: HashState
152{
153 let mut state = hash_state.hasher();
154 t.hash(&mut state);
c34b1796 155 // We need to avoid 0 in order to prevent collisions with
85aaf69f
SL
156 // EMPTY_HASH. We can maintain our precious uniform distribution
157 // of initial indexes by unconditionally setting the MSB,
158 // effectively reducing 64-bits hashes to 63 bits.
159 SafeHash { hash: 0x8000_0000_0000_0000 | state.finish() }
160}
161
1a4d82fc
JJ
162// `replace` casts a `*u64` to a `*SafeHash`. Since we statically
163// ensure that a `FullBucket` points to an index with a non-zero hash,
164// and a `SafeHash` is just a `u64` with a different name, this is
165// safe.
166//
167// This test ensures that a `SafeHash` really IS the same size as a
168// `u64`. If you need to change the size of `SafeHash` (and
169// consequently made this test fail), `replace` needs to be
170// modified to no longer assume this.
171#[test]
172fn can_alias_safehash_as_u64() {
173 assert_eq!(size_of::<SafeHash>(), size_of::<u64>())
174}
175
176impl<K, V> RawBucket<K, V> {
85aaf69f 177 unsafe fn offset(self, count: isize) -> RawBucket<K, V> {
1a4d82fc
JJ
178 RawBucket {
179 hash: self.hash.offset(count),
180 key: self.key.offset(count),
181 val: self.val.offset(count),
85aaf69f 182 _marker: marker::PhantomData,
1a4d82fc
JJ
183 }
184 }
185}
186
187// Buckets hold references to the table.
188impl<K, V, M> FullBucket<K, V, M> {
189 /// Borrow a reference to the table.
190 pub fn table(&self) -> &M {
191 &self.table
192 }
193 /// Move out the reference to the table.
194 pub fn into_table(self) -> M {
195 self.table
196 }
197 /// Get the raw index.
85aaf69f 198 pub fn index(&self) -> usize {
1a4d82fc
JJ
199 self.idx
200 }
201}
202
203impl<K, V, M> EmptyBucket<K, V, M> {
204 /// Borrow a reference to the table.
205 pub fn table(&self) -> &M {
206 &self.table
207 }
208 /// Move out the reference to the table.
209 pub fn into_table(self) -> M {
210 self.table
211 }
212}
213
214impl<K, V, M> Bucket<K, V, M> {
215 /// Move out the reference to the table.
216 pub fn into_table(self) -> M {
217 self.table
218 }
219 /// Get the raw index.
85aaf69f 220 pub fn index(&self) -> usize {
1a4d82fc
JJ
221 self.idx
222 }
223}
224
225impl<K, V, M: Deref<Target=RawTable<K, V>>> Bucket<K, V, M> {
226 pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> {
85aaf69f 227 Bucket::at_index(table, hash.inspect() as usize)
1a4d82fc
JJ
228 }
229
85aaf69f 230 pub fn at_index(table: M, ib_index: usize) -> Bucket<K, V, M> {
c34b1796
AL
231 // if capacity is 0, then the RawBucket will be populated with bogus pointers.
232 // This is an uncommon case though, so avoid it in release builds.
233 debug_assert!(table.capacity() > 0, "Table should have capacity at this point");
1a4d82fc
JJ
234 let ib_index = ib_index & (table.capacity() - 1);
235 Bucket {
236 raw: unsafe {
85aaf69f 237 table.first_bucket_raw().offset(ib_index as isize)
1a4d82fc
JJ
238 },
239 idx: ib_index,
240 table: table
241 }
242 }
243
244 pub fn first(table: M) -> Bucket<K, V, M> {
245 Bucket {
246 raw: table.first_bucket_raw(),
247 idx: 0,
248 table: table
249 }
250 }
251
252 /// Reads a bucket at a given index, returning an enum indicating whether
253 /// it's initialized or not. You need to match on this enum to get
254 /// the appropriate types to call most of the other functions in
255 /// this module.
256 pub fn peek(self) -> BucketState<K, V, M> {
257 match unsafe { *self.raw.hash } {
258 EMPTY_BUCKET =>
259 Empty(EmptyBucket {
260 raw: self.raw,
261 idx: self.idx,
262 table: self.table
263 }),
264 _ =>
265 Full(FullBucket {
266 raw: self.raw,
267 idx: self.idx,
268 table: self.table
269 })
270 }
271 }
272
273 /// Modifies the bucket pointer in place to make it point to the next slot.
274 pub fn next(&mut self) {
275 // Branchless bucket iteration step.
276 // As we reach the end of the table...
277 // We take the current idx: 0111111b
278 // Xor it by its increment: ^ 1000000b
279 // ------------
280 // 1111111b
281 // Then AND with the capacity: & 1000000b
282 // ------------
283 // to get the backwards offset: 1000000b
284 // ... and it's zero at all other times.
285 let maybe_wraparound_dist = (self.idx ^ (self.idx + 1)) & self.table.capacity();
286 // Finally, we obtain the offset 1 or the offset -cap + 1.
85aaf69f 287 let dist = 1 - (maybe_wraparound_dist as isize);
1a4d82fc
JJ
288
289 self.idx += 1;
290
291 unsafe {
292 self.raw = self.raw.offset(dist);
293 }
294 }
295}
296
297impl<K, V, M: Deref<Target=RawTable<K, V>>> EmptyBucket<K, V, M> {
298 #[inline]
299 pub fn next(self) -> Bucket<K, V, M> {
300 let mut bucket = self.into_bucket();
301 bucket.next();
302 bucket
303 }
304
305 #[inline]
306 pub fn into_bucket(self) -> Bucket<K, V, M> {
307 Bucket {
308 raw: self.raw,
309 idx: self.idx,
310 table: self.table
311 }
312 }
313
314 pub fn gap_peek(self) -> Option<GapThenFull<K, V, M>> {
315 let gap = EmptyBucket {
316 raw: self.raw,
317 idx: self.idx,
318 table: ()
319 };
320
321 match self.next().peek() {
322 Full(bucket) => {
323 Some(GapThenFull {
324 gap: gap,
325 full: bucket
326 })
327 }
328 Empty(..) => None
329 }
330 }
331}
332
333impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> EmptyBucket<K, V, M> {
334 /// Puts given key and value pair, along with the key's hash,
335 /// into this bucket in the hashtable. Note how `self` is 'moved' into
336 /// this function, because this slot will no longer be empty when
337 /// we return! A `FullBucket` is returned for later use, pointing to
338 /// the newly-filled slot in the hashtable.
339 ///
340 /// Use `make_hash` to construct a `SafeHash` to pass to this function.
341 pub fn put(mut self, hash: SafeHash, key: K, value: V)
342 -> FullBucket<K, V, M> {
343 unsafe {
344 *self.raw.hash = hash.inspect();
345 ptr::write(self.raw.key, key);
346 ptr::write(self.raw.val, value);
347 }
348
349 self.table.size += 1;
350
351 FullBucket { raw: self.raw, idx: self.idx, table: self.table }
352 }
353}
354
355impl<K, V, M: Deref<Target=RawTable<K, V>>> FullBucket<K, V, M> {
356 #[inline]
357 pub fn next(self) -> Bucket<K, V, M> {
358 let mut bucket = self.into_bucket();
359 bucket.next();
360 bucket
361 }
362
363 #[inline]
364 pub fn into_bucket(self) -> Bucket<K, V, M> {
365 Bucket {
366 raw: self.raw,
367 idx: self.idx,
368 table: self.table
369 }
370 }
371
372 /// Get the distance between this bucket and the 'ideal' location
373 /// as determined by the key's hash stored in it.
374 ///
375 /// In the cited blog posts above, this is called the "distance to
376 /// initial bucket", or DIB. Also known as "probe count".
85aaf69f 377 pub fn distance(&self) -> usize {
1a4d82fc
JJ
378 // Calculates the distance one has to travel when going from
379 // `hash mod capacity` onwards to `idx mod capacity`, wrapping around
380 // if the destination is not reached before the end of the table.
c34b1796 381 (self.idx.wrapping_sub(self.hash().inspect() as usize)) & (self.table.capacity() - 1)
1a4d82fc
JJ
382 }
383
384 #[inline]
385 pub fn hash(&self) -> SafeHash {
386 unsafe {
387 SafeHash {
388 hash: *self.raw.hash
389 }
390 }
391 }
392
393 /// Gets references to the key and value at a given index.
394 pub fn read(&self) -> (&K, &V) {
395 unsafe {
396 (&*self.raw.key,
397 &*self.raw.val)
398 }
399 }
400}
401
402impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> FullBucket<K, V, M> {
403 /// Removes this bucket's key and value from the hashtable.
404 ///
405 /// This works similarly to `put`, building an `EmptyBucket` out of the
406 /// taken bucket.
407 pub fn take(mut self) -> (EmptyBucket<K, V, M>, K, V) {
1a4d82fc
JJ
408 self.table.size -= 1;
409
410 unsafe {
411 *self.raw.hash = EMPTY_BUCKET;
412 (
413 EmptyBucket {
414 raw: self.raw,
415 idx: self.idx,
416 table: self.table
417 },
85aaf69f
SL
418 ptr::read(self.raw.key),
419 ptr::read(self.raw.val)
1a4d82fc
JJ
420 )
421 }
422 }
423
424 pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) {
425 unsafe {
426 let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h);
427 let old_key = ptr::replace(self.raw.key, k);
428 let old_val = ptr::replace(self.raw.val, v);
429
430 (old_hash, old_key, old_val)
431 }
432 }
433
434 /// Gets mutable references to the key and value at a given index.
435 pub fn read_mut(&mut self) -> (&mut K, &mut V) {
436 unsafe {
437 (&mut *self.raw.key,
438 &mut *self.raw.val)
439 }
440 }
441}
442
443impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + 't> FullBucket<K, V, M> {
444 /// Exchange a bucket state for immutable references into the table.
445 /// Because the underlying reference to the table is also consumed,
446 /// no further changes to the structure of the table are possible;
447 /// in exchange for this, the returned references have a longer lifetime
448 /// than the references returned by `read()`.
449 pub fn into_refs(self) -> (&'t K, &'t V) {
450 unsafe {
451 (&*self.raw.key,
452 &*self.raw.val)
453 }
454 }
455}
456
457impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + DerefMut + 't> FullBucket<K, V, M> {
458 /// This works similarly to `into_refs`, exchanging a bucket state
459 /// for mutable references into the table.
460 pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
461 unsafe {
462 (&mut *self.raw.key,
463 &mut *self.raw.val)
464 }
465 }
466}
467
468impl<K, V, M> BucketState<K, V, M> {
469 // For convenience.
470 pub fn expect_full(self) -> FullBucket<K, V, M> {
471 match self {
472 Full(full) => full,
473 Empty(..) => panic!("Expected full bucket")
474 }
475 }
476}
477
478impl<K, V, M: Deref<Target=RawTable<K, V>>> GapThenFull<K, V, M> {
479 #[inline]
480 pub fn full(&self) -> &FullBucket<K, V, M> {
481 &self.full
482 }
483
484 pub fn shift(mut self) -> Option<GapThenFull<K, V, M>> {
485 unsafe {
486 *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
c34b1796
AL
487 ptr::copy_nonoverlapping(self.full.raw.key, self.gap.raw.key, 1);
488 ptr::copy_nonoverlapping(self.full.raw.val, self.gap.raw.val, 1);
1a4d82fc
JJ
489 }
490
491 let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
492
493 match self.full.next().peek() {
494 Full(bucket) => {
495 self.gap.raw = prev_raw;
496 self.gap.idx = prev_idx;
497
498 self.full = bucket;
499
500 Some(self)
501 }
502 Empty(..) => None
503 }
504 }
505}
506
507
508/// Rounds up to a multiple of a power of two. Returns the closest multiple
509/// of `target_alignment` that is higher or equal to `unrounded`.
510///
511/// # Panics
512///
513/// Panics if `target_alignment` is not a power of two.
85aaf69f 514fn round_up_to_next(unrounded: usize, target_alignment: usize) -> usize {
1a4d82fc
JJ
515 assert!(target_alignment.is_power_of_two());
516 (unrounded + target_alignment - 1) & !(target_alignment - 1)
517}
518
519#[test]
520fn test_rounding() {
521 assert_eq!(round_up_to_next(0, 4), 0);
522 assert_eq!(round_up_to_next(1, 4), 4);
523 assert_eq!(round_up_to_next(2, 4), 4);
524 assert_eq!(round_up_to_next(3, 4), 4);
525 assert_eq!(round_up_to_next(4, 4), 4);
526 assert_eq!(round_up_to_next(5, 4), 8);
527}
528
529// Returns a tuple of (key_offset, val_offset),
530// from the start of a mallocated array.
62682a34 531#[inline]
85aaf69f
SL
532fn calculate_offsets(hashes_size: usize,
533 keys_size: usize, keys_align: usize,
534 vals_align: usize)
c34b1796 535 -> (usize, usize, bool) {
1a4d82fc 536 let keys_offset = round_up_to_next(hashes_size, keys_align);
c34b1796 537 let (end_of_keys, oflo) = keys_offset.overflowing_add(keys_size);
1a4d82fc
JJ
538
539 let vals_offset = round_up_to_next(end_of_keys, vals_align);
540
c34b1796 541 (keys_offset, vals_offset, oflo)
1a4d82fc
JJ
542}
543
544// Returns a tuple of (minimum required malloc alignment, hash_offset,
545// array_size), from the start of a mallocated array.
85aaf69f
SL
546fn calculate_allocation(hash_size: usize, hash_align: usize,
547 keys_size: usize, keys_align: usize,
548 vals_size: usize, vals_align: usize)
c34b1796 549 -> (usize, usize, usize, bool) {
1a4d82fc 550 let hash_offset = 0;
c34b1796
AL
551 let (_, vals_offset, oflo) = calculate_offsets(hash_size,
552 keys_size, keys_align,
553 vals_align);
554 let (end_of_vals, oflo2) = vals_offset.overflowing_add(vals_size);
1a4d82fc 555
62682a34 556 let align = cmp::max(hash_align, cmp::max(keys_align, vals_align));
1a4d82fc 557
62682a34 558 (align, hash_offset, end_of_vals, oflo || oflo2)
1a4d82fc
JJ
559}
560
561#[test]
562fn test_offset_calculation() {
c34b1796
AL
563 assert_eq!(calculate_allocation(128, 8, 15, 1, 4, 4), (8, 0, 148, false));
564 assert_eq!(calculate_allocation(3, 1, 2, 1, 1, 1), (1, 0, 6, false));
565 assert_eq!(calculate_allocation(6, 2, 12, 4, 24, 8), (8, 0, 48, false));
566 assert_eq!(calculate_offsets(128, 15, 1, 4), (128, 144, false));
567 assert_eq!(calculate_offsets(3, 2, 1, 1), (3, 5, false));
568 assert_eq!(calculate_offsets(6, 12, 4, 8), (8, 24, false));
1a4d82fc
JJ
569}
570
571impl<K, V> RawTable<K, V> {
572 /// Does not initialize the buckets. The caller should ensure they,
573 /// at the very least, set every hash to EMPTY_BUCKET.
85aaf69f 574 unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
1a4d82fc
JJ
575 if capacity == 0 {
576 return RawTable {
577 size: 0,
578 capacity: 0,
85aaf69f
SL
579 hashes: Unique::new(EMPTY as *mut u64),
580 marker: marker::PhantomData,
1a4d82fc
JJ
581 };
582 }
85aaf69f 583
1a4d82fc
JJ
584 // No need for `checked_mul` before a more restrictive check performed
585 // later in this method.
586 let hashes_size = capacity * size_of::<u64>();
587 let keys_size = capacity * size_of::< K >();
588 let vals_size = capacity * size_of::< V >();
589
590 // Allocating hashmaps is a little tricky. We need to allocate three
591 // arrays, but since we know their sizes and alignments up front,
592 // we just allocate a single array, and then have the subarrays
593 // point into it.
594 //
595 // This is great in theory, but in practice getting the alignment
596 // right is a little subtle. Therefore, calculating offsets has been
597 // factored out into a different function.
c34b1796 598 let (malloc_alignment, hash_offset, size, oflo) =
1a4d82fc 599 calculate_allocation(
62682a34
SL
600 hashes_size, align_of::<u64>(),
601 keys_size, align_of::< K >(),
602 vals_size, align_of::< V >());
1a4d82fc 603
c34b1796
AL
604 assert!(!oflo, "capacity overflow");
605
1a4d82fc
JJ
606 // One check for overflow that covers calculation and rounding of size.
607 let size_of_bucket = size_of::<u64>().checked_add(size_of::<K>()).unwrap()
608 .checked_add(size_of::<V>()).unwrap();
609 assert!(size >= capacity.checked_mul(size_of_bucket)
610 .expect("capacity overflow"),
611 "capacity overflow");
612
613 let buffer = allocate(size, malloc_alignment);
614 if buffer.is_null() { ::alloc::oom() }
615
85aaf69f 616 let hashes = buffer.offset(hash_offset as isize) as *mut u64;
1a4d82fc
JJ
617
618 RawTable {
619 capacity: capacity,
620 size: 0,
85aaf69f
SL
621 hashes: Unique::new(hashes),
622 marker: marker::PhantomData,
1a4d82fc
JJ
623 }
624 }
625
626 fn first_bucket_raw(&self) -> RawBucket<K, V> {
627 let hashes_size = self.capacity * size_of::<u64>();
628 let keys_size = self.capacity * size_of::<K>();
629
85aaf69f 630 let buffer = *self.hashes as *mut u8;
c34b1796
AL
631 let (keys_offset, vals_offset, oflo) =
632 calculate_offsets(hashes_size,
62682a34
SL
633 keys_size, align_of::<K>(),
634 align_of::<V>());
c34b1796 635 debug_assert!(!oflo, "capacity overflow");
1a4d82fc
JJ
636 unsafe {
637 RawBucket {
85aaf69f
SL
638 hash: *self.hashes,
639 key: buffer.offset(keys_offset as isize) as *mut K,
640 val: buffer.offset(vals_offset as isize) as *mut V,
641 _marker: marker::PhantomData,
1a4d82fc
JJ
642 }
643 }
644 }
645
646 /// Creates a new raw table from a given capacity. All buckets are
647 /// initially empty.
85aaf69f 648 pub fn new(capacity: usize) -> RawTable<K, V> {
1a4d82fc
JJ
649 unsafe {
650 let ret = RawTable::new_uninitialized(capacity);
c34b1796 651 ptr::write_bytes(*ret.hashes, 0, capacity);
1a4d82fc
JJ
652 ret
653 }
654 }
655
656 /// The hashtable's capacity, similar to a vector's.
85aaf69f 657 pub fn capacity(&self) -> usize {
1a4d82fc
JJ
658 self.capacity
659 }
660
661 /// The number of elements ever `put` in the hashtable, minus the number
662 /// of elements ever `take`n.
85aaf69f 663 pub fn size(&self) -> usize {
1a4d82fc
JJ
664 self.size
665 }
666
667 fn raw_buckets(&self) -> RawBuckets<K, V> {
668 RawBuckets {
669 raw: self.first_bucket_raw(),
670 hashes_end: unsafe {
85aaf69f 671 self.hashes.offset(self.capacity as isize)
1a4d82fc 672 },
85aaf69f 673 marker: marker::PhantomData,
1a4d82fc
JJ
674 }
675 }
676
677 pub fn iter(&self) -> Iter<K, V> {
678 Iter {
679 iter: self.raw_buckets(),
680 elems_left: self.size(),
681 }
682 }
683
684 pub fn iter_mut(&mut self) -> IterMut<K, V> {
685 IterMut {
686 iter: self.raw_buckets(),
687 elems_left: self.size(),
688 }
689 }
690
691 pub fn into_iter(self) -> IntoIter<K, V> {
692 let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
693 // Replace the marker regardless of lifetime bounds on parameters.
694 IntoIter {
695 iter: RawBuckets {
696 raw: raw,
697 hashes_end: hashes_end,
85aaf69f 698 marker: marker::PhantomData,
1a4d82fc
JJ
699 },
700 table: self,
701 }
702 }
703
704 pub fn drain(&mut self) -> Drain<K, V> {
705 let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
706 // Replace the marker regardless of lifetime bounds on parameters.
707 Drain {
708 iter: RawBuckets {
709 raw: raw,
710 hashes_end: hashes_end,
85aaf69f 711 marker: marker::PhantomData,
1a4d82fc
JJ
712 },
713 table: self,
714 }
715 }
716
717 /// Returns an iterator that copies out each entry. Used while the table
718 /// is being dropped.
719 unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets<K, V> {
720 let raw_bucket = self.first_bucket_raw();
721 RevMoveBuckets {
85aaf69f 722 raw: raw_bucket.offset(self.capacity as isize),
1a4d82fc
JJ
723 hashes_end: raw_bucket.hash,
724 elems_left: self.size,
85aaf69f 725 marker: marker::PhantomData,
1a4d82fc
JJ
726 }
727 }
728}
729
730/// A raw iterator. The basis for some other iterators in this module. Although
731/// this interface is safe, it's not used outside this module.
732struct RawBuckets<'a, K, V> {
733 raw: RawBucket<K, V>,
734 hashes_end: *mut u64,
85aaf69f
SL
735
736 // Strictly speaking, this should be &'a (K,V), but that would
737 // require that K:'a, and we often use RawBuckets<'static...> for
738 // move iterations, so that messes up a lot of other things. So
739 // just use `&'a (K,V)` as this is not a publicly exposed type
740 // anyway.
741 marker: marker::PhantomData<&'a ()>,
1a4d82fc
JJ
742}
743
744// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
745impl<'a, K, V> Clone for RawBuckets<'a, K, V> {
746 fn clone(&self) -> RawBuckets<'a, K, V> {
747 RawBuckets {
748 raw: self.raw,
749 hashes_end: self.hashes_end,
85aaf69f 750 marker: marker::PhantomData,
1a4d82fc
JJ
751 }
752 }
753}
754
755
756impl<'a, K, V> Iterator for RawBuckets<'a, K, V> {
757 type Item = RawBucket<K, V>;
758
759 fn next(&mut self) -> Option<RawBucket<K, V>> {
760 while self.raw.hash != self.hashes_end {
761 unsafe {
762 // We are swapping out the pointer to a bucket and replacing
763 // it with the pointer to the next one.
764 let prev = ptr::replace(&mut self.raw, self.raw.offset(1));
765 if *prev.hash != EMPTY_BUCKET {
766 return Some(prev);
767 }
768 }
769 }
770
771 None
772 }
773}
774
775/// An iterator that moves out buckets in reverse order. It leaves the table
776/// in an inconsistent state and should only be used for dropping
777/// the table's remaining entries. It's used in the implementation of Drop.
778struct RevMoveBuckets<'a, K, V> {
779 raw: RawBucket<K, V>,
780 hashes_end: *mut u64,
85aaf69f
SL
781 elems_left: usize,
782
783 // As above, `&'a (K,V)` would seem better, but we often use
784 // 'static for the lifetime, and this is not a publicly exposed
785 // type.
786 marker: marker::PhantomData<&'a ()>,
1a4d82fc
JJ
787}
788
789impl<'a, K, V> Iterator for RevMoveBuckets<'a, K, V> {
790 type Item = (K, V);
791
792 fn next(&mut self) -> Option<(K, V)> {
793 if self.elems_left == 0 {
794 return None;
795 }
796
797 loop {
798 debug_assert!(self.raw.hash != self.hashes_end);
799
800 unsafe {
801 self.raw = self.raw.offset(-1);
802
803 if *self.raw.hash != EMPTY_BUCKET {
804 self.elems_left -= 1;
805 return Some((
85aaf69f
SL
806 ptr::read(self.raw.key),
807 ptr::read(self.raw.val)
1a4d82fc
JJ
808 ));
809 }
810 }
811 }
812 }
813}
814
815/// Iterator over shared references to entries in a table.
816pub struct Iter<'a, K: 'a, V: 'a> {
817 iter: RawBuckets<'a, K, V>,
85aaf69f 818 elems_left: usize,
1a4d82fc
JJ
819}
820
821// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
822impl<'a, K, V> Clone for Iter<'a, K, V> {
823 fn clone(&self) -> Iter<'a, K, V> {
824 Iter {
825 iter: self.iter.clone(),
826 elems_left: self.elems_left
827 }
828 }
829}
830
831
832/// Iterator over mutable references to entries in a table.
833pub struct IterMut<'a, K: 'a, V: 'a> {
834 iter: RawBuckets<'a, K, V>,
85aaf69f 835 elems_left: usize,
1a4d82fc
JJ
836}
837
838/// Iterator over the entries in a table, consuming the table.
839pub struct IntoIter<K, V> {
840 table: RawTable<K, V>,
841 iter: RawBuckets<'static, K, V>
842}
843
844/// Iterator over the entries in a table, clearing the table.
845pub struct Drain<'a, K: 'a, V: 'a> {
846 table: &'a mut RawTable<K, V>,
847 iter: RawBuckets<'static, K, V>,
848}
849
850impl<'a, K, V> Iterator for Iter<'a, K, V> {
851 type Item = (&'a K, &'a V);
852
853 fn next(&mut self) -> Option<(&'a K, &'a V)> {
854 self.iter.next().map(|bucket| {
855 self.elems_left -= 1;
856 unsafe {
857 (&*bucket.key,
858 &*bucket.val)
859 }
860 })
861 }
862
85aaf69f 863 fn size_hint(&self) -> (usize, Option<usize>) {
1a4d82fc
JJ
864 (self.elems_left, Some(self.elems_left))
865 }
866}
85aaf69f
SL
867impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
868 fn len(&self) -> usize { self.elems_left }
869}
1a4d82fc
JJ
870
871impl<'a, K, V> Iterator for IterMut<'a, K, V> {
872 type Item = (&'a K, &'a mut V);
873
874 fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
875 self.iter.next().map(|bucket| {
876 self.elems_left -= 1;
877 unsafe {
878 (&*bucket.key,
879 &mut *bucket.val)
880 }
881 })
882 }
883
85aaf69f 884 fn size_hint(&self) -> (usize, Option<usize>) {
1a4d82fc
JJ
885 (self.elems_left, Some(self.elems_left))
886 }
887}
85aaf69f
SL
888impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
889 fn len(&self) -> usize { self.elems_left }
890}
1a4d82fc
JJ
891
892impl<K, V> Iterator for IntoIter<K, V> {
893 type Item = (SafeHash, K, V);
894
895 fn next(&mut self) -> Option<(SafeHash, K, V)> {
896 self.iter.next().map(|bucket| {
897 self.table.size -= 1;
898 unsafe {
899 (
900 SafeHash {
901 hash: *bucket.hash,
902 },
85aaf69f
SL
903 ptr::read(bucket.key),
904 ptr::read(bucket.val)
1a4d82fc
JJ
905 )
906 }
907 })
908 }
909
85aaf69f 910 fn size_hint(&self) -> (usize, Option<usize>) {
1a4d82fc
JJ
911 let size = self.table.size();
912 (size, Some(size))
913 }
914}
85aaf69f
SL
915impl<K, V> ExactSizeIterator for IntoIter<K, V> {
916 fn len(&self) -> usize { self.table.size() }
917}
1a4d82fc 918
85aaf69f 919impl<'a, K, V> Iterator for Drain<'a, K, V> {
1a4d82fc
JJ
920 type Item = (SafeHash, K, V);
921
922 #[inline]
923 fn next(&mut self) -> Option<(SafeHash, K, V)> {
924 self.iter.next().map(|bucket| {
925 self.table.size -= 1;
926 unsafe {
927 (
928 SafeHash {
929 hash: ptr::replace(bucket.hash, EMPTY_BUCKET),
930 },
85aaf69f
SL
931 ptr::read(bucket.key),
932 ptr::read(bucket.val)
1a4d82fc
JJ
933 )
934 }
935 })
936 }
937
85aaf69f 938 fn size_hint(&self) -> (usize, Option<usize>) {
1a4d82fc
JJ
939 let size = self.table.size();
940 (size, Some(size))
941 }
942}
85aaf69f
SL
943impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
944 fn len(&self) -> usize { self.table.size() }
945}
1a4d82fc 946
1a4d82fc
JJ
947impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
948 fn drop(&mut self) {
85aaf69f 949 for _ in self.by_ref() {}
1a4d82fc
JJ
950 }
951}
952
953impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
954 fn clone(&self) -> RawTable<K, V> {
955 unsafe {
956 let mut new_ht = RawTable::new_uninitialized(self.capacity());
957
958 {
959 let cap = self.capacity();
960 let mut new_buckets = Bucket::first(&mut new_ht);
961 let mut buckets = Bucket::first(self);
962 while buckets.index() != cap {
963 match buckets.peek() {
964 Full(full) => {
965 let (h, k, v) = {
966 let (k, v) = full.read();
967 (full.hash(), k.clone(), v.clone())
968 };
969 *new_buckets.raw.hash = h.inspect();
970 ptr::write(new_buckets.raw.key, k);
971 ptr::write(new_buckets.raw.val, v);
972 }
973 Empty(..) => {
974 *new_buckets.raw.hash = EMPTY_BUCKET;
975 }
976 }
977 new_buckets.next();
978 buckets.next();
979 }
980 };
981
982 new_ht.size = self.size();
983
984 new_ht
985 }
986 }
987}
988
1a4d82fc
JJ
989impl<K, V> Drop for RawTable<K, V> {
990 fn drop(&mut self) {
c34b1796 991 if self.capacity == 0 || self.capacity == mem::POST_DROP_USIZE {
1a4d82fc
JJ
992 return;
993 }
85aaf69f 994
1a4d82fc
JJ
995 // This is done in reverse because we've likely partially taken
996 // some elements out with `.into_iter()` from the front.
997 // Check if the size is 0, so we don't do a useless scan when
998 // dropping empty tables such as on resize.
999 // Also avoid double drop of elements that have been already moved out.
1000 unsafe {
1001 for _ in self.rev_move_buckets() {}
1002 }
1003
1004 let hashes_size = self.capacity * size_of::<u64>();
1005 let keys_size = self.capacity * size_of::<K>();
1006 let vals_size = self.capacity * size_of::<V>();
c34b1796 1007 let (align, _, size, oflo) =
62682a34
SL
1008 calculate_allocation(hashes_size, align_of::<u64>(),
1009 keys_size, align_of::<K>(),
1010 vals_size, align_of::<V>());
c34b1796
AL
1011
1012 debug_assert!(!oflo, "should be impossible");
1a4d82fc
JJ
1013
1014 unsafe {
85aaf69f 1015 deallocate(*self.hashes as *mut u8, size, align);
1a4d82fc
JJ
1016 // Remember how everything was allocated out of one buffer
1017 // during initialization? We only need one call to free here.
1018 }
1019 }
1020}