#![allow(clippy::implicit_hasher)]
#[cfg(feature = "asynch")]
pub mod asynch;
#[cfg(feature = "serde")]
use serde::{
de::{Deserialize, Deserializer},
ser::{Serialize, SerializeMap, Serializer},
};
#[cfg(feature = "serde")]
use crate::utils::MapCollector;
#[cfg(all(feature = "arcache", feature = "arcache-is-hashmap"))]
use crate::internals::hashmap::cursor::Datum;
use crate::internals::lincowcell::{LinCowCell, LinCowCellReadTxn, LinCowCellWriteTxn};
include!("impl.rs");
impl<K: Hash + Eq + Clone + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static>
HashMap<K, V>
{
pub fn new() -> Self {
HashMap {
inner: LinCowCell::new(unsafe { SuperBlock::new() }),
}
}
pub fn read(&self) -> HashMapReadTxn<'_, K, V> {
let inner = self.inner.read();
HashMapReadTxn { inner }
}
pub fn write(&self) -> HashMapWriteTxn<'_, K, V> {
let inner = self.inner.write();
HashMapWriteTxn { inner }
}
pub fn try_write(&self) -> Option<HashMapWriteTxn<'_, K, V>> {
self.inner
.try_write()
.map(|inner| HashMapWriteTxn { inner })
}
}
impl<K: Hash + Eq + Clone + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static>
HashMapWriteTxn<'_, K, V>
{
#[cfg(all(feature = "arcache", feature = "arcache-is-hashmap"))]
pub(crate) fn get_txid(&self) -> u64 {
self.inner.as_ref().get_txid()
}
#[cfg(all(feature = "arcache", feature = "arcache-is-hashmap"))]
pub(crate) fn prehash<Q>(&self, k: &Q) -> u64
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.inner.as_ref().hash_key(k)
}
#[cfg(all(feature = "arcache", feature = "arcache-is-hashmap"))]
pub(crate) unsafe fn get_slot_mut(&mut self, k_hash: u64) -> Option<&mut [Datum<K, V>]> {
self.inner.as_mut().get_slot_mut_ref(k_hash)
}
pub fn commit(self) {
self.inner.commit();
}
}
impl<K: Hash + Eq + Clone + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static>
HashMapReadTxn<'_, K, V>
{
#[cfg(all(feature = "arcache", feature = "arcache-is-hashmap"))]
pub(crate) fn get_txid(&self) -> u64 {
self.inner.as_ref().get_txid()
}
#[cfg(all(feature = "arcache", feature = "arcache-is-hashmap"))]
pub(crate) fn prehash<Q>(&self, k: &Q) -> u64
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
self.inner.as_ref().hash_key(k)
}
}
#[cfg(feature = "serde")]
impl<K, V> Serialize for HashMapReadTxn<'_, K, V>
where
K: Serialize + Hash + Eq + Clone + Debug + Sync + Send + 'static,
V: Serialize + Clone + Sync + Send + 'static,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(Some(self.len()))?;
for (key, val) in self.iter() {
state.serialize_entry(key, val)?;
}
state.end()
}
}
#[cfg(feature = "serde")]
impl<K, V> Serialize for HashMap<K, V>
where
K: Serialize + Hash + Eq + Clone + Debug + Sync + Send + 'static,
V: Serialize + Clone + Sync + Send + 'static,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.read().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, K, V> Deserialize<'de> for HashMap<K, V>
where
K: Deserialize<'de> + Hash + Eq + Clone + Debug + Sync + Send + 'static,
V: Deserialize<'de> + Clone + Sync + Send + 'static,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(MapCollector::new())
}
}
#[cfg(test)]
mod tests {
use super::HashMap;
#[test]
fn test_hashmap_basic_write() {
let hmap: HashMap<usize, usize> = HashMap::new();
let mut hmap_write = hmap.write();
hmap_write.insert(10, 10);
hmap_write.extend(vec![(15, 15)]);
assert!(hmap_write.contains_key(&10));
assert!(hmap_write.contains_key(&15));
assert!(!hmap_write.contains_key(&20));
assert!(hmap_write.get(&10) == Some(&10));
{
let v = hmap_write.get_mut(&10).unwrap();
*v = 11;
}
assert!(hmap_write.get(&10) == Some(&11));
assert!(hmap_write.remove(&10).is_some());
assert!(!hmap_write.contains_key(&10));
assert!(hmap_write.contains_key(&15));
assert!(hmap_write.remove(&30).is_none());
assert!(!hmap_write.is_empty());
assert_eq!(hmap_write.keys().count(), 1);
hmap_write.clear();
assert!(!hmap_write.contains_key(&10));
assert!(!hmap_write.contains_key(&15));
hmap_write.commit();
}
#[test]
fn test_hashmap_basic_read_write() {
let hmap: HashMap<usize, usize> = HashMap::new();
let mut hmap_w1 = hmap.write();
hmap_w1.insert(10, 10);
hmap_w1.insert(15, 15);
hmap_w1.commit();
let hmap_r1 = hmap.read();
assert!(hmap_r1.contains_key(&10));
assert!(hmap_r1.contains_key(&15));
assert!(!hmap_r1.contains_key(&20));
let mut hmap_w2 = hmap.write();
hmap_w2.insert(20, 20);
assert!(!hmap_w2.is_empty());
assert_eq!(hmap_w2.keys().count(), 3);
assert_eq!(hmap_w2.len(), 3);
hmap_w2.commit();
assert!(hmap_r1.contains_key(&10));
assert!(hmap_r1.contains_key(&15));
assert!(!hmap_r1.contains_key(&20));
let hmap_r2 = hmap.read();
assert!(hmap_r2.contains_key(&10));
assert!(hmap_r2.contains_key(&15));
assert!(hmap_r2.contains_key(&20));
assert!(!hmap_r2.is_empty());
assert_eq!(hmap_r2.len(), 3);
assert_eq!(hmap_r2.keys().count(), 3);
}
#[test]
fn test_hashmap_basic_read_snapshot() {
let hmap: HashMap<usize, usize> = HashMap::default();
let mut hmap_w1 = hmap.write();
hmap_w1.insert(10, 10);
hmap_w1.insert(15, 15);
let snap = hmap_w1.to_snapshot();
assert!(snap.contains_key(&10));
assert!(snap.contains_key(&15));
assert!(!snap.contains_key(&20));
hmap_w1.commit();
let hmap_read = hmap.read();
let snap = hmap_read.to_snapshot();
assert!(snap.contains_key(&10));
assert!(snap.contains_key(&15));
assert!(!snap.contains_key(&20));
assert_eq!(snap.len(), 2);
assert!(!snap.is_empty());
assert!(snap.iter().any(|(_k, v)| *v == 10));
assert_eq!(snap.values().count(), 2);
assert_eq!(snap.keys().count(), 2);
}
#[test]
fn test_hashmap_basic_iter() {
let hmap: HashMap<usize, usize> = HashMap::new();
let mut hmap_w1 = hmap.write();
assert!(hmap_w1.iter().count() == 0);
hmap_w1.insert(10, 10);
hmap_w1.insert(15, 15);
assert!(hmap_w1.iter().count() == 2);
let hmap_r1 = hmap.read();
assert!(hmap_r1.iter().count() == 0);
}
#[test]
fn test_hashmap_from_iter() {
let hmap: HashMap<usize, usize> = vec![(10, 10), (15, 15), (20, 20)].into_iter().collect();
let hmap_r2 = hmap.read();
assert!(hmap_r2.contains_key(&10));
assert!(hmap_r2.contains_key(&15));
assert!(hmap_r2.contains_key(&20));
}
#[cfg(feature = "serde")]
#[test]
fn test_hashmap_serialize_deserialize() {
let hmap: HashMap<usize, usize> = vec![(10, 11), (15, 16), (20, 21)].into_iter().collect();
let value = serde_json::to_value(&hmap).unwrap();
assert_eq!(value, serde_json::json!({ "10": 11, "15": 16, "20": 21 }));
let hmap: HashMap<usize, usize> = serde_json::from_value(value).unwrap();
let mut vec: Vec<(usize, usize)> = hmap.read().iter().map(|(k, v)| (*k, *v)).collect();
vec.sort_unstable();
assert_eq!(vec, [(10, 11), (15, 16), (20, 21)]);
}
#[test]
fn test_hashmap_keys() {
let hmap: HashMap<usize, usize> = vec![(10, 10), (15, 15), (20, 20)].into_iter().collect();
let hmap_read = hmap.read();
assert!(hmap_read.keys().any(|&x| x == 10));
let hmap_write = hmap.write();
assert!(hmap_write.keys().any(|&x| x == 10));
}
#[test]
fn test_hashmap_values() {
let hmap: HashMap<usize, usize> = vec![(10, 11), (15, 15), (20, 20)].into_iter().collect();
let hmap_read = hmap.read();
assert!(hmap_read.values().any(|&x| x == 11));
let hmap_write = hmap.write();
assert!(hmap_write.values().any(|&x| x == 11));
}
#[test]
fn test_write_snapshot_bits() {
let hmap: HashMap<usize, usize> = vec![(10, 11), (15, 15), (20, 20)].into_iter().collect();
let hmap_write = hmap.write();
let hmap_write_snapshot = hmap_write.to_snapshot();
assert!(!hmap_write_snapshot.is_empty());
assert_eq!(hmap_write_snapshot.len(), 3);
assert!(hmap_write_snapshot.contains_key(&10));
assert!(hmap_write_snapshot.values().any(|&x| x == 11));
assert!(hmap_write_snapshot.values().all(|&x| x != 10));
assert!(hmap_write_snapshot.keys().any(|&x| x == 10));
assert!(hmap_write_snapshot.keys().all(|&x| x != 11));
assert!(hmap_write_snapshot.keys().any(|&x| x == 10));
assert!(hmap_write_snapshot.iter().count() == 3);
}
}