mod table;
mod bucket;
mod insertion;
mod guard;
mod iter;
pub use self::{
guard::{ReadGuard, Removed},
insertion::{Insertion, Preview},
iter::{IntoIter, Iter, IterMut},
};
pub use std::collections::hash_map::RandomState;
use self::{
bucket::{Bucket, Garbage},
insertion::{InsertNew, Reinsert},
table::Table,
};
use owned_alloc::OwnedAlloc;
use ptr::check_null_align;
use std::{
borrow::Borrow,
fmt,
hash::{BuildHasher, Hash, Hasher},
iter::FromIterator,
mem,
};
pub struct Map<K, V, H = RandomState> {
top: OwnedAlloc<Table<K, V>>,
incin: SharedIncin<K, V>,
builder: H,
}
impl<K, V> Map<K, V> {
pub fn new() -> Self {
check_null_align::<Table<K, V>>();
check_null_align::<Bucket<K, V>>();
Self::default()
}
pub fn with_incin(incin: SharedIncin<K, V>) -> Self {
Self::with_hasher_and_incin(RandomState::default(), incin)
}
}
impl<K, V, H> Map<K, V, H> {
pub fn iter(&self) -> Iter<K, V> {
self.into_iter()
}
pub fn iter_mut(&mut self) -> IterMut<K, V> {
self.into_iter()
}
pub fn optimize_space(&mut self) {
self.incin.clear();
self.top.optimize_space();
}
pub fn clear(&mut self) {
self.incin.clear();
let mut tables = Vec::new();
self.top.clear(&mut tables);
while let Some(mut table) = tables.pop() {
unsafe { table.free_nodes(&mut tables) }
}
}
}
impl<K, V, H> Map<K, V, H>
where
H: BuildHasher,
{
pub fn with_hasher(builder: H) -> Self {
Self::with_hasher_and_incin(builder, SharedIncin::new())
}
pub fn with_hasher_and_incin(builder: H, incin: SharedIncin<K, V>) -> Self {
Self { top: Table::new_alloc(), incin, builder }
}
pub fn incin(&self) -> SharedIncin<K, V> {
self.incin.clone()
}
pub fn hasher(&self) -> &H {
&self.builder
}
pub fn get<'map, Q>(&'map self, key: &Q) -> Option<ReadGuard<'map, K, V>>
where
Q: ?Sized + Hash + Ord,
K: Borrow<Q>,
{
let hash = self.hash_of(key);
let pause = self.incin.inner.pause();
unsafe { self.top.get(key, hash, pause) }
}
pub fn insert(&self, key: K, val: V) -> Option<Removed<K, V>>
where
K: Hash + Ord,
{
let pause = self.incin.inner.pause();
let hash = self.hash_of(&key);
let insertion = unsafe {
self.top.insert(
InsertNew::with_pair(|_, _, _| Preview::Keep, (key, val)),
hash,
&pause,
&self.incin.inner,
)
};
match insertion {
Insertion::Created => None,
Insertion::Updated(old) => Some(old),
Insertion::Failed(_) => unreachable!(),
}
}
pub fn insert_with<F>(
&self,
key: K,
interactive: F,
) -> Insertion<K, V, (K, Option<V>)>
where
K: Hash + Ord,
F: FnMut(&K, Option<&mut V>, Option<&(K, V)>) -> Preview<V>,
{
let hash = self.hash_of(&key);
let pause = self.incin.inner.pause();
let insertion = unsafe {
self.top.insert(
InsertNew::with_key(interactive, key),
hash,
&pause,
&self.incin.inner,
)
};
match insertion {
Insertion::Created => Insertion::Created,
Insertion::Updated(old) => Insertion::Updated(old),
Insertion::Failed(inserter) => {
Insertion::Failed(inserter.into_pair())
},
}
}
pub fn reinsert(
&self,
mut removed: Removed<K, V>,
) -> Insertion<K, V, Removed<K, V>>
where
K: Hash + Ord,
{
if !Removed::is_usable_by(&mut removed, &self.incin.inner) {
return Insertion::Failed(removed);
}
let hash = self.hash_of(removed.key());
let pause = self.incin.inner.pause();
let insertion = unsafe {
self.top.insert(
Reinsert::new(|_, _| true, removed),
hash,
&pause,
&self.incin.inner,
)
};
match insertion {
Insertion::Created => Insertion::Created,
Insertion::Updated(old) => Insertion::Updated(old),
Insertion::Failed(_) => unreachable!(),
}
}
pub fn reinsert_with<F>(
&self,
mut removed: Removed<K, V>,
interactive: F,
) -> Insertion<K, V, Removed<K, V>>
where
K: Hash + Ord,
F: FnMut(&(K, V), Option<&(K, V)>) -> bool,
{
if !Removed::is_usable_by(&mut removed, &self.incin.inner) {
return Insertion::Failed(removed);
}
let hash = self.hash_of(removed.key());
let pause = self.incin.inner.pause();
let insertion = unsafe {
self.top.insert(
Reinsert::new(interactive, removed),
hash,
&pause,
&self.incin.inner,
)
};
match insertion {
Insertion::Created => Insertion::Created,
Insertion::Updated(old) => Insertion::Updated(old),
Insertion::Failed(inserter) => {
Insertion::Failed(inserter.into_removed())
},
}
}
pub fn remove<Q>(&self, key: &Q) -> Option<Removed<K, V>>
where
Q: ?Sized + Hash + Ord,
K: Borrow<Q>,
{
self.remove_with(key, |_| true)
}
pub fn remove_with<Q, F>(
&self,
key: &Q,
interactive: F,
) -> Option<Removed<K, V>>
where
Q: ?Sized + Hash + Ord,
K: Borrow<Q>,
F: FnMut(&(K, V)) -> bool,
{
let hash = self.hash_of(key);
let pause = self.incin.inner.pause();
unsafe {
self.top.remove(key, interactive, hash, &pause, &self.incin.inner)
}
}
pub fn extend<I>(&self, iterable: I)
where
I: IntoIterator<Item = (K, V)>,
K: Hash + Ord,
{
for (key, val) in iterable {
self.insert(key, val);
}
}
fn hash_of<Q>(&self, key: &Q) -> u64
where
Q: ?Sized + Hash,
{
let mut hasher = self.builder.build_hasher();
key.hash(&mut hasher);
hasher.finish()
}
}
impl<K, V, H> Default for Map<K, V, H>
where
H: BuildHasher + Default,
{
fn default() -> Self {
Self::with_hasher(H::default())
}
}
impl<K, V, H> fmt::Debug for Map<K, V, H>
where
H: fmt::Debug,
{
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
write!(
fmtr,
"Map {} top_table: {:?}, incin: {:?}, build_hasher: {:?} {}",
'{', self.top, self.incin.inner, self.builder, '}'
)
}
}
impl<K, V, H> Drop for Map<K, V, H> {
fn drop(&mut self) {
let mut tables = Vec::new();
unsafe { self.top.free_nodes(&mut tables) }
while let Some(mut table) = tables.pop() {
unsafe { table.free_nodes(&mut tables) }
}
}
}
impl<'map, K, V, H> IntoIterator for &'map Map<K, V, H> {
type Item = ReadGuard<'map, K, V>;
type IntoIter = Iter<'map, K, V>;
fn into_iter(self) -> Self::IntoIter {
Iter::new(self.incin.inner.pause(), &self.top)
}
}
impl<'map, K, V, H> IntoIterator for &'map mut Map<K, V, H> {
type Item = (&'map K, &'map mut V);
type IntoIter = IterMut<'map, K, V>;
fn into_iter(self) -> Self::IntoIter {
IterMut::new(&mut self.top)
}
}
impl<K, V, H> IntoIterator for Map<K, V, H> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
fn into_iter(mut self) -> Self::IntoIter {
let raw = self.top.raw();
unsafe {
(&mut self.builder as *mut H).drop_in_place();
(&mut self.incin as *mut SharedIncin<K, V>).drop_in_place();
mem::forget(self);
IntoIter::new(OwnedAlloc::from_raw(raw))
}
}
}
impl<K, V, H> Extend<(K, V)> for Map<K, V, H>
where
H: BuildHasher,
K: Hash + Ord,
{
fn extend<I>(&mut self, iterable: I)
where
I: IntoIterator<Item = (K, V)>,
{
(&*self).extend(iterable)
}
}
impl<K, V, H> FromIterator<(K, V)> for Map<K, V, H>
where
H: BuildHasher + Default,
K: Hash + Ord,
{
fn from_iter<I>(iterable: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
{
let this = Self::default();
this.extend(iterable);
this
}
}
unsafe impl<K, V, H> Send for Map<K, V, H>
where
K: Send,
V: Send,
H: Send,
{
}
unsafe impl<K, V, H> Sync for Map<K, V, H>
where
K: Sync,
V: Sync,
H: Sync,
{
}
make_shared_incin! {
{ "[`Map`]" }
pub SharedIncin<K, V> of Garbage<K, V>
}
impl<K, V> fmt::Debug for SharedIncin<K, V> {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
write!(fmtr, "SharedIncin {} inner: {:?} {}", '{', self.inner, '}')
}
}
#[cfg(test)]
mod test {
use super::*;
use std::{collections::HashMap, sync::Arc, thread};
#[test]
fn inserts_and_gets() {
let map = Map::new();
assert!(map.get("five").is_none());
assert!(map.insert("five".to_owned(), 5).is_none());
assert_eq!(*map.get("five").unwrap().val(), 5);
assert!(map.get("four").is_none());
assert!(map.insert("four".to_owned(), 4).is_none());
assert_eq!(*map.get("five").unwrap().val(), 5);
assert_eq!(*map.get("four").unwrap().val(), 4);
let guard = map.get("four").unwrap();
assert_eq!(guard.key(), "four");
assert_eq!(*guard.val(), 4);
}
#[test]
fn create() {
let map = Map::new();
assert!(map
.insert_with(
"five".to_owned(),
|_, _, stored| if stored.is_none() {
Preview::New(5)
} else {
Preview::Discard
}
)
.created());
assert_eq!(*map.get("five").unwrap().val(), 5);
assert!(map
.insert_with(
"five".to_owned(),
|_, _, stored| if stored.is_none() {
Preview::New(500)
} else {
Preview::Discard
}
)
.failed()
.is_some());
}
#[test]
fn update() {
let map = Map::new();
assert!(map
.insert_with("five".to_owned(), |_, _, stored| {
if let Some((_, n)) = stored {
Preview::New(*n + 6)
} else {
Preview::Discard
}
})
.failed()
.is_some());
assert!(map.insert("five".to_owned(), 5).is_none());
let guard = map
.insert_with("five".to_owned(), |_, _, stored| {
if let Some((_, n)) = stored {
Preview::New(*n + 7)
} else {
Preview::Discard
}
})
.take_updated()
.unwrap();
assert_eq!(guard.key(), "five");
assert_eq!(*guard.val(), 5);
assert_eq!(*map.get("five").unwrap().val(), 12);
}
#[test]
fn never_inserts() {
let map = Map::new();
assert!(map
.insert_with("five".to_owned(), |_, _, _| Preview::Discard)
.failed()
.is_some());
assert!(map.insert("five".to_owned(), 5).is_none());
assert!(map
.insert_with("five".to_owned(), |_, _, _| Preview::Discard)
.failed()
.is_some());
}
#[test]
fn inserts_reinserts() {
let map = Map::new();
assert!(map.insert("four".to_owned(), 4).is_none());
let prev = map.insert("four".to_owned(), 40).unwrap();
assert_eq!(prev.key(), "four");
assert_eq!(*prev.val(), 4);
let prev = map.reinsert(prev).take_updated().unwrap();
assert_eq!(prev.key(), "four");
assert_eq!(*prev.val(), 40);
assert!(*map.get("four").unwrap().val() == 4);
}
#[test]
fn never_reinserts() {
let map = Map::new();
map.insert("five".to_owned(), 5);
let prev = map.remove("five").unwrap();
let prev = map.reinsert_with(prev, |_, _| false).take_failed().unwrap();
assert!(map.insert("five".to_owned(), 5).is_none());
map.reinsert_with(prev, |_, _| false).take_failed().unwrap();
}
#[test]
fn reinserts_create() {
let map = Map::new();
map.insert("five".to_owned(), 5);
let first = map.remove("five").unwrap();
map.insert("five".to_owned(), 5);
let second = map.remove("five").unwrap();
assert!(map
.reinsert_with(first, |_, stored| stored.is_none())
.created());
assert_eq!(*map.get("five").unwrap().val(), 5);
assert!(map
.reinsert_with(second, |_, stored| stored.is_none())
.failed()
.is_some());
}
#[test]
fn reinserts_update() {
let map = Map::new();
map.insert("five".to_owned(), 5);
let prev = map.remove("five").unwrap();
let prev = map
.reinsert_with(prev, |_, stored| stored.is_some())
.take_failed()
.unwrap();
map.insert("five".to_owned(), 5);
assert!(map
.reinsert_with(prev, |_, stored| stored.is_some())
.updated()
.is_some());
}
#[test]
fn inserts_and_removes() {
let map = Map::new();
assert!(map.remove("five").is_none());
assert!(map.remove("four").is_none());
map.insert("five".to_owned(), 5);
let removed = map.remove("five").unwrap();
assert_eq!(removed.key(), "five");
assert_eq!(*removed.val(), 5);
assert!(map.insert("four".to_owned(), 4).is_none());
map.insert("three".to_owned(), 3);
assert!(map.remove("two").is_none());
map.insert("two".to_owned(), 2);
let removed = map.remove("three").unwrap();
assert_eq!(removed.key(), "three");
assert_eq!(*removed.val(), 3);
let removed = map.remove("two").unwrap();
assert_eq!(removed.key(), "two");
assert_eq!(*removed.val(), 2);
let removed = map.remove("four").unwrap();
assert_eq!(removed.key(), "four");
assert_eq!(*removed.val(), 4);
}
#[test]
fn repeated_inserts() {
let map = Map::new();
assert!(map.insert("five".to_owned(), 5).is_none());
assert!(*map.insert("five".to_owned(), 5).unwrap().val() == 5);
}
#[test]
fn reinsert_from_other_map_fails() {
let other = Map::new();
other.insert(5, 3);
other.insert(0, 0);
let removed = other.remove(&5).unwrap();
let _active_read = other.get(&0).unwrap();
let map = Map::new();
map.reinsert(removed).failed().unwrap();
}
#[test]
fn iter_valid_items() {
let map = Map::new();
for i in 0 .. 10u128 {
for j in 0 .. 32 {
map.insert((i, j), i << j);
}
}
let mut result = HashMap::new();
for guard in &map {
let (k, v) = *guard;
let in_place = result.get(&(k, v)).map_or(0, |&x| x);
result.insert((k, v), in_place + 1);
}
for i in 0 .. 10 {
for j in 0 .. 32 {
let pair = ((i, j), i << j);
assert_eq!(*result.get(&pair).unwrap(), 1);
}
}
}
#[test]
fn optimize_space_preserves_entries() {
let mut map = Map::new();
for i in 0 .. 200u128 {
for j in 0 .. 128 {
map.insert((i, j), i << j);
}
}
for i in 0 .. 200 {
for j in 0 .. 16 {
map.remove(&(i, j));
}
}
map.optimize_space();
let mut result = HashMap::new();
for guard in &map {
let (k, v) = *guard;
let in_place = result.get(&(k, v)).map_or(0, |&x| x);
result.insert((k, v), in_place + 1);
}
for i in 0 .. 200 {
for j in 16 .. 128 {
let pair = ((i, j), i << j);
assert_eq!(*result.get(&pair).unwrap(), 1);
}
}
}
#[test]
fn iter_mut_and_into_iter() {
let mut map = Map::new();
for i in 0 .. 10u128 {
for j in 0 .. 32 {
map.insert((i, j), i << j);
}
}
let mut result = HashMap::new();
for (k, v) in &mut map {
let in_place = result.get(&(*k, *v)).map_or(0, |&x| x);
result.insert((*k, *v), in_place + 1);
*v += 1;
}
for i in 0 .. 10 {
for j in 0 .. 32 {
let pair = ((i, j), i << j);
assert_eq!(*result.get(&pair).unwrap(), 1);
}
}
result.clear();
for (k, v) in map {
let in_place = result.get(&(k, v)).map_or(0, |&x| x);
result.insert((k, v), in_place + 1);
}
for i in 0 .. 10 {
for j in 0 .. 32 {
let pair = ((i, j), (i << j) + 1);
assert_eq!(*result.get(&pair).unwrap(), 1);
}
}
}
#[test]
fn multithreaded() {
let map = Arc::new(Map::new());
let mut threads = Vec::new();
for i in 1i64 ..= 20 {
let map = map.clone();
threads.push(thread::spawn(move || {
let prev = map
.get(&format!("prefix{}suffix", i - 1))
.map_or(0, |guard| *guard.val());
map.insert(format!("prefix{}suffix", i), prev + i);
map.insert_with(
format!("prefix{}suffix", i + 1),
|_, _, stored| {
Preview::New(stored.map_or(0, |&(_, x)| x + i))
},
);
}));
}
for thread in threads {
thread.join().expect("thread failed");
}
for i in 1i64 ..= 20 {
let val = *map.get(&format!("prefix{}suffix", i)).unwrap().val();
assert!(val > 0);
}
}
}