foyer_memory/eviction/
fifo.rs1use std::{mem::offset_of, sync::Arc};
16
17use foyer_common::{
18 code::{Key, Value},
19 properties::Properties,
20};
21use intrusive_collections::{intrusive_adapter, LinkedList, LinkedListAtomicLink};
22use serde::{Deserialize, Serialize};
23
24use super::{Eviction, Op};
25use crate::{error::Result, record::Record};
26
27#[derive(Debug, Clone, Default, Serialize, Deserialize)]
29pub struct FifoConfig {}
30
31#[derive(Debug, Default)]
33pub struct FifoState {
34 link: LinkedListAtomicLink,
35}
36
37intrusive_adapter! { Adapter<K, V, P> = Arc<Record<Fifo<K, V, P>>>: Record<Fifo<K, V, P>> { ?offset = Record::<Fifo<K, V, P>>::STATE_OFFSET + offset_of!(FifoState, link) => LinkedListAtomicLink } where K: Key, V: Value, P: Properties }
38
39pub struct Fifo<K, V, P>
40where
41 K: Key,
42 V: Value,
43 P: Properties,
44{
45 queue: LinkedList<Adapter<K, V, P>>,
46}
47
48impl<K, V, P> Eviction for Fifo<K, V, P>
49where
50 K: Key,
51 V: Value,
52 P: Properties,
53{
54 type Config = FifoConfig;
55 type Key = K;
56 type Value = V;
57 type Properties = P;
58 type State = FifoState;
59
60 fn new(_capacity: usize, _config: &Self::Config) -> Self
61 where
62 Self: Sized,
63 {
64 Self {
65 queue: LinkedList::new(Adapter::new()),
66 }
67 }
68
69 fn update(&mut self, _: usize, _: Option<&Self::Config>) -> Result<()> {
70 Ok(())
71 }
72
73 fn push(&mut self, record: Arc<Record<Self>>) {
74 record.set_in_eviction(true);
75 self.queue.push_back(record);
76 }
77
78 fn pop(&mut self) -> Option<Arc<Record<Self>>> {
79 self.queue.pop_front().inspect(|record| record.set_in_eviction(false))
80 }
81
82 fn remove(&mut self, record: &Arc<Record<Self>>) {
83 unsafe { self.queue.remove_from_ptr(Arc::as_ptr(record)) };
84 record.set_in_eviction(false);
85 }
86
87 fn acquire() -> Op<Self> {
88 Op::noop()
89 }
90
91 fn release() -> Op<Self> {
92 Op::noop()
93 }
94}
95
96#[cfg(test)]
97pub mod tests {
98
99 use itertools::Itertools;
100
101 use super::*;
102 use crate::{
103 eviction::test_utils::{assert_ptr_eq, assert_ptr_vec_eq, Dump, TestProperties},
104 record::Data,
105 };
106
107 impl<K, V> Dump for Fifo<K, V, TestProperties>
108 where
109 K: Key + Clone,
110 V: Value + Clone,
111 {
112 type Output = Vec<Arc<Record<Self>>>;
113 fn dump(&self) -> Self::Output {
114 let mut res = vec![];
115 let mut cursor = self.queue.cursor();
116 loop {
117 cursor.move_next();
118 match cursor.clone_pointer() {
119 Some(record) => res.push(record),
120 None => break,
121 }
122 }
123 res
124 }
125 }
126
127 type TestFifo = Fifo<u64, u64, TestProperties>;
128
129 #[test]
130 fn test_fifo() {
131 let rs = (0..8)
132 .map(|i| {
133 Arc::new(Record::new(Data {
134 key: i,
135 value: i,
136 properties: TestProperties::default(),
137 hash: i,
138 weight: 1,
139 }))
140 })
141 .collect_vec();
142 let r = |i: usize| rs[i].clone();
143
144 let mut fifo = TestFifo::new(100, &FifoConfig {});
145
146 fifo.push(r(0));
148 fifo.push(r(1));
149 fifo.push(r(2));
150 fifo.push(r(3));
151
152 let r0 = fifo.pop().unwrap();
154 let r1 = fifo.pop().unwrap();
155 assert_ptr_eq(&rs[0], &r0);
156 assert_ptr_eq(&rs[1], &r1);
157
158 fifo.push(r(4));
160 fifo.push(r(5));
161 fifo.push(r(6));
162
163 fifo.remove(&rs[3]);
165 fifo.remove(&rs[4]);
166 fifo.remove(&rs[5]);
167
168 assert_ptr_vec_eq(fifo.dump(), vec![r(2), r(6)]);
169
170 fifo.clear();
171
172 assert_ptr_vec_eq(fifo.dump(), vec![]);
173 }
174}