pub(crate) mod get_or_insert;
pub(crate) use get_or_insert::{GetOrInsertFuture, GetOrTryInsertFuture};
pub(crate) mod get_or_insert_race;
pub(crate) use get_or_insert_race::{GetOrInsertRace, GetOrTryInsertRace};
mod no_policy;
pub use no_policy::NoPolicy;
use crate::map::LightMap;
use crate::policy::{NoopPolicy, Policy};
pub use hashbrown::hash_map::DefaultHashBuilder;
use std::future::Future;
use std::hash::{BuildHasher, Hash};
use std::sync::Arc;
pub struct LightCache<K, V, S = DefaultHashBuilder, P = NoopPolicy> {
pub(crate) inner: Arc<LightCacheInner<K, V, S, P>>,
}
impl<K, V, S, P> Clone for LightCache<K, V, S, P> {
fn clone(&self) -> Self {
LightCache {
inner: self.inner.clone(),
}
}
}
pub(crate) struct LightCacheInner<K, V, S = DefaultHashBuilder, P = NoopPolicy> {
pub(crate) policy: P,
map: LightMap<K, V, S>,
}
impl<K, V> LightCache<K, V> {
pub fn new() -> Self {
LightCache {
inner: Arc::new(LightCacheInner {
map: LightMap::new(),
policy: NoopPolicy,
}),
}
}
pub fn with_capacity(capacity: usize) -> Self {
LightCache {
inner: Arc::new(LightCacheInner {
map: LightMap::with_capacity(capacity),
policy: NoopPolicy,
}),
}
}
}
impl<K, V, S: BuildHasher, P> LightCache<K, V, S, P> {
pub fn from_parts(policy: P, hasher: S) -> Self {
LightCache {
inner: Arc::new(LightCacheInner {
map: LightMap::with_hasher(hasher),
policy,
}),
}
}
pub fn from_parts_with_capacity(policy: P, hasher: S, capacity: usize) -> Self {
LightCache {
inner: Arc::new(LightCacheInner {
map: LightMap::with_capacity_and_hasher(capacity, hasher),
policy,
}),
}
}
}
impl<K, V, S, P> LightCache<K, V, S, P> {
pub fn len(&self) -> usize {
self.inner.map.len()
}
}
impl<K, V, S, P> LightCache<K, V, S, P>
where
K: Eq + Hash + Copy,
V: Clone + Sync,
S: BuildHasher,
P: Policy<K, V>,
{
pub async fn get_or_insert<F, Fut>(&self, key: K, init: F) -> V
where
F: FnOnce() -> Fut,
Fut: Future<Output = V>,
{
if let Some(value) = self.get(&key) {
return value;
}
self.get_or_insert_inner(key, init).await
}
pub async fn get_or_try_insert<F, Fut, Err>(
&self,
key: K,
init: F,
) -> Result<V, Err>
where
F: FnOnce() -> Fut,
Fut: std::future::Future<Output = Result<V, Err>>,
{
if let Some(value) = self.get(&key) {
return Ok(value);
}
self.get_or_try_insert_inner(key, init).await
}
pub async fn get_or_insert_race<F, Fut>(&self, key: K, init: F) -> V
where
F: FnOnce() -> Fut,
Fut: Future<Output = V>,
{
if let Some(val) = self.get(&key) {
return val;
}
self.get_or_insert_race_inner(key, init).await
}
pub async fn get_or_try_insert_race<F, Fut, E>(&self, key: K, init: F) -> Result<V, E>
where
F: FnOnce() -> Fut,
Fut: Future<Output = Result<V, E>>,
{
if let Some(val) = self.get(&key) {
return Ok(val);
}
self.get_or_try_insert_race_inner(key, init).await
}
#[inline]
pub fn insert(&self, key: K, value: V) -> Option<V> {
self.policy().insert(key, value, self)
}
#[inline]
pub fn get(&self, key: &K) -> Option<V> {
self.policy().get(key, self)
}
#[inline]
pub fn remove(&self, key: &K) -> Option<V> {
self.policy().remove(key, self)
}
#[inline]
pub fn prune(&self) {
self.policy().prune(self)
}
}
impl<K, V, S, P> LightCache<K, V, S, P>
where
K: Eq + Hash + Copy,
V: Clone + Sync,
S: BuildHasher,
P: Policy<K, V>,
{
#[inline]
fn get_or_insert_inner<F, Fut>(&self, key: K, init: F) -> GetOrInsertFuture<K, V, S, P, F, Fut>
where
F: FnOnce() -> Fut,
Fut: Future<Output = V>,
{
let (hash, shard) = self.inner.map.shard(&key).unwrap();
GetOrInsertFuture::new(self, shard, hash, key, init)
}
#[inline]
fn get_or_try_insert_inner<F, Fut, E>(
&self,
key: K,
init: F,
) -> GetOrTryInsertFuture<K, V, S, P, F, Fut>
where
F: FnOnce() -> Fut,
Fut: Future<Output = Result<V, E>>,
{
let (hash, shard) = self.inner.map.shard(&key).unwrap();
GetOrTryInsertFuture::new(self, shard, hash, key, init)
}
#[inline]
fn get_or_insert_race_inner<F, Fut>(&self, key: K, init: F) -> GetOrInsertRace<K, V, S, P, Fut>
where
F: FnOnce() -> Fut,
Fut: Future<Output = V>,
{
let (hash, shard) = self.inner.map.shard(&key).unwrap();
GetOrInsertRace::new(self, shard, hash, key, init())
}
#[inline]
fn get_or_try_insert_race_inner<F, Fut, E>(
&self,
key: K,
init: F,
) -> GetOrTryInsertRace<K, V, S, P, Fut>
where
F: FnOnce() -> Fut,
Fut: Future<Output = Result<V, E>>,
{
let (hash, shard) = self.inner.map.shard(&key).unwrap();
GetOrTryInsertRace::new(self, shard, hash, key, init())
}
}
impl<K, V, S, P> LightCache<K, V, S, P>
where
K: Eq + Hash + Copy,
V: Clone + Sync,
S: BuildHasher,
{
#[inline]
pub(crate) fn get_no_policy(&self, key: &K) -> Option<V> {
self.inner.map.get(key)
}
#[inline]
pub(crate) fn insert_no_policy(&self, key: K, value: V) -> Option<V> {
self.inner.map.insert(key, value)
}
#[inline]
pub(crate) fn remove_no_policy(&self, key: &K) -> Option<V> {
self.inner.map.remove(key)
}
#[inline]
pub(crate) fn policy(&self) -> &P {
&self.inner.policy
}
}