use crossbeam_channel::Sender;
use futures_util::future::{BoxFuture, Shared};
use std::{future::Future, hash::Hash, sync::Arc};
use crate::common::{concurrent::WriteOp, time::Instant};
mod base_cache;
mod builder;
mod cache;
mod entry_selector;
mod housekeeper;
mod invalidator;
mod key_lock;
mod notifier;
mod value_initializer;
pub use {
builder::CacheBuilder,
cache::Cache,
entry_selector::{OwnedKeyEntrySelector, RefKeyEntrySelector},
};
pub type PredicateId = String;
pub(crate) type PredicateIdStr<'a> = &'a str;
pub(crate) struct OptionallyNone;
pub(crate) struct ComputeNone;
impl<T: ?Sized> FutureExt for T where T: Future {}
pub trait FutureExt: Future {
fn boxed<'a, T>(self) -> BoxFuture<'a, T>
where
Self: Future<Output = T> + Sized + Send + 'a,
{
Box::pin(self)
}
}
pub struct Iter<'i, K, V>(crate::sync_base::iter::Iter<'i, K, V>);
impl<'i, K, V> Iter<'i, K, V> {
pub(crate) fn new(inner: crate::sync_base::iter::Iter<'i, K, V>) -> Self {
Self(inner)
}
}
impl<'i, K, V> Iterator for Iter<'i, K, V>
where
K: Eq + Hash + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
{
type Item = (Arc<K>, V);
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
pub(crate) enum InterruptedOp<K, V> {
CallEvictionListener {
ts: Instant,
future: Shared<BoxFuture<'static, ()>>,
op: WriteOp<K, V>,
},
SendWriteOp {
ts: Instant,
op: WriteOp<K, V>,
},
}
struct CancelGuard<'a, K, V> {
interrupted_op_ch: &'a Sender<InterruptedOp<K, V>>,
ts: Instant,
future: Option<Shared<BoxFuture<'static, ()>>>,
op: Option<WriteOp<K, V>>,
}
impl<'a, K, V> CancelGuard<'a, K, V> {
fn new(interrupted_op_ch: &'a Sender<InterruptedOp<K, V>>, ts: Instant) -> Self {
Self {
interrupted_op_ch,
ts,
future: None,
op: None,
}
}
fn set_future_and_op(&mut self, future: Shared<BoxFuture<'static, ()>>, op: WriteOp<K, V>) {
self.future = Some(future);
self.op = Some(op);
}
fn set_op(&mut self, op: WriteOp<K, V>) {
self.op = Some(op);
}
fn unset_future(&mut self) {
self.future = None;
}
fn clear(&mut self) {
self.future = None;
self.op = None;
}
}
impl<'a, K, V> Drop for CancelGuard<'a, K, V> {
fn drop(&mut self) {
let interrupted_op = match (self.future.take(), self.op.take()) {
(Some(future), Some(op)) => InterruptedOp::CallEvictionListener {
ts: self.ts,
future,
op,
},
(None, Some(op)) => InterruptedOp::SendWriteOp { ts: self.ts, op },
_ => return,
};
self.interrupted_op_ch
.send(interrupted_op)
.expect("Failed to send a pending op");
}
}