Skip to content

Simplify hash table drops #40739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 25, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 18 additions & 47 deletions src/libstd/collections/hash/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,15 +896,23 @@ impl<K, V> RawTable<K, V> {
}
}

/// Returns an iterator that copies out each entry. Used while the table
/// is being dropped.
unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets<K, V> {
let raw_bucket = self.first_bucket_raw();
RevMoveBuckets {
raw: raw_bucket.offset(self.capacity as isize),
hashes_end: raw_bucket.hash,
elems_left: self.size,
marker: marker::PhantomData,
/// Drops buckets in reverse order. It leaves the table in an inconsistent
/// state and should only be used for dropping the table's remaining
/// entries. It's used in the implementation of Drop.
unsafe fn rev_drop_buckets(&mut self) {
let first_raw = self.first_bucket_raw();
let mut raw = first_raw.offset(self.capacity as isize);
let mut elems_left = self.size;

while elems_left != 0 {
debug_assert!(raw.hash != first_raw.hash);

raw = raw.offset(-1);

if *raw.hash != EMPTY_BUCKET {
elems_left -= 1;
ptr::drop_in_place(raw.pair as *mut (K, V));
}
}
}

Expand Down Expand Up @@ -964,43 +972,6 @@ impl<'a, K, V> Iterator for RawBuckets<'a, K, V> {
}
}

/// An iterator that moves out buckets in reverse order. It leaves the table
/// in an inconsistent state and should only be used for dropping
/// the table's remaining entries. It's used in the implementation of Drop.
struct RevMoveBuckets<'a, K, V> {
raw: RawBucket<K, V>,
hashes_end: *mut HashUint,
elems_left: usize,

// As above, `&'a (K,V)` would seem better, but we often use
// 'static for the lifetime, and this is not a publicly exposed
// type.
marker: marker::PhantomData<&'a ()>,
}

impl<'a, K, V> Iterator for RevMoveBuckets<'a, K, V> {
type Item = (K, V);

fn next(&mut self) -> Option<(K, V)> {
if self.elems_left == 0 {
return None;
}

loop {
debug_assert!(self.raw.hash != self.hashes_end);

unsafe {
self.raw = self.raw.offset(-1);

if *self.raw.hash != EMPTY_BUCKET {
self.elems_left -= 1;
return Some(ptr::read(self.raw.pair));
}
}
}
}
}

/// Iterator over shared references to entries in a table.
pub struct Iter<'a, K: 'a, V: 'a> {
iter: RawBuckets<'a, K, V>,
Expand Down Expand Up @@ -1227,7 +1198,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
unsafe {
if needs_drop::<(K, V)>() {
// avoid linear runtime for types that don't need drop
for _ in self.rev_move_buckets() {}
self.rev_drop_buckets();
}
}

Expand Down