dualcache_ff/static_cache/
static_cache.rs1#[cfg(not(feature = "std"))]
2use alloc::vec::Vec;
3
4use core::hash::{BuildHasher, Hash, Hasher};
5use ahash::RandomState;
6use core::cell::UnsafeCell;
7
8use crate::sync::{Arc, ArcSlice, new_arc_slice};
9use crate::sync::atomic::{AtomicBool, AtomicU32, Ordering};
10use crate::filters::{T1, T2};
11use crate::storage::Cache;
12use crate::cache::WorkerState;
13use crate::core_cache::CoreCache;
14use crate::Config;
15
16pub struct StaticDualCache<K, V, S = RandomState> {
19 pub hasher: S,
20 pub t1: Arc<T1<K, V>>,
21 pub t2: Arc<T2<K, V>>,
22 pub cache: Arc<Cache<K, V>>,
23 pub epoch: Arc<AtomicU32>,
24 pub worker_states: ArcSlice<WorkerState>,
25
26 lock: AtomicBool,
28 core: UnsafeCell<CoreCache<K, V>>,
29}
30
31unsafe impl<K: Send, V: Send, S: Send> Send for StaticDualCache<K, V, S> {}
32unsafe impl<K: Sync, V: Sync, S: Sync> Sync for StaticDualCache<K, V, S> {}
33
34impl<K, V> StaticDualCache<K, V, RandomState>
35where
36 K: Hash + Eq + Send + Sync + Clone + 'static,
37 V: Send + Sync + Clone + 'static,
38{
39 pub fn new(config: Config) -> Self {
40 Self::with_hasher(config, RandomState::new())
41 }
42
43 pub fn new_headless(config: Config) -> (Self, ()) {
44 (Self::new(config), ())
45 }
46}
47
48impl<K, V, S> StaticDualCache<K, V, S>
49where
50 K: Hash + Eq + Send + Sync + Clone + 'static,
51 V: Send + Sync + Clone + 'static,
52 S: BuildHasher + Clone + Send + 'static,
53{
54 pub fn with_hasher(config: Config, hasher: S) -> Self {
55 let t1 = Arc::new(T1::new(config.capacity));
56 let t2 = Arc::new(T2::new(config.capacity));
57 let cache = Arc::new(Cache::new(config.capacity));
58 let epoch = Arc::new(AtomicU32::new(0));
59 let is_cold_start = Arc::new(AtomicBool::new(true));
60
61 let mut states = Vec::with_capacity(config.threads);
62 for _ in 0..config.threads {
63 states.push(WorkerState::new());
64 }
65 let worker_states = new_arc_slice(states);
66
67 let core = CoreCache::new(
68 config.capacity,
69 t1.clone(),
70 t2.clone(),
71 cache.clone(),
72 epoch.clone(),
73 config.duration,
74 worker_states.clone(),
75 is_cold_start,
76 );
77
78 Self {
79 hasher,
80 t1,
81 t2,
82 cache,
83 epoch,
84 worker_states,
85 lock: AtomicBool::new(false),
86 core: UnsafeCell::new(core),
87 }
88 }
89
90 #[inline(always)]
91 fn acquire_lock(&self) -> &mut CoreCache<K, V> {
92 while self.lock.compare_exchange_weak(
93 false,
94 true,
95 Ordering::Acquire,
96 Ordering::Relaxed,
97 ).is_err() {
98 core::hint::spin_loop();
99 }
100 unsafe { &mut *self.core.get() }
101 }
102
103 #[inline(always)]
104 fn release_lock(&self) {
105 self.lock.store(false, Ordering::Release);
106 }
107
108 pub fn get(&self, key: &K) -> Option<V> {
110 let current_epoch = self.epoch.load(Ordering::Relaxed);
111 let mut s = self.hasher.build_hasher();
112 key.hash(&mut s);
113 let hash = s.finish();
114 let tag = (hash >> 48) as u16;
115
116 let res = if let Some(node) = self.t1.get_node(hash) {
117 if node.key == *key && (node.expire_at == 0 || node.expire_at >= current_epoch) {
118 Some(node.value.clone())
119 } else {
120 None
121 }
122 } else if let Some(node) = self.t2.get_node(hash) {
123 if node.key == *key && (node.expire_at == 0 || node.expire_at >= current_epoch) {
124 Some(node.value.clone())
125 } else {
126 None
127 }
128 } else {
129 let mut val = None;
130 if let Some(global_idx) = self.cache.index_probe(hash, tag) {
131 if let Some(v) = self.cache.node_get_full(global_idx, key, current_epoch) {
132 val = Some(v);
133 }
134 }
135 val
136 };
137
138 if res.is_some() {
140 if let Some(global_idx) = self.cache.index_probe(hash, tag) {
141 let core = self.acquire_lock();
142 core.process_hits(&[global_idx]);
143 self.release_lock();
144 }
145 }
146
147 res
148 }
149
150 pub fn insert(&self, key: K, value: V) {
152 let mut s = self.hasher.build_hasher();
153 key.hash(&mut s);
154 let hash = s.finish();
155
156 let core = self.acquire_lock();
157 core.handle_admission_insert(key, value, hash, false);
158 self.release_lock();
159 }
160
161 pub fn insert_t1(&self, key: K, value: V) {
162 let mut s = self.hasher.build_hasher();
163 key.hash(&mut s);
164 let hash = s.finish();
165
166 let core = self.acquire_lock();
167 core.handle_insert_t1(key, value, hash);
168 self.release_lock();
169 }
170
171 pub fn remove(&self, key: &K) {
172 let mut s = self.hasher.build_hasher();
173 key.hash(&mut s);
174 let hash = s.finish();
175
176 let core = self.acquire_lock();
177 core.handle_remove(key.clone(), hash); self.release_lock();
179 }
180
181 pub fn maintenance(&self) {
182 let core = self.acquire_lock();
183 core.maintenance();
184 self.release_lock();
185 }
186
187 pub fn clear(&self) {
188 let core = self.acquire_lock();
189 core.handle_clear();
190 self.release_lock();
191 }
192}