1use crate::core::engine::DualCacheCore;
2#[cfg(not(feature = "std"))]
3use crate::componant::qsbr::{ThreadStateNode, pin};
4use crate::componant::config::CachePolicy;
5use core::hash::Hash;
6use no_std_tool::sync::SpinMutex;
7use ::core::sync::atomic::{AtomicUsize, Ordering};
8
9#[cfg(feature = "std")]
10pub struct StaticDualCache<K, V, P: CachePolicy, const T0_CAP: usize, const T1_CAP: usize, const T2_CAP: usize, const TOTAL_CAP: usize> {
11 core: DualCacheCore<K, V, P, T0_CAP, T1_CAP, T2_CAP, TOTAL_CAP>,
12 tls_registry: crate::componant::tls::TlsRegistry<K, V, 64, 4096, 128>,
13 reclaim_lock: SpinMutex<()>,
14 insert_count: AtomicUsize,
15}
16
17#[cfg(feature = "std")]
18impl<K, V, P: CachePolicy, const T0_CAP: usize, const T1_CAP: usize, const T2_CAP: usize, const TOTAL_CAP: usize> StaticDualCache<K, V, P, T0_CAP, T1_CAP, T2_CAP, TOTAL_CAP>
19where
20 K: Clone + Eq + Hash + Send + Sync + 'static,
21 V: Clone + Send + Sync + 'static,
22{
23 pub const fn new(eviction: P::Evict) -> Self {
24 Self {
25 core: DualCacheCore::new(eviction),
26 tls_registry: crate::componant::tls::TlsRegistry::new(),
27 reclaim_lock: SpinMutex::new(()),
28 insert_count: AtomicUsize::new(0),
29 }
30 }
31
32 pub fn get(&self, key: &K) -> Option<V> {
34 thread_local! {
35 static THREAD_HANDLE: std::cell::OnceCell<crate::componant::tls::TlsHandle> = const { std::cell::OnceCell::new() };
36 }
37
38 let node_ptr = THREAD_HANDLE.with(|cell| {
39 cell.get_or_init(|| self.tls_registry.register_thread()).qsbr_node
40 });
41
42 let guard = unsafe { crate::componant::qsbr::Guard::unpinned(node_ptr) };
43 self.core.get(key, &guard, 16).map(|(v_ref, _tier, _hint)| v_ref.clone())
44 }
45
46 pub fn put(&self, key: K, value: V) {
48 thread_local! {
49 static THREAD_HANDLE: std::cell::OnceCell<crate::componant::tls::TlsHandle> = const { std::cell::OnceCell::new() };
50 }
51
52 let node_ptr = THREAD_HANDLE.with(|cell| {
53 cell.get_or_init(|| self.tls_registry.register_thread()).qsbr_node
54 });
55
56 self.core.put(key, value, node_ptr);
57
58 let count = self.insert_count.fetch_add(1, Ordering::Relaxed);
59
60 if count % 1024 == 1023 && self.reclaim_lock.lock().is_ok() {
62 self.core.sync_reclaim();
63 }
64 }
65}
66
67#[cfg(not(feature = "std"))]
68pub struct StaticDualCache<K, V, P: CachePolicy, const T0_CAP: usize, const T1_CAP: usize, const T2_CAP: usize, const TOTAL_CAP: usize> {
69 inner: SpinMutex<(DualCacheCore<K, V, P, T0_CAP, T1_CAP, T2_CAP, TOTAL_CAP>, ThreadStateNode, bool)>,
70 insert_count: AtomicUsize,
71}
72
73#[cfg(not(feature = "std"))]
74impl<K, V, P: CachePolicy, const T0_CAP: usize, const T1_CAP: usize, const T2_CAP: usize, const TOTAL_CAP: usize> StaticDualCache<K, V, P, T0_CAP, T1_CAP, T2_CAP, TOTAL_CAP>
75where
76 K: Clone + Eq + Hash,
77 V: Clone,
78{
79 pub const fn new(eviction: P::Evict) -> Self {
80 Self {
81 inner: SpinMutex::new((DualCacheCore::new(eviction), ThreadStateNode::new(), false)),
82 insert_count: AtomicUsize::new(0),
83 }
84 }
85
86 pub fn get(&self, key: &K) -> Option<V> {
88 let mut inner = match self.inner.lock() {
89 Ok(guard) => guard,
90 Err(_) => return None, };
92 let (engine, qsbr_node, registered) = &mut *inner;
93
94 if !*registered {
95 crate::componant::qsbr::register_node(qsbr_node as *mut _, 0, ::core::ptr::null(), None);
96 *registered = true;
97 }
98
99 let guard = pin(qsbr_node as *mut ThreadStateNode);
100
101 engine.get(key, &guard, 16).map(|(v_ref, _tier, _hint)| v_ref.clone())
104 }
105
106 pub fn put(&self, key: K, value: V) {
108 let mut inner = match self.inner.lock() {
109 Ok(guard) => guard,
110 Err(_) => return, };
112 let (engine, qsbr_node, registered) = &mut *inner;
113
114 if !*registered {
115 crate::componant::qsbr::register_node(qsbr_node as *mut _, 0, ::core::ptr::null(), None);
116 *registered = true;
117 }
118
119 let node_ptr = qsbr_node as *mut ThreadStateNode;
120
121 engine.put(key, value, node_ptr);
122
123 let count = self.insert_count.fetch_add(1, Ordering::Relaxed);
124
125 if count % 1024 == 1023 {
127 engine.sync_reclaim();
128 }
129 }
130}
131
132#[cfg(feature = "std")]
133impl<K, V, P: CachePolicy, const T0_CAP: usize, const T1_CAP: usize, const T2_CAP: usize, const TOTAL_CAP: usize> Default for StaticDualCache<K, V, P, T0_CAP, T1_CAP, T2_CAP, TOTAL_CAP>
134where
135 K: Clone + Eq + Hash + Send + Sync + 'static,
136 V: Clone + Send + Sync + 'static,
137{
138 fn default() -> Self {
139 Self::new(P::Evict::default())
140 }
141}
142
143#[cfg(not(feature = "std"))]
144impl<K, V, P: CachePolicy, const T0_CAP: usize, const T1_CAP: usize, const T2_CAP: usize, const TOTAL_CAP: usize> Default for StaticDualCache<K, V, P, T0_CAP, T1_CAP, T2_CAP, TOTAL_CAP>
145where
146 K: Clone + Eq + Hash,
147 V: Clone,
148{
149 fn default() -> Self {
150 Self::new(P::Evict::default())
151 }
152}
153
154pub type StaticBottomUpCache<K, V> = StaticDualCache<K, V, crate::componant::config::DefaultExponentialPolicy, 64, 4096, 262144, { 64 + 4096 + 262144 }>;