Skip to content

Commit

Permalink
fix race during incremental copy
Browse files Browse the repository at this point in the history
  • Loading branch information
ibraheemdev committed May 6, 2024
1 parent ece4110 commit ce92176
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 12 deletions.
18 changes: 11 additions & 7 deletions src/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ where

match unsafe { self.table.entry(i) }.compare_exchange_weak(
entry.raw,
new_entry as _,
new_entry.cast(),
Ordering::AcqRel,
Ordering::Acquire,
) {
Expand Down Expand Up @@ -963,13 +963,13 @@ where
}
}

let mut next = None;
let mut next: Option<(Table<K, V>, usize)> = None;

loop {
// the entry was deleted
if entry.addr & Entry::TOMBSTONE != 0 {
// if we already inserted into the new table, we have to delete the copy
if let Some(next) = next {
if let Some((next_table, next)) = next {
unsafe {
// delete the entry we inserted
next_table
Expand Down Expand Up @@ -999,7 +999,7 @@ where
match next {
// we already inserted into the table but the entry changed,
// so we just update the copy
Some(next) => unsafe {
Some((next_table, next)) => unsafe {
next_table.entry(next).store(
entry.ptr.map_addr(|addr| addr | Entry::BORROWED),
Ordering::Release,
Expand Down Expand Up @@ -1047,7 +1047,11 @@ where
//
// If `abort` is `true`, this method returns `None` if the table is full.
// Otherwise, it will recursively try to allocate and insert into a resize.
fn insert_copy(&self, new_entry: Tagged<*mut Entry<K, V>>, abort: bool) -> Option<usize> {
fn insert_copy(
&self,
new_entry: Tagged<*mut Entry<K, V>>,
abort: bool,
) -> Option<(Table<K, V>, usize)> {
let key = unsafe { &(*new_entry.ptr).key };

let hash = self.root.hasher.hash_one(key);
Expand Down Expand Up @@ -1076,7 +1080,7 @@ where
) {
Ok(_) => {
unsafe { self.table.meta(i).store(meta::h2(hash), Ordering::Release) };
return Some(i);
return Some((self.table, i));
}
Err(found) => {
fence(Ordering::Acquire);
Expand All @@ -1093,7 +1097,7 @@ where
meta::h2(hash)
};

if self.table.meta(i).load(Ordering::Relaxed) == meta::EMPTY {
if self.table.meta(i).load(Ordering::Acquire) == meta::EMPTY {
self.table.meta(i).store(meta, Ordering::Release);
}
}
Expand Down
8 changes: 3 additions & 5 deletions tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ use std::hash::{BuildHasher, BuildHasherDefault, Hasher};
use std::sync::Arc;

fn with_map<K, V>(test: impl Fn(HashMap<K, V>)) {
let map = HashMap::new().resize_mode(ResizeMode::Blocking);
test(map);

let map = HashMap::new().resize_mode(ResizeMode::Incremental(1));
test(map);
test(HashMap::new().resize_mode(ResizeMode::Blocking));
test(HashMap::new().resize_mode(ResizeMode::Incremental(1)));
test(HashMap::new().resize_mode(ResizeMode::Incremental(128)));
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions tests/stress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::thread;
fn with_map<K, V>(mut test: impl FnMut(&dyn Fn() -> HashMap<K, V>)) {
test(&(|| HashMap::new().resize_mode(ResizeMode::Blocking)));
test(&(|| HashMap::new().resize_mode(ResizeMode::Incremental(1))));
test(&(|| HashMap::new().resize_mode(ResizeMode::Incremental(128))));
}

#[test]
Expand Down

0 comments on commit ce92176

Please sign in to comment.