use serde::{Deserialize, Deserializer, Serialize, Serializer};
use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::borrow::Borrow;
use std::cell::UnsafeCell;
use std::collections::HashMap;
use std::collections::hash_map::{IntoIter as MapIntoIter, Iter as MapIter, Keys};
use std::fmt::{Debug, Formatter};
use std::hash::{BuildHasherDefault, DefaultHasher, Hash};
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
pub use crate::guard_common::{EntryGuard, MutRefGuard, ReadGuard, RefGuard, WriteGuard};
pub type DefaultBuildHasher = BuildHasherDefault<DefaultHasher>;
pub struct SyncHashMap<K, V> {
dirty: UnsafeCell<HashMap<K, RwLock<V>, DefaultBuildHasher>>,
lock: RwLock<()>,
}
unsafe impl<K, V> Send for SyncHashMap<K, V> {}
unsafe impl<K, V> Sync for SyncHashMap<K, V> {}
impl<K, V> SyncHashMap<K, V>
where
K: Eq + Hash,
{
pub fn new_arc() -> Arc<Self> {
Arc::new(Self::new())
}
pub const fn new() -> Self {
Self {
dirty: UnsafeCell::new(HashMap::with_hasher(DefaultBuildHasher::new())),
lock: RwLock::new(()),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
dirty: UnsafeCell::new(HashMap::with_capacity_and_hasher(
capacity,
std::hash::BuildHasherDefault::default(),
)),
lock: RwLock::new(()),
}
}
pub fn with_map(map: HashMap<K, V>) -> Self {
let mut wrapped =
HashMap::with_capacity_and_hasher(map.len(), std::hash::BuildHasherDefault::default());
for (k, v) in map {
wrapped.insert(k, RwLock::new(v));
}
Self {
dirty: UnsafeCell::new(wrapped),
lock: RwLock::new(()),
}
}
#[inline(always)]
pub fn insert(&self, k: K, v: V) -> Option<V> {
let _lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
m.insert(k, RwLock::new(v)).map(|old| old.into_inner())
}
#[inline(always)]
pub fn insert_mut(&mut self, k: K, v: V) -> Option<V> {
let m = unsafe { &mut *self.dirty.get() };
m.insert(k, RwLock::new(v)).map(|old| old.into_inner())
}
#[inline(always)]
pub fn remove(&self, k: &K) -> Option<V> {
let _lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
m.remove(k).map(|v| v.into_inner())
}
#[inline(always)]
pub fn remove_mut(&mut self, k: &K) -> Option<V> {
let m = unsafe { &mut *self.dirty.get() };
m.remove(k).map(|v| v.into_inner())
}
#[inline(always)]
pub fn len(&self) -> usize {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
m.len()
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
m.is_empty()
}
#[inline(always)]
pub fn clear(&self) {
let _lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
m.clear();
}
#[inline(always)]
pub fn clear_mut(&mut self) {
let m = unsafe { &mut *self.dirty.get() };
m.clear();
}
#[inline(always)]
pub fn shrink_to_fit(&self) {
let _lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
m.shrink_to_fit();
}
#[inline(always)]
pub fn shrink_to_fit_mut(&mut self) {
let m = unsafe { &mut *self.dirty.get() };
m.shrink_to_fit();
}
pub fn from(map: HashMap<K, V>) -> Self {
Self::with_map(map)
}
#[inline]
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<RefGuard<'_, V>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let map_lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let value_lock_wrapper = m.get(k)?;
let value_ptr = unsafe {
let lock_ptr = value_lock_wrapper as *const RwLock<V> as *mut RwLock<V>;
&*(*lock_ptr).get_mut()
};
Some(RefGuard {
_lock: map_lock,
_value: value_ptr,
})
}
pub fn get_rlock<Q: ?Sized>(&self, k: &Q) -> Option<ReadGuard<'_, V>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let map_lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let value_lock_wrapper = m.get(k)?;
let value_lock = value_lock_wrapper.read();
Some(ReadGuard {
_lock: map_lock,
_value_lock: value_lock,
})
}
#[inline]
pub fn get_uncheck<Q: ?Sized>(&self, k: &Q) -> RefGuard<'_, V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let map_lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let value_lock_wrapper = m.get(k).expect("key not found");
let value_ptr = unsafe {
let lock_ptr = value_lock_wrapper as *const RwLock<V> as *mut RwLock<V>;
&*(*lock_ptr).get_mut()
};
RefGuard {
_lock: map_lock,
_value: value_ptr,
}
}
#[inline]
pub fn get_mut<Q: ?Sized>(&self, k: &Q) -> Option<MutRefGuard<'_, V>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let map_lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let value_lock_wrapper = m.get(k)?;
let value_ptr = unsafe {
let lock_ptr = value_lock_wrapper as *const RwLock<V> as *mut RwLock<V>;
&mut *(*lock_ptr).get_mut()
};
Some(MutRefGuard {
_lock: map_lock,
_value: value_ptr,
})
}
#[inline]
pub fn get_mut_lock<Q: ?Sized>(&self, k: &Q) -> Option<WriteGuard<'_, V>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let map_lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let value_lock_wrapper = m.get(k)?;
let value_lock = value_lock_wrapper.write();
Some(WriteGuard {
_lock: map_lock,
_value_lock: value_lock,
})
}
#[inline]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
m.contains_key(k)
}
pub fn iter_mut_lock(&self) -> IterLock<'_, K, V> {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
IterLock {
_lock,
inner: m.iter(),
}
}
pub fn iter_mut(&self) -> IterMut<'_, K, V> {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
IterMut {
_lock,
inner: m.iter(),
}
}
pub fn iter_rlock(&self) -> IterRLock<'_, K, V> {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
IterRLock {
_lock,
inner: m.iter(),
}
}
pub fn iter(&self) -> Iter<'_, K, V> {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
Iter {
_lock,
inner: m.iter(),
}
}
pub fn dirty_ref(&self) -> ReadGuardMap<'_, K, V> {
let _lock = self.lock.read();
let v = unsafe { &*self.dirty.get() };
ReadGuardMap { _lock, v }
}
pub unsafe fn dirty_ref_unsafe(&self) -> &HashMap<K, RwLock<V>, DefaultBuildHasher> {
unsafe { &*self.dirty.get() }
}
pub fn into_inner(self) -> HashMap<K, V> {
self.dirty
.into_inner()
.into_iter()
.map(|(k, v)| (k, v.into_inner()))
.collect()
}
#[inline]
pub fn keys(&self) -> KeysGuard<'_, K, V> {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
KeysGuard {
_lock,
inner: m.keys(),
}
}
#[inline]
pub fn values(&self) -> ValuesGuard<'_, K, V> {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
ValuesGuard {
_lock,
inner: m.values(),
}
}
#[inline]
pub fn values_mut(&self) -> ValuesMutGuard<'_, K, V> {
let _lock = self.lock.write();
let m = unsafe { &*self.dirty.get() };
ValuesMutGuard {
_lock,
inner: m.values(),
}
}
#[inline]
pub fn retain<F>(&self, mut f: F)
where
F: FnMut(&K, &mut V) -> bool,
{
let _lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
m.retain(|k, v| f(k, v.get_mut()));
}
#[inline]
pub fn capacity(&self) -> usize {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
m.capacity()
}
#[inline]
pub fn reserve(&self, additional: usize) {
let _lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
m.reserve(additional);
}
#[inline]
pub fn remove_entry(&self, k: &K) -> Option<(K, V)> {
let _lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
m.remove_entry(k).map(|(k, v)| (k, v.into_inner()))
}
#[inline]
pub fn get_or_insert(&self, k: K, default: V) -> EntryGuard<'_, V> {
let map_lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
let entry = m.entry(k).or_insert_with(|| RwLock::new(default));
let value_lock = entry.write();
EntryGuard {
_lock: map_lock,
_value_lock: value_lock,
}
}
#[inline]
pub fn get_or_insert_with<F>(&self, k: K, default: F) -> EntryGuard<'_, V>
where
F: FnOnce() -> V,
{
let map_lock = self.lock.write();
let m = unsafe { &mut *self.dirty.get() };
let entry = m.entry(k).or_insert_with(|| RwLock::new(default()));
let value_lock = entry.write();
EntryGuard {
_lock: map_lock,
_value_lock: value_lock,
}
}
#[inline]
pub fn get_clone<Q: ?Sized>(&self, k: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Hash + Eq,
V: Clone,
{
let _map_lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
m.get(k).map(|v| v.read().clone())
}
#[inline]
pub fn take(&self, k: &K) -> Option<V> {
self.remove(k)
}
}
pub struct ReadGuardMap<'a, K, V> {
_lock: RwLockReadGuard<'a, ()>,
v: &'a HashMap<K, RwLock<V>, DefaultBuildHasher>,
}
impl<'a, K, V> Deref for ReadGuardMap<'a, K, V> {
type Target = HashMap<K, RwLock<V>, DefaultBuildHasher>;
fn deref(&self) -> &Self::Target {
self.v
}
}
impl<'a, K, V> Debug for ReadGuardMap<'a, K, V>
where
K: Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut map = f.debug_map();
for (k, v) in self.v.iter() {
map.entry(k, &*v.read());
}
map.finish()
}
}
impl<'a, K, V> AsRef<HashMap<K, RwLock<V>, DefaultBuildHasher>> for ReadGuardMap<'a, K, V> {
fn as_ref(&self) -> &HashMap<K, RwLock<V>, DefaultBuildHasher> {
self.v
}
}
#[allow(dead_code)]
#[deprecated(note = "Use WriteGuard instead")]
pub type SyncMapRefMut<'a, V> = WriteGuard<'a, V>;
pub struct IterRLock<'a, K, V> {
_lock: RwLockReadGuard<'a, ()>,
inner: MapIter<'a, K, RwLock<V>>,
}
impl<'a, K, V> Iterator for IterRLock<'a, K, V> {
type Item = (&'a K, RwLockReadGuard<'a, V>);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(k, v)| (k, v.read()))
}
}
pub type IterMy<'a, K, V> = IterRLock<'a, K, V>;
pub struct IterLock<'a, K, V> {
_lock: RwLockReadGuard<'a, ()>,
inner: MapIter<'a, K, RwLock<V>>,
}
impl<'a, K, V> Iterator for IterLock<'a, K, V> {
type Item = (&'a K, RwLockWriteGuard<'a, V>);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(k, v)| (k, v.write()))
}
}
pub struct IterMut<'a, K, V> {
_lock: RwLockReadGuard<'a, ()>,
inner: MapIter<'a, K, RwLock<V>>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(k, v)| {
let value_ptr = unsafe {
let lock_ptr = v as *const RwLock<V> as *mut RwLock<V>;
&mut *(*lock_ptr).get_mut()
};
(k, value_ptr)
})
}
}
pub struct KeysGuard<'a, K, V> {
_lock: RwLockReadGuard<'a, ()>,
inner: Keys<'a, K, RwLock<V>>,
}
impl<'a, K, V> Deref for KeysGuard<'a, K, V> {
type Target = Keys<'a, K, RwLock<V>>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, K, V> DerefMut for KeysGuard<'a, K, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<'a, K, V> Iterator for KeysGuard<'a, K, V> {
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
pub struct ValuesGuard<'a, K, V> {
_lock: RwLockReadGuard<'a, ()>,
inner: std::collections::hash_map::Values<'a, K, RwLock<V>>,
}
impl<'a, K, V> Iterator for ValuesGuard<'a, K, V> {
type Item = RwLockReadGuard<'a, V>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|v| v.read())
}
}
pub struct ValuesMutGuard<'a, K, V> {
_lock: RwLockWriteGuard<'a, ()>,
inner: std::collections::hash_map::Values<'a, K, RwLock<V>>,
}
impl<'a, K, V> Iterator for ValuesMutGuard<'a, K, V> {
type Item = RwLockWriteGuard<'a, V>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|v| v.write())
}
}
pub struct Iter<'a, K, V> {
_lock: RwLockReadGuard<'a, ()>,
inner: MapIter<'a, K, RwLock<V>>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(k, v)| {
unsafe {
let lock_ptr = v as *const RwLock<V> as *mut RwLock<V>;
(k, &*(*lock_ptr).get_mut())
}
})
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
fn len(&self) -> usize {
self.inner.len()
}
}
impl<'a, K, V> IntoIterator for &'a SyncHashMap<K, V>
where
K: Eq + Hash,
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K, V> IntoIterator for &'a mut SyncHashMap<K, V>
where
K: Eq + Hash,
{
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<K, V> IntoIterator for SyncHashMap<K, V>
where
K: Eq + Hash,
{
type Item = (K, V);
type IntoIter = MapIntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
self.into_inner().into_iter()
}
}
impl<K, V> From<HashMap<K, V>> for SyncHashMap<K, V>
where
K: Eq + Hash,
{
fn from(map: HashMap<K, V>) -> Self {
Self::with_map(map)
}
}
impl<K, V> Serialize for SyncHashMap<K, V>
where
K: Eq + Hash + Serialize,
V: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeMap;
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let mut map = serializer.serialize_map(Some(m.len()))?;
for (k, v) in m.iter() {
map.serialize_entry(k, &*v.read())?;
}
map.end()
}
}
impl<'de, K, V> Deserialize<'de> for SyncHashMap<K, V>
where
K: Eq + Hash + Deserialize<'de>,
V: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let m = HashMap::deserialize(deserializer)?;
Ok(Self::with_map(m))
}
}
impl<K, V> Debug for SyncHashMap<K, V>
where
K: Eq + Hash + Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let mut map = f.debug_map();
for (k, v) in m.iter() {
map.entry(k, &*v.read());
}
map.finish()
}
}
impl<K, V> Clone for SyncHashMap<K, V>
where
K: Clone + Eq + Hash,
V: Clone,
{
fn clone(&self) -> Self {
let _lock = self.lock.read();
let m = unsafe { &*self.dirty.get() };
let cloned: HashMap<K, V> = m
.iter()
.map(|(k, v)| (k.clone(), v.read().clone()))
.collect();
SyncHashMap::with_map(cloned)
}
}
impl<K, V> Default for SyncHashMap<K, V>
where
K: Eq + Hash,
{
fn default() -> Self {
Self::new()
}
}
impl<K, V> PartialEq for SyncHashMap<K, V>
where
K: Eq + Hash,
V: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
let _lock_self = self.lock.read();
let _lock_other = other.lock.read();
let self_map = unsafe { &*self.dirty.get() };
let other_map = unsafe { &*other.dirty.get() };
if self_map.len() != other_map.len() {
return false;
}
for (k, v) in self_map.iter() {
match other_map.get(k) {
Some(other_v) => {
if *v.read() != *other_v.read() {
return false;
}
}
None => return false,
}
}
true
}
}
impl<K, V> Eq for SyncHashMap<K, V>
where
K: Eq + Hash,
V: Eq,
{
}
pub mod buckets {
use super::{MutRefGuard, RefGuard, SyncHashMap, WriteGuard};
use std::hash::{Hash, Hasher};
#[derive(Debug, Clone)]
pub struct SyncHashMapB<K, V>
where
K: Eq + Hash,
{
inner: Vec<SyncHashMap<K, V>>,
len: usize,
}
impl<K, V> SyncHashMapB<K, V>
where
K: Eq + Hash,
{
pub fn new(bucket_count: Option<usize>) -> Self {
let count = bucket_count.unwrap_or(10);
let mut arr = Vec::with_capacity(count);
for _ in 0..count {
arr.push(SyncHashMap::new());
}
Self {
inner: arr,
len: count,
}
}
fn key_to_bucket_index(&self, k: &K) -> usize {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
k.hash(&mut hasher);
let hash = hasher.finish();
(hash % self.len as u64) as usize
}
#[inline]
pub fn insert(&self, k: K, v: V) -> Option<V> {
let index = self.key_to_bucket_index(&k);
self.inner[index].insert(k, v)
}
#[inline]
pub fn insert_mut(&mut self, k: K, v: V) -> Option<V> {
let index = self.key_to_bucket_index(&k);
self.inner[index].insert_mut(k, v)
}
#[inline]
pub fn remove(&self, k: &K) -> Option<V> {
let index = self.key_to_bucket_index(k);
self.inner[index].remove(k)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.iter().all(|bucket| bucket.is_empty())
}
#[inline]
pub fn len(&self) -> usize {
self.inner.iter().map(|bucket| bucket.len()).sum()
}
#[inline]
pub fn clear(&self) {
self.inner.iter().for_each(|bucket| bucket.clear());
}
#[inline]
pub fn get(&self, k: &K) -> Option<RefGuard<'_, V>> {
let index = self.key_to_bucket_index(k);
self.inner[index].get(k)
}
#[inline]
pub fn get_mut(&self, k: &K) -> Option<MutRefGuard<'_, V>> {
let index = self.key_to_bucket_index(k);
self.inner[index].get_mut(k)
}
#[inline]
pub fn get_mut_lock(&self, k: &K) -> Option<WriteGuard<'_, V>> {
let index = self.key_to_bucket_index(k);
self.inner[index].get_mut_lock(k)
}
#[inline]
pub fn bucket_count(&self) -> usize {
self.len
}
#[inline]
pub fn keys(&self) -> impl Iterator<Item = &K> {
self.inner.iter().flat_map(|bucket| bucket.keys())
}
#[inline]
pub fn get_clone(&self, k: &K) -> Option<V>
where
V: Clone,
{
let index = self.key_to_bucket_index(k);
self.inner[index].get_clone(k)
}
}
impl<K, V> Default for SyncHashMapB<K, V>
where
K: Eq + Hash,
{
fn default() -> Self {
Self::new(None)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
use std::sync::Arc;
use std::thread;
#[test]
fn test_sync_hash_map_new() {
let map: SyncHashMap<i32, String> = SyncHashMap::new();
assert_eq!(map.len(), 0);
assert!(map.is_empty());
}
#[test]
fn test_sync_hash_map_with_capacity() {
let map = SyncHashMap::<i32, String>::with_capacity(100);
assert!(map.capacity() >= 100);
}
#[test]
fn test_sync_hash_map_with_map() {
let mut original = HashMap::new();
original.insert(1, "one".to_string());
original.insert(2, "two".to_string());
let map = SyncHashMap::with_map(original);
assert_eq!(map.len(), 2);
assert_eq!(*map.get(&1).unwrap(), "one".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_insert_and_get() {
let map = SyncHashMap::new();
assert_eq!(map.insert(1, "one".to_string()), None);
assert_eq!(map.insert(2, "two".to_string()), None);
assert_eq!(map.len(), 2);
assert_eq!(*map.get(&1).unwrap(), "one".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
assert!(map.get(&3).is_none());
}
#[test]
fn test_sync_hash_map_insert_replace() {
let map = SyncHashMap::new();
assert_eq!(map.insert(1, "one".to_string()), None);
assert_eq!(
map.insert(1, "updated".to_string()),
Some("one".to_string())
);
assert_eq!(*map.get(&1).unwrap(), "updated".to_string());
}
#[test]
fn test_sync_hash_map_remove() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
assert_eq!(map.remove(&1), Some("one".to_string()));
assert_eq!(map.remove(&1), None);
assert_eq!(map.len(), 1);
assert!(map.get(&1).is_none());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_contains_key() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
assert!(map.contains_key(&1));
assert!(!map.contains_key(&2));
}
#[test]
fn test_sync_hash_map_clear() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
assert_eq!(map.len(), 2);
map.clear();
assert_eq!(map.len(), 0);
assert!(map.is_empty());
}
#[test]
fn test_sync_hash_map_capacity_operations() {
let map = SyncHashMap::new();
assert_eq!(map.capacity(), 0);
map.reserve(100);
assert!(map.capacity() >= 100);
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
let old_capacity = map.capacity();
map.shrink_to_fit();
assert!(map.capacity() <= old_capacity);
}
#[test]
fn test_sync_hash_map_retain() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
map.insert(3, "three".to_string());
map.retain(|&k, _| k % 2 == 1);
assert_eq!(map.len(), 2);
assert!(map.contains_key(&1));
assert!(!map.contains_key(&2));
assert!(map.contains_key(&3));
}
#[test]
fn test_sync_hash_map_get_or_insert() {
let map = SyncHashMap::new();
{
let value = map.get_or_insert(1, "default".to_string());
assert_eq!(*value, "default");
}
assert_eq!(map.len(), 1);
{
let value = map.get_or_insert(1, "new_default".to_string());
assert_eq!(*value, "default");
}
assert_eq!(map.len(), 1);
}
#[test]
fn test_sync_hash_map_get_or_insert_with() {
let map = SyncHashMap::new();
{
let value = map.get_or_insert_with(1, || "computed".to_string());
assert_eq!(*value, "computed");
}
assert_eq!(map.len(), 1);
{
let value = map.get_or_insert_with(1, || "new_computed".to_string());
assert_eq!(*value, "computed");
}
}
#[test]
fn test_sync_hash_map_remove_entry() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
let removed = map.remove_entry(&1);
assert_eq!(removed, Some((1, "one".to_string())));
assert_eq!(map.len(), 1);
assert!(!map.contains_key(&1));
}
#[test]
fn test_sync_hash_map_iterators() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
map.insert(3, "three".to_string());
let keys: Vec<_> = map.keys().collect();
assert!(keys.contains(&&1));
assert!(keys.contains(&&2));
assert!(keys.contains(&&3));
assert_eq!(map.get_clone(&1), Some("one".to_string()));
assert_eq!(map.get_clone(&2), Some("two".to_string()));
assert_eq!(map.get_clone(&3), Some("three".to_string()));
let mut count = 0;
for (k, v) in map.iter() {
count += 1;
assert!(map.contains_key(k));
assert_eq!(*map.get(k).unwrap(), *v);
}
let mut count_rlock = 0;
for (k, v) in map.iter_rlock() {
count_rlock += 1;
assert!(map.contains_key(k));
assert_eq!(*map.get(k).unwrap(), *v);
for (k, v) in map.iter_rlock() {
count_rlock += 1;
assert!(map.contains_key(k));
assert_eq!(*map.get(k).unwrap(), *v);
}
}
assert_eq!(count_rlock, 12);
assert_eq!(count, 3);
}
#[test]
fn test_sync_hash_map_iter_mut() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
for (k, v) in map.iter_mut() {
if *k == 1 {
*v = "modified".to_string();
}
}
assert_eq!(*map.get(&1).unwrap(), "modified".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
for (k, mut v) in map.iter_mut_lock() {
if *k == 1 {
*v = "modified2".to_string();
}
if *k == 2 {
*v = "modified3".to_string();
}
}
assert_eq!(*map.get(&1).unwrap(), "modified2".to_string());
assert_eq!(*map.get(&2).unwrap(), "modified3".to_string());
}
#[test]
fn test_sync_hash_map_values_mut() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
for mut v in map.values_mut() {
if *v == "one" {
*v = "modified".to_string();
}
}
assert_eq!(*map.get(&1).unwrap(), "modified".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_get_clone() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
assert_eq!(map.get_clone(&1), Some("one".to_string()));
assert_eq!(map.get_clone(&2), None);
}
#[test]
fn test_sync_hash_map_clone() {
let map1 = SyncHashMap::new();
map1.insert(1, "one".to_string());
map1.insert(2, "two".to_string());
let map2 = map1.clone();
assert_eq!(map1.len(), map2.len());
assert_eq!(*map1.get(&1).unwrap(), *map2.get(&1).unwrap());
assert_eq!(*map1.get(&2).unwrap(), *map2.get(&2).unwrap());
map1.insert(3, "three".to_string());
assert!(!map2.contains_key(&3));
}
#[test]
fn test_sync_hash_map_partial_eq() {
let map1 = SyncHashMap::new();
map1.insert(1, "one".to_string());
map1.insert(2, "two".to_string());
let map2 = SyncHashMap::new();
map2.insert(1, "one".to_string());
map2.insert(2, "two".to_string());
let map3 = SyncHashMap::new();
map3.insert(1, "different".to_string());
assert_eq!(map1, map2);
assert_ne!(map1, map3);
}
#[test]
fn test_sync_hash_map_debug() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
let debug_str = format!("{:?}", map);
assert!(debug_str.contains("1"));
assert!(debug_str.contains("one"));
}
#[test]
fn test_sync_hash_map_serialization() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
let serialized = serde_json::to_string(&map).unwrap();
assert!(serialized.contains("1"));
assert!(serialized.contains("one"));
assert!(serialized.contains("2"));
assert!(serialized.contains("two"));
let deserialized: SyncHashMap<i32, String> = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized.len(), 2);
assert_eq!(*deserialized.get(&1).unwrap(), "one".to_string());
assert_eq!(*deserialized.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_from_hashmap() {
let mut original = HashMap::new();
original.insert(1, "one".to_string());
original.insert(2, "two".to_string());
let map = SyncHashMap::from(original);
assert_eq!(map.len(), 2);
assert_eq!(*map.get(&1).unwrap(), "one".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_into_iterator() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
let mut count = 0;
for (k, v) in &map {
count += 1;
assert!(map.contains_key(k));
assert_eq!(*map.get(k).unwrap(), *v);
}
assert_eq!(count, 2);
let owned_pairs: Vec<_> = map.into_iter().collect();
assert_eq!(owned_pairs.len(), 2);
}
#[test]
fn test_sync_hash_map_default() {
let map: SyncHashMap<i32, String> = Default::default();
assert_eq!(map.len(), 0);
assert!(map.is_empty());
}
#[test]
fn test_sync_hash_map_arc() {
let map = SyncHashMap::new_arc();
map.insert(1, "one".to_string());
assert_eq!(*map.get(&1).unwrap(), "one".to_string());
let map2 = Arc::clone(&map);
map2.insert(2, "two".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_get_mut() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
{
let mut value = map.get_mut(&1).unwrap();
*value = "modified".to_string();
}
assert_eq!(*map.get(&1).unwrap(), "modified".to_string());
}
#[test]
fn test_sync_hash_map_concurrent_access() {
let map = Arc::new(SyncHashMap::new());
let handles: Vec<_> = (0..10)
.map(|i| {
let map = Arc::clone(&map);
thread::spawn(move || {
map.insert(i, format!("value_{}", i));
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
assert_eq!(map.len(), 10);
for i in 0..10 {
assert_eq!(*map.get(&i).unwrap(), format!("value_{}", i));
}
let map_read = Arc::clone(&map);
let handles: Vec<_> = (0..10)
.map(|i| {
let map = Arc::clone(&map_read);
thread::spawn(move || {
let value = map.get(&i);
assert_eq!(*value.unwrap(), format!("value_{}", i));
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn test_sync_hash_map_dirty_ref() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
let dirty = map.dirty_ref();
assert_eq!(dirty.len(), 1);
assert_eq!(*dirty.get(&1).unwrap().read(), "one".to_string());
}
#[test]
fn test_sync_hash_map_into_inner() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
let inner = map.into_inner();
assert_eq!(inner.len(), 2);
assert_eq!(inner.get(&1), Some(&"one".to_string()));
assert_eq!(inner.get(&2), Some(&"two".to_string()));
}
#[test]
fn test_sync_hash_map_guard_debug() {
let map = SyncHashMap::new();
map.insert(1, "test".to_string());
let guard = map.get(&1).unwrap();
let debug_str = format!("{:?}", guard);
assert!(debug_str.contains("test"));
}
#[test]
fn test_sync_hash_map_guard_partial_eq() {
let map = SyncHashMap::new();
map.insert(1, "value".to_string());
let guard1 = map.get(&1).unwrap();
let guard2 = map.get(&1).unwrap();
assert_eq!(guard1, guard2);
}
mod buckets_tests {
use super::*;
#[test]
fn test_sync_hash_map_buckets_new() {
let map = buckets::SyncHashMapB::<i32, String>::new(None);
assert_eq!(map.len(), 0);
assert!(map.is_empty());
assert_eq!(map.bucket_count(), 10); }
#[test]
fn test_sync_hash_map_buckets_with_custom_size() {
let map = buckets::SyncHashMapB::<i32, String>::new(Some(5));
assert_eq!(map.bucket_count(), 5);
}
#[test]
fn test_sync_hash_map_buckets_insert_and_get() {
let map = buckets::SyncHashMapB::new(Some(3));
assert_eq!(map.insert(1, "one".to_string()), None);
assert_eq!(map.insert(2, "two".to_string()), None);
assert_eq!(map.len(), 2);
assert_eq!(*map.get(&1).unwrap(), "one".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
assert!(map.get(&3).is_none());
}
#[test]
fn test_sync_hash_map_buckets_remove() {
let map = buckets::SyncHashMapB::new(Some(3));
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
assert_eq!(map.remove(&1), Some("one".to_string()));
assert_eq!(map.len(), 1);
assert!(map.get(&1).is_none());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_buckets_clear() {
let map = buckets::SyncHashMapB::new(Some(3));
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
assert_eq!(map.len(), 2);
map.clear();
assert_eq!(map.len(), 0);
assert!(map.is_empty());
}
#[test]
fn test_sync_hash_map_buckets_iterators() {
let map = buckets::SyncHashMapB::new(Some(3));
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
map.insert(3, "three".to_string());
let keys: Vec<_> = map.keys().collect();
assert!(keys.contains(&&1));
assert!(keys.contains(&&2));
assert!(keys.contains(&&3));
assert_eq!(map.get_clone(&1), Some("one".to_string()));
assert_eq!(map.get_clone(&2), Some("two".to_string()));
assert_eq!(map.get_clone(&3), Some("three".to_string()));
{
let mut v = map.get_mut(&1).unwrap();
*v = "modified".to_string();
}
assert_eq!(*map.get(&1).unwrap(), "modified".to_string());
}
#[test]
fn test_sync_hash_map_buckets_default() {
let map: buckets::SyncHashMapB<i32, String> = Default::default();
assert_eq!(map.len(), 0);
assert!(map.is_empty());
assert_eq!(map.bucket_count(), 10);
}
#[test]
fn test_sync_hash_map_buckets_debug() {
let map = buckets::SyncHashMapB::new(Some(2));
map.insert(1, "one".to_string());
let debug_str = format!("{:?}", map);
assert!(debug_str.contains("1"));
assert!(debug_str.contains("one"));
}
}
#[test]
fn test_sync_hash_map_comprehensive() {
let map = SyncHashMap::new();
map.insert("key1", 42);
map.insert("key2", 24);
assert_eq!(map.len(), 2);
assert!(!map.is_empty());
*map.get_mut("key1").unwrap() = 100;
assert_eq!(*map.get(&"key1").unwrap(), 100);
map.insert("key3", 50);
map.retain(|_, v| *v > 30);
assert_eq!(map.len(), 2);
assert_eq!(*map.get(&"key1").unwrap(), 100);
assert!(map.get(&"key2").is_none());
assert_eq!(*map.get(&"key3").unwrap(), 50);
let map2 = map.clone();
assert_eq!(map, map2);
let mut sum = 0;
for (_, v) in map.iter() {
sum += *v;
}
assert_eq!(sum, 150);
map.clear();
assert_eq!(map.len(), 0);
assert!(map.is_empty());
}
#[test]
fn test_sync_hash_map_iter_nlock() {
let map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
map.insert(3, "three".to_string());
let mut count = 0;
for (k, v) in map.iter() {
count += 1;
match *k {
1 => assert_eq!(v, "one"),
2 => assert_eq!(v, "two"),
3 => assert_eq!(v, "three"),
_ => panic!("unexpected key"),
}
}
assert_eq!(count, 3);
let iter = map.iter();
assert_eq!(iter.len(), 3);
}
#[test]
fn test_sync_hash_map_into_iter_mut() {
let mut map = SyncHashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
for (k, mut v) in &mut map {
if *k == 1 {
*v = "modified".to_string();
}
}
assert_eq!(*map.get(&1).unwrap(), "modified".to_string());
assert_eq!(*map.get(&2).unwrap(), "two".to_string());
}
#[test]
fn test_sync_hash_map_into_iter_ref() {
let map = SyncHashMap::new();
map.insert(1, 10);
map.insert(2, 20);
map.insert(3, 30);
let mut sum = 0;
for (_, v) in &map {
sum += *v;
}
assert_eq!(sum, 60);
assert_eq!(map.len(), 3);
}
#[test]
fn test_sync_hash_map_iter_nlock_empty() {
let map: SyncHashMap<i32, String> = SyncHashMap::new();
let mut count = 0;
for _ in map.iter() {
count += 1;
}
assert_eq!(count, 0);
let iter = map.iter();
assert_eq!(iter.len(), 0);
}
}