use crate::core::RUMResult;
use crate::net::tcp::{AsyncOwnedRwLockReadGuard, AsyncOwnedRwLockWriteGuard};
use crate::threading::thread_primitives::SafeLock;
use crate::threading::threading_functions::{lock_read, new_lock, process_write_critical_section};
use crate::types::RUMHashMap;
use crate::{rumtk_critical_section_write, rumtk_lock_read, rumtk_new_lock};
use clap::builder::TypedValueParser;
use core::hash::Hash;
pub use once_cell::unsync::Lazy;
use std::fmt::Debug;
use std::sync::LazyLock;
pub const DEFAULT_CACHE_PAGE_SIZE: usize = 10;
pub type RUMCache<K, V> = RUMHashMap<K, V>;
pub type LockedCache<K, V> = SafeLock<RUMCache<K, V>>;
pub type LazyRUMCache<K, V> = LazyLock<LockedCache<K, V>>;
pub type RUMCacheValue<V> = AsyncOwnedRwLockReadGuard<V>;
pub type RUMCacheMutValue<V> = AsyncOwnedRwLockWriteGuard<V>;
pub type RUMCacheWriteGuard<K,V> = AsyncOwnedRwLockWriteGuard<RUMCache<K, V>>;
pub const fn new_cache<K, V>() -> LazyRUMCache<K, V>
where
K: Debug,
V: Debug,
{
LazyLock::new(|| {
let cache = RUMCache::<K, V>::with_capacity(DEFAULT_CACHE_PAGE_SIZE);
rumtk_new_lock!(cache)
})
}
pub unsafe fn cache_push<K, V>(
cache: *mut LazyRUMCache<K, V>,
key: &K,
val: V,
)
where
K: Hash + Eq + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
{
rumtk_critical_section_write!((**cache).clone(), |mut guard: RUMCacheWriteGuard<K,V>| {
guard.insert(key.clone(), val.clone());
})
}
pub unsafe fn cache_get<K, V>(
cache: *mut LazyRUMCache<K, V>,
key: &K,
) -> Option<V>
where
K: Hash + Eq + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
{
let guard = rumtk_lock_read!(*cache);
match (*guard).get(key) {
Some(val) => Some(val.clone()),
None => None
}
}
pub unsafe fn cache_get_or_set<K, V, F>(
cache: *mut LazyRUMCache<K, V>,
key: &K,
default_func: F
) -> RUMResult<V>
where
K: Hash + Eq + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
F: Fn() -> RUMResult<V>
{
let val = match cache_get(cache, key) {
Some(val) => val,
None => {
cache_push(cache, key, default_func()?);
cache_get(cache, key).unwrap()
}
};
Ok(val)
}
pub mod cache_macros {
#[macro_export]
macro_rules! rumtk_cache_fetch {
( $cache:expr, $key:expr, $default_func:expr ) => {{
use $crate::cache::{cache_get_or_set};
#[allow(clippy::macro_metavars_in_unsafe)]
unsafe {
cache_get_or_set($cache, $key, $default_func)
}
}};
}
#[macro_export]
macro_rules! rumtk_cache_push {
( $cache:expr, $key:expr, $val:expr ) => {{
use $crate::cache::cache_push;
#[allow(clippy::macro_metavars_in_unsafe)]
unsafe {
cache_push($cache, $key, $val)
}
}};
}
#[macro_export]
macro_rules! rumtk_cache_get {
( $cache:expr, $key:expr ) => {{
use $crate::cache::cache_get;
#[allow(clippy::macro_metavars_in_unsafe)]
unsafe {
cache_get($cache, $key)
}
}};
}
}