Skip to content

Commit

Permalink
refactor: loose bound of in-memory eviction related traits (#334)
Browse files Browse the repository at this point in the history
* refactor: remove Handle bound from Eviction

Signed-off-by: MrCroxx <[email protected]>

* refactor: loose bound of in-memory eviction related traits

Signed-off-by: MrCroxx <[email protected]>

---------

Signed-off-by: MrCroxx <[email protected]>
  • Loading branch information
MrCroxx authored Apr 14, 2024
1 parent e3051f2 commit 7bc5954
Show file tree
Hide file tree
Showing 10 changed files with 327 additions and 435 deletions.
35 changes: 19 additions & 16 deletions foyer-memory/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,37 +39,40 @@ use crate::{
};

pub type FifoCache<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCache<K, V, Fifo<K, V>, HashTableIndexer<K, FifoHandle<K, V>>, L, S>;
pub type FifoCacheConfig<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> = CacheConfig<Fifo<K, V>, L, S>;
GenericCache<K, V, Fifo<(K, V)>, HashTableIndexer<K, FifoHandle<(K, V)>>, L, S>;
pub type FifoCacheConfig<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
CacheConfig<K, V, Fifo<(K, V)>, L, S>;
pub type FifoCacheEntry<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCacheEntry<K, V, Fifo<K, V>, HashTableIndexer<K, FifoHandle<K, V>>, L, S>;
GenericCacheEntry<K, V, Fifo<(K, V)>, HashTableIndexer<K, FifoHandle<(K, V)>>, L, S>;
pub type FifoEntry<K, V, ER, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericEntry<K, V, Fifo<K, V>, HashTableIndexer<K, FifoHandle<K, V>>, L, S, ER>;
GenericEntry<K, V, Fifo<(K, V)>, HashTableIndexer<K, FifoHandle<(K, V)>>, L, S, ER>;

pub type LruCache<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCache<K, V, Lru<K, V>, HashTableIndexer<K, LruHandle<K, V>>, L, S>;
pub type LruCacheConfig<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> = CacheConfig<Lru<K, V>, L, S>;
GenericCache<K, V, Lru<(K, V)>, HashTableIndexer<K, LruHandle<(K, V)>>, L, S>;
pub type LruCacheConfig<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
CacheConfig<K, V, Lru<(K, V)>, L, S>;
pub type LruCacheEntry<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCacheEntry<K, V, Lru<K, V>, HashTableIndexer<K, LruHandle<K, V>>, L, S>;
GenericCacheEntry<K, V, Lru<(K, V)>, HashTableIndexer<K, LruHandle<(K, V)>>, L, S>;
pub type LruEntry<K, V, ER, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericEntry<K, V, Lru<K, V>, HashTableIndexer<K, LruHandle<K, V>>, L, S, ER>;
GenericEntry<K, V, Lru<(K, V)>, HashTableIndexer<K, LruHandle<(K, V)>>, L, S, ER>;

pub type LfuCache<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCache<K, V, Lfu<K, V>, HashTableIndexer<K, LfuHandle<K, V>>, L, S>;
pub type LfuCacheConfig<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> = CacheConfig<Lfu<K, V>, L, S>;
GenericCache<K, V, Lfu<(K, V)>, HashTableIndexer<K, LfuHandle<(K, V)>>, L, S>;
pub type LfuCacheConfig<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
CacheConfig<K, V, Lfu<(K, V)>, L, S>;
pub type LfuCacheEntry<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCacheEntry<K, V, Lfu<K, V>, HashTableIndexer<K, LfuHandle<K, V>>, L, S>;
GenericCacheEntry<K, V, Lfu<(K, V)>, HashTableIndexer<K, LfuHandle<(K, V)>>, L, S>;
pub type LfuEntry<K, V, ER, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericEntry<K, V, Lfu<K, V>, HashTableIndexer<K, LfuHandle<K, V>>, L, S, ER>;
GenericEntry<K, V, Lfu<(K, V)>, HashTableIndexer<K, LfuHandle<(K, V)>>, L, S, ER>;

pub type S3FifoCache<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCache<K, V, S3Fifo<K, V>, HashTableIndexer<K, S3FifoHandle<K, V>>, L, S>;
GenericCache<K, V, S3Fifo<(K, V)>, HashTableIndexer<K, S3FifoHandle<(K, V)>>, L, S>;
pub type S3FifoCacheConfig<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
CacheConfig<S3Fifo<K, V>, L, S>;
CacheConfig<K, V, S3Fifo<(K, V)>, L, S>;
pub type S3FifoCacheEntry<K, V, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericCacheEntry<K, V, S3Fifo<K, V>, HashTableIndexer<K, S3FifoHandle<K, V>>, L, S>;
GenericCacheEntry<K, V, S3Fifo<(K, V)>, HashTableIndexer<K, S3FifoHandle<(K, V)>>, L, S>;
pub type S3FifoEntry<K, V, ER, L = DefaultCacheEventListener<K, V>, S = RandomState> =
GenericEntry<K, V, S3Fifo<K, V>, HashTableIndexer<K, S3FifoHandle<K, V>>, L, S, ER>;
GenericEntry<K, V, S3Fifo<(K, V)>, HashTableIndexer<K, S3FifoHandle<(K, V)>>, L, S, ER>;

pub enum CacheEntry<K, V, L, S = RandomState>
where
Expand Down
91 changes: 37 additions & 54 deletions foyer-memory/src/eviction/fifo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use foyer_intrusive::{
use crate::{
eviction::Eviction,
handle::{BaseHandle, Handle},
CacheContext, Key, Value,
CacheContext,
};

#[derive(Debug, Clone)]
Expand All @@ -40,34 +40,30 @@ impl From<FifoContext> for CacheContext {
}
}

pub struct FifoHandle<K, V>
pub struct FifoHandle<T>
where
K: Key,
V: Value,
T: Send + Sync + 'static,
{
link: DlistLink,
base: BaseHandle<K, V, FifoContext>,
base: BaseHandle<T, FifoContext>,
}

impl<K, V> Debug for FifoHandle<K, V>
impl<T> Debug for FifoHandle<T>
where
K: Key,
V: Value,
T: Send + Sync + 'static,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FifoHandle").finish()
}
}

intrusive_adapter! { FifoHandleDlistAdapter<K, V> = NonNull<FifoHandle<K, V>>: FifoHandle<K, V> { link: DlistLink } where K: Key, V: Value }
intrusive_adapter! { FifoHandleDlistAdapter<T> = NonNull<FifoHandle<T>>: FifoHandle<T> { link: DlistLink } where T: Send + Sync + 'static }

impl<K, V> Handle for FifoHandle<K, V>
impl<T> Handle for FifoHandle<T>
where
K: Key,
V: Value,
T: Send + Sync + 'static,
{
type Key = K;
type Value = V;
type Data = T;
type Context = FifoContext;

fn new() -> Self {
Expand All @@ -77,36 +73,34 @@ where
}
}

fn init(&mut self, hash: u64, key: Self::Key, value: Self::Value, charge: usize, context: Self::Context) {
self.base.init(hash, key, value, charge, context);
fn init(&mut self, hash: u64, data: Self::Data, charge: usize, context: Self::Context) {
self.base.init(hash, data, charge, context);
}

fn base(&self) -> &BaseHandle<Self::Key, Self::Value, Self::Context> {
fn base(&self) -> &BaseHandle<Self::Data, Self::Context> {
&self.base
}

fn base_mut(&mut self) -> &mut BaseHandle<Self::Key, Self::Value, Self::Context> {
fn base_mut(&mut self) -> &mut BaseHandle<Self::Data, Self::Context> {
&mut self.base
}
}

#[derive(Debug, Clone)]
pub struct FifoConfig {}

pub struct Fifo<K, V>
pub struct Fifo<T>
where
K: Key,
V: Value,
T: Send + Sync + 'static,
{
queue: Dlist<FifoHandleDlistAdapter<K, V>>,
queue: Dlist<FifoHandleDlistAdapter<T>>,
}

impl<K, V> Eviction for Fifo<K, V>
impl<T> Eviction for Fifo<T>
where
K: Key,
V: Value,
T: Send + Sync + 'static,
{
type Handle = FifoHandle<K, V>;
type Item = FifoHandle<T>;
type Config = FifoConfig;

unsafe fn new(_capacity: usize, _config: &Self::Config) -> Self
Expand All @@ -116,29 +110,29 @@ where
Self { queue: Dlist::new() }
}

unsafe fn push(&mut self, mut ptr: NonNull<Self::Handle>) {
unsafe fn push(&mut self, mut ptr: NonNull<Self::Item>) {
self.queue.push_back(ptr);
ptr.as_mut().base_mut().set_in_eviction(true);
}

unsafe fn pop(&mut self) -> Option<NonNull<Self::Handle>> {
unsafe fn pop(&mut self) -> Option<NonNull<Self::Item>> {
self.queue.pop_front().map(|mut ptr| {
ptr.as_mut().base_mut().set_in_eviction(false);
ptr
})
}

unsafe fn reinsert(&mut self, _: NonNull<Self::Handle>) {}
unsafe fn reinsert(&mut self, _: NonNull<Self::Item>) {}

unsafe fn access(&mut self, _: NonNull<Self::Handle>) {}
unsafe fn access(&mut self, _: NonNull<Self::Item>) {}

unsafe fn remove(&mut self, mut ptr: NonNull<Self::Handle>) {
unsafe fn remove(&mut self, mut ptr: NonNull<Self::Item>) {
let p = self.queue.iter_mut_from_raw(ptr.as_mut().link.raw()).remove().unwrap();
assert_eq!(p, ptr);
ptr.as_mut().base_mut().set_in_eviction(false);
}

unsafe fn clear(&mut self) -> Vec<NonNull<Self::Handle>> {
unsafe fn clear(&mut self) -> Vec<NonNull<Self::Item>> {
let mut res = Vec::with_capacity(self.len());
while let Some(mut ptr) = self.queue.pop_front() {
ptr.as_mut().base_mut().set_in_eviction(false);
Expand All @@ -156,18 +150,8 @@ where
}
}

unsafe impl<K, V> Send for Fifo<K, V>
where
K: Key,
V: Value,
{
}
unsafe impl<K, V> Sync for Fifo<K, V>
where
K: Key,
V: Value,
{
}
unsafe impl<T> Send for Fifo<T> where T: Send + Sync + 'static {}
unsafe impl<T> Sync for Fifo<T> where T: Send + Sync + 'static {}

#[cfg(test)]
pub mod tests {
Expand All @@ -177,25 +161,24 @@ pub mod tests {
use super::*;
use crate::eviction::test_utils::TestEviction;

impl<K, V> TestEviction for Fifo<K, V>
impl<T> TestEviction for Fifo<T>
where
K: Key + Clone,
V: Value + Clone,
T: Send + Sync + 'static + Clone,
{
fn dump(&self) -> Vec<(<Self::Handle as Handle>::Key, <Self::Handle as Handle>::Value)> {
fn dump(&self) -> Vec<T> {
self.queue
.iter()
.map(|handle| (handle.base().key().clone(), handle.base().value().clone()))
.map(|handle| handle.base().data_unwrap_unchecked().clone())
.collect_vec()
}
}

type TestFifoHandle = FifoHandle<u64, u64>;
type TestFifo = Fifo<u64, u64>;
type TestFifoHandle = FifoHandle<u64>;
type TestFifo = Fifo<u64>;

unsafe fn new_test_fifo_handle_ptr(key: u64, value: u64) -> NonNull<TestFifoHandle> {
unsafe fn new_test_fifo_handle_ptr(data: u64) -> NonNull<TestFifoHandle> {
let mut handle = Box::new(TestFifoHandle::new());
handle.init(0, key, value, 1, FifoContext);
handle.init(0, data, 1, FifoContext);
NonNull::new_unchecked(Box::into_raw(handle))
}

Expand All @@ -206,7 +189,7 @@ pub mod tests {
#[test]
fn test_fifo() {
unsafe {
let ptrs = (0..8).map(|i| new_test_fifo_handle_ptr(i, i)).collect_vec();
let ptrs = (0..8).map(|i| new_test_fifo_handle_ptr(i)).collect_vec();

let mut fifo = TestFifo::new(100, &FifoConfig {});

Expand Down
Loading

0 comments on commit 7bc5954

Please sign in to comment.