use hashbrown::HashMap;
use crate::parking_lot::RwLock;
use crate::std::hash::Hash;
use crate::std::hash::Hasher;
use crate::std::ops::{Deref, DerefMut};
use crate::std::vec::Vec;
const NCB: u64 = 8;
const NCM: usize = 1 << NCB;
#[derive(Default)]
pub struct DHashMap<K, V>
where
K: Hash + Eq,
{
submaps: Vec<RwLock<HashMap<K, V>>>,
hash_nonce: u64,
}
impl<'a, K: 'a, V: 'a> DHashMap<K, V>
where
K: Hash + Eq,
{
#[cfg(feature = "std")]
#[cfg_attr(feature = "std", inline(always))]
pub fn new() -> Self {
if !check_opt(NCB, NCM) {
panic!("dhashmap params illegal");
}
Self {
submaps: (0..NCM).map(|_| RwLock::new(HashMap::new())).collect(),
hash_nonce: rand::random(),
}
}
pub fn with_nonce(hash_nonce: u64) -> Self {
if !check_opt(NCB, NCM) {
panic!("dhashmap params illegal");
}
Self {
submaps: (0..NCM).map(|_| RwLock::new(HashMap::new())).collect(),
hash_nonce,
}
}
#[inline(always)]
pub fn insert(&self, key: K, value: V) {
let mapi = self.determine_map(&key);
let mut submap = unsafe { self.submaps.get_unchecked(mapi).write() };
submap.insert(key, value);
}
#[inline(always)]
pub fn contains_key(&self, key: &K) -> bool {
let mapi = self.determine_map(&key);
let submap = unsafe { self.submaps.get_unchecked(mapi).read() };
submap.contains_key(&key)
}
#[inline(always)]
pub fn get(&'a self, key: &'a K) -> Option<DHashMapRef<'a, K, V>> {
let mapi = self.determine_map(&key);
let submap = unsafe { self.submaps.get_unchecked(mapi).read() };
if submap.contains_key(&key) {
Some(DHashMapRef { lock: submap, key })
} else {
None
}
}
#[inline(always)]
pub fn get_mut(&'a self, key: &'a K) -> Option<DHashMapRefMut<'a, K, V>> {
let mapi = self.determine_map(&key);
let submap = unsafe { self.submaps.get_unchecked(mapi).write() };
if submap.contains_key(&key) {
Some(DHashMapRefMut { lock: submap, key })
} else {
None
}
}
#[inline(always)]
pub fn remove(&self, key: &K) -> Option<(K, V)> {
let mapi = self.determine_map(&key);
let mut submap = unsafe { self.submaps.get_unchecked(mapi).write() };
submap.remove_entry(key)
}
#[inline(always)]
pub fn retain<F: Clone + FnMut(&K, &mut V) -> bool>(&self, f: F) {
self.submaps.iter().for_each(|locked| {
let mut submap = locked.write();
submap.retain(f.clone());
});
}
#[inline(always)]
pub fn clear(&self) {
self.submaps.iter().for_each(|locked| {
let mut submap = locked.write();
submap.clear();
});
}
#[inline(always)]
pub fn tables_read(
&self,
) -> impl Iterator<Item = SMRInterface<K, V>> {
self.submaps.iter().map(|t| SMRInterface::new(t.read()))
}
#[inline(always)]
pub fn tables_write(
&self,
) -> impl Iterator<Item = SMRWInterface<K, V>> {
self.submaps.iter().map(|t| SMRWInterface::new(t.write()))
}
#[inline(always)]
pub fn determine_map(&self, key: &K) -> usize {
let mut hash_state = fxhash::FxHasher64::default();
hash_state.write_u64(self.hash_nonce);
key.hash(&mut hash_state);
let hash = hash_state.finish();
let shift = 64 - NCB;
(hash >> shift) as usize
}
}
#[inline(always)]
fn check_opt(ncb: u64, ncm: usize) -> bool {
2_u64.pow(ncb as u32) == ncm as u64
}
pub struct SMRInterface<'a, K, V>
where
K: Hash + Eq,
{
inner: crate::parking_lot::RwLockReadGuard<'a, HashMap<K, V>>,
}
impl<'a, K: 'a, V: 'a> SMRInterface<'a, K, V>
where
K: Hash + Eq,
{
fn new(inner: crate::parking_lot::RwLockReadGuard<'a, HashMap<K, V>>) -> Self {
Self {
inner,
}
}
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.inner.iter()
}
}
pub struct SMRWInterface<'a, K, V>
where
K: Hash + Eq,
{
inner: crate::parking_lot::RwLockWriteGuard<'a, HashMap<K, V>>,
}
impl<'a, K: 'a, V: 'a> SMRWInterface<'a, K, V>
where
K: Hash + Eq,
{
fn new(inner: crate::parking_lot::RwLockWriteGuard<'a, HashMap<K, V>>) -> Self {
Self {
inner,
}
}
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.inner.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
self.inner.iter_mut()
}
}
pub struct DHashMapRef<'a, K, V>
where
K: Hash + Eq,
{
pub lock: crate::parking_lot::RwLockReadGuard<'a, HashMap<K, V>>,
pub key: &'a K,
}
impl<'a, K, V> Deref for DHashMapRef<'a, K, V>
where
K: Hash + Eq,
{
type Target = V;
#[inline(always)]
fn deref(&self) -> &V {
self.lock.get(self.key).unwrap()
}
}
pub struct DHashMapRefMut<'a, K, V>
where
K: Hash + Eq,
{
pub lock: crate::parking_lot::RwLockWriteGuard<'a, HashMap<K, V>>,
pub key: &'a K,
}
impl<'a, K, V> Deref for DHashMapRefMut<'a, K, V>
where
K: Hash + Eq,
{
type Target = V;
#[inline(always)]
fn deref(&self) -> &V {
self.lock.get(self.key).unwrap()
}
}
impl<'a, K, V> DerefMut for DHashMapRefMut<'a, K, V>
where
K: Hash + Eq,
{
#[inline(always)]
fn deref_mut(&mut self) -> &mut V {
self.lock.get_mut(self.key).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn insert_then_assert_64() {
let map = DHashMap::new();
for i in 0..64_i32 {
map.insert(i, i * 2);
}
for i in 0..64_i32 {
assert_eq!(i * 2, *map.get(&i).unwrap());
}
}
}