use std::collections::{HashMap, VecDeque};
use std::hash::Hash;
use std::marker::PhantomData;
use std::ptr::NonNull;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::{Arc, Mutex, MutexGuard};
use crate::data_holder::{DataHolder, SharedDataContainerType, DATA_HOLDER_BLOCK_SIZE_INTERNAL};
use crate::data_reference::DataReference;
use crate::fixed_address_continuous_allocation::{FaVec, FaVecIndex};
type HashType<T, U> = HashMap<T, U>;
pub struct MbarcMap<T: Hash + Eq, U> {
data: SharedDataContainerType<U>,
data_refs: Arc<Mutex<HashType<T, DataReference<U>>>>,
}
impl<T: Hash + Eq, U> Default for MbarcMap<T, U> {
fn default() -> Self {
Self::new()
}
}
impl<T: Hash + Eq, U> MbarcMap<T, U> {
pub fn new() -> Self {
Self {
data: Arc::new(Mutex::new(FaVec::new())),
data_refs: Arc::new(Mutex::new(HashType::new())),
}
}
pub fn insert(&self, key: T, value: U) -> Option<DataReference<U>> {
let mut refs_lock = self.data_refs.lock().unwrap();
let mut data_lock = self.data.lock().unwrap();
let new_holder = DataHolder {
ref_count: AtomicUsize::new(1),
pending_removal: AtomicBool::new(false),
data: Mutex::new(value),
owner: self.data.clone(),
owning_key: FaVecIndex::from_absolute_index(0),
};
let new_key = data_lock.push(new_holder);
let inserted_item = data_lock.get_mut(&new_key).unwrap();
inserted_item.owning_key = new_key;
refs_lock.insert(
key,
DataReference {
ptr: NonNull::new(inserted_item as *mut DataHolder<U>).unwrap(),
phantom: PhantomData,
},
)
}
pub fn contains(&self, key: &T) -> bool {
self.data_refs.lock().unwrap().contains_key(key)
}
pub fn get(&self, key: &T) -> Option<DataReference<U>> {
self.data_refs.lock().unwrap().get(key).cloned()
}
pub fn remove(&self, key: &T) -> Option<DataReference<U>> {
match self.data_refs.lock().unwrap().remove(key) {
Some(value_ref) => {
value_ref.raw_data().set_deleted();
Some(value_ref)
}
None => None,
}
}
pub fn len(&self) -> usize {
self.data_refs.lock().unwrap().len()
}
pub fn is_empty(&self) -> bool {
self.data_refs.lock().unwrap().is_empty()
}
pub fn iter(
&self,
) -> crate::minimally_blocking_atomic_reference_counted_map::Iter<DataReference<U>> {
let ref_lock = self.data_refs.lock().unwrap();
let mut vals = VecDeque::with_capacity(ref_lock.len());
for value in ref_lock.values() {
vals.push_back(value.clone());
}
Iter { items: vals }
}
pub fn iter_copied_values_ordered(&self) -> Iter<DataReference<U>> {
let data_lock = self.data.lock().unwrap();
Iter {
items: data_lock.iter().map(|a| a.make_new_ref()).collect(),
}
}
pub fn iter_exclusive(&self) -> LockedContainer<'_, T, U> {
LockedContainer {
items: self.data_refs.lock().unwrap(),
}
}
pub fn iter_values_exclusive(&self) -> LockedValuesContainer<'_, U> {
LockedValuesContainer {
items: self.data.lock().unwrap(),
}
}
}
impl<T: Hash + Eq + Clone, U> MbarcMap<T, U> {
pub fn iter_cloned_keys(&self) -> Iter<(T, DataReference<U>)> {
let ref_lock = self.data_refs.lock().unwrap();
let mut vals = VecDeque::with_capacity(ref_lock.len());
for (key, value) in ref_lock.iter() {
vals.push_back((key.clone(), value.clone()));
}
Iter { items: vals }
}
}
impl<T: Hash + Eq + Copy, U> MbarcMap<T, U> {
pub fn iter_copied_keys(&self) -> Iter<(T, DataReference<U>)> {
let ref_lock = self.data_refs.lock().unwrap();
let mut vals = VecDeque::with_capacity(ref_lock.len());
for (key, value) in ref_lock.iter() {
vals.push_back((*key, value.clone()));
}
Iter { items: vals }
}
}
unsafe impl<T: Hash + Eq, U> Send for MbarcMap<T, U> {}
unsafe impl<T: Hash + Eq, U> Sync for MbarcMap<T, U> {}
impl<T: Hash + Eq, U> Drop for MbarcMap<T, U> {
fn drop(&mut self) {
let ref_lock = self.data_refs.lock().unwrap();
for value in ref_lock.values() {
value.raw_data().set_deleted();
}
}
}
impl<K, V, const N: usize> From<[(K, V); N]> for MbarcMap<K, V>
where
K: Eq + Hash,
{
fn from(arr: [(K, V); N]) -> Self {
let map = Self::new();
for (k, v) in arr {
map.insert(k, v);
}
map
}
}
pub struct Iter<U> {
items: VecDeque<U>,
}
impl<U> Iterator for Iter<U> {
type Item = U;
fn next(&mut self) -> Option<Self::Item> {
self.items.pop_front()
}
}
pub struct LockedContainer<'a, T, U> {
items: MutexGuard<'a, HashType<T, DataReference<U>>>,
}
impl<'a, T, U> LockedContainer<'a, T, U> {
pub fn iter(&self) -> impl Iterator<Item = (&T, &DataReference<U>)> {
self.items.iter()
}
}
pub struct LockedValuesContainer<'a, U> {
items: MutexGuard<'a, FaVec<DataHolder<U>, DATA_HOLDER_BLOCK_SIZE_INTERNAL>>,
}
impl<'a, U> LockedValuesContainer<'a, U> {
pub fn iter(&'a self) -> impl Iterator<Item = &'a Mutex<U>> {
self.items.iter().map(|value| &value.data)
}
}